diff --git a/config/dev/application-common.yml b/config/dev/application-common.yml index b54f4e42..07b11bc2 100644 --- a/config/dev/application-common.yml +++ b/config/dev/application-common.yml @@ -88,11 +88,18 @@ spring: cloud: # sentinel 配置 sentinel: + # sentinel 开关 + enabled: true # 取消控制台懒加载 eager: true transport: - # 控制台地址 - dashboard: localhost:8718 + # dashboard控制台服务名 用于服务发现 + # 如无此配置将默认使用下方 dashboard 配置直接注册 + server-name: ruoyi-sentinel-dashboard + # 客户端指定注册的ip 用于多网卡ip不稳点使用 + # client-ip: + # 控制台地址 从1.3.0开始使用 server-name 注册 + # dashboard: localhost:8718 # redis通用配置 子服务可以自行配置进行覆盖 redis: diff --git a/ruoyi-auth/pom.xml b/ruoyi-auth/pom.xml index 1ccfb14d..abbac6fe 100644 --- a/ruoyi-auth/pom.xml +++ b/ruoyi-auth/pom.xml @@ -28,18 +28,17 @@ spring-cloud-starter-alibaba-nacos-config - - - com.alibaba.cloud - spring-cloud-starter-alibaba-sentinel - - org.springframework.boot spring-boot-starter-actuator + + com.ruoyi + ruoyi-common-sentinel + + com.ruoyi diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml index c5909b86..bf30ea08 100644 --- a/ruoyi-common/pom.xml +++ b/ruoyi-common/pom.xml @@ -31,6 +31,7 @@ ruoyi-common-sms ruoyi-common-logstash ruoyi-common-elasticsearch + ruoyi-common-sentinel ruoyi-common diff --git a/ruoyi-common/ruoyi-common-bom/pom.xml b/ruoyi-common/ruoyi-common-bom/pom.xml index ca97d4f7..1f260030 100644 --- a/ruoyi-common/ruoyi-common-bom/pom.xml +++ b/ruoyi-common/ruoyi-common-bom/pom.xml @@ -144,6 +144,11 @@ ${project.version} + + com.ruoyi + ruoyi-common-sentinel + ${project.version} + diff --git a/ruoyi-common/ruoyi-common-dubbo/pom.xml b/ruoyi-common/ruoyi-common-dubbo/pom.xml index 31a7a297..63b8572d 100644 --- a/ruoyi-common/ruoyi-common-dubbo/pom.xml +++ b/ruoyi-common/ruoyi-common-dubbo/pom.xml @@ -36,11 +36,6 @@ dubbo-spring-boot-actuator - - com.alibaba.csp - sentinel-apache-dubbo3-adapter - - org.projectlombok lombok diff --git a/ruoyi-common/ruoyi-common-sentinel/pom.xml b/ruoyi-common/ruoyi-common-sentinel/pom.xml new file mode 100644 index 00000000..14b4adeb --- /dev/null +++ b/ruoyi-common/ruoyi-common-sentinel/pom.xml @@ -0,0 +1,50 @@ + + + + com.ruoyi + ruoyi-common + 1.2.0 + + 4.0.0 + + ruoyi-common-sentinel + + + ruoyi-common-sentinel 限流模块 + + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-sentinel + + + + com.alibaba.csp + sentinel-datasource-nacos + + + com.alibaba.csp + sentinel-apache-dubbo3-adapter + + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + true + + + + com.ruoyi + ruoyi-common-core + + + + org.springframework.boot + spring-boot-autoconfigure + + + + diff --git a/ruoyi-common/ruoyi-common-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/SentinelAutoConfiguration.java b/ruoyi-common/ruoyi-common-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/SentinelAutoConfiguration.java new file mode 100644 index 00000000..5caecafa --- /dev/null +++ b/ruoyi-common/ruoyi-common-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/SentinelAutoConfiguration.java @@ -0,0 +1,265 @@ +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.sentinel.custom; + +import com.alibaba.cloud.commons.lang.StringUtils; +import com.alibaba.cloud.sentinel.SentinelProperties; +import com.alibaba.cloud.sentinel.datasource.converter.JsonConverter; +import com.alibaba.cloud.sentinel.datasource.converter.XmlConverter; +import com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect; +import com.alibaba.csp.sentinel.config.SentinelConfig; +import com.alibaba.csp.sentinel.init.InitExecutor; +import com.alibaba.csp.sentinel.log.LogBase; +import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule; +import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; +import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; +import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule; +import com.alibaba.csp.sentinel.slots.system.SystemRule; +import com.alibaba.csp.sentinel.transport.config.TransportConfig; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.xml.XmlMapper; +import com.ruoyi.common.core.utils.StreamUtils; +import com.ruoyi.common.sentinel.config.properties.SentinelCustomProperties; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.client.discovery.DiscoveryClient; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; + +import javax.annotation.PostConstruct; +import java.util.List; + +import static com.alibaba.cloud.sentinel.SentinelConstants.BLOCK_PAGE_URL_CONF_KEY; +import static com.alibaba.csp.sentinel.config.SentinelConfig.setConfig; + +/** + * 改造sentinel自动配置 支持服务名注册 + * + * @author Lion Li + * + * @author xiaojing + * @author jiashuai.xie + * @author Jim + */ +@Configuration(proxyBeanMethods = false) +@ConditionalOnProperty(name = "spring.cloud.sentinel.enabled", matchIfMissing = true) +@EnableConfigurationProperties({SentinelProperties.class, SentinelCustomProperties.class}) +public class SentinelAutoConfiguration { + + @Value("${project.name:${spring.application.name:}}") + private String projectName; + + @Autowired + private SentinelProperties properties; + @Autowired + private SentinelCustomProperties customProperties; + @Autowired + private DiscoveryClient discoveryClient; + + @PostConstruct + private void init() { + if (StringUtils.isEmpty(System.getProperty(LogBase.LOG_DIR)) + && StringUtils.isNotBlank(properties.getLog().getDir())) { + System.setProperty(LogBase.LOG_DIR, properties.getLog().getDir()); + } + if (StringUtils.isEmpty(System.getProperty(LogBase.LOG_NAME_USE_PID)) + && properties.getLog().isSwitchPid()) { + System.setProperty(LogBase.LOG_NAME_USE_PID, + String.valueOf(properties.getLog().isSwitchPid())); + } + if (StringUtils.isEmpty(System.getProperty(SentinelConfig.APP_NAME_PROP_KEY)) + && StringUtils.isNotBlank(projectName)) { + System.setProperty(SentinelConfig.APP_NAME_PROP_KEY, projectName); + } + if (StringUtils.isEmpty(System.getProperty(TransportConfig.SERVER_PORT)) + && StringUtils.isNotBlank(properties.getTransport().getPort())) { + System.setProperty(TransportConfig.SERVER_PORT, + properties.getTransport().getPort()); + } + + if (StringUtils.isNotBlank(customProperties.getServerName())) { + List instances = discoveryClient.getInstances(customProperties.getServerName()); + String serverList = StreamUtils.join(instances, instance -> + String.format("http://%s:%s", instance.getHost(), instance.getPort())); + System.setProperty(TransportConfig.CONSOLE_SERVER, serverList); + } else { + if (StringUtils.isEmpty(System.getProperty(TransportConfig.CONSOLE_SERVER)) + && StringUtils.isNotBlank(properties.getTransport().getDashboard())) { + System.setProperty(TransportConfig.CONSOLE_SERVER, + properties.getTransport().getDashboard()); + } + } + + if (StringUtils.isEmpty(System.getProperty(TransportConfig.HEARTBEAT_INTERVAL_MS)) + && StringUtils + .isNotBlank(properties.getTransport().getHeartbeatIntervalMs())) { + System.setProperty(TransportConfig.HEARTBEAT_INTERVAL_MS, + properties.getTransport().getHeartbeatIntervalMs()); + } + if (StringUtils.isEmpty(System.getProperty(TransportConfig.HEARTBEAT_CLIENT_IP)) + && StringUtils.isNotBlank(properties.getTransport().getClientIp())) { + System.setProperty(TransportConfig.HEARTBEAT_CLIENT_IP, + properties.getTransport().getClientIp()); + } + if (StringUtils.isEmpty(System.getProperty(SentinelConfig.CHARSET)) + && StringUtils.isNotBlank(properties.getMetric().getCharset())) { + System.setProperty(SentinelConfig.CHARSET, + properties.getMetric().getCharset()); + } + if (StringUtils + .isEmpty(System.getProperty(SentinelConfig.SINGLE_METRIC_FILE_SIZE)) + && StringUtils.isNotBlank(properties.getMetric().getFileSingleSize())) { + System.setProperty(SentinelConfig.SINGLE_METRIC_FILE_SIZE, + properties.getMetric().getFileSingleSize()); + } + if (StringUtils + .isEmpty(System.getProperty(SentinelConfig.TOTAL_METRIC_FILE_COUNT)) + && StringUtils.isNotBlank(properties.getMetric().getFileTotalCount())) { + System.setProperty(SentinelConfig.TOTAL_METRIC_FILE_COUNT, + properties.getMetric().getFileTotalCount()); + } + if (StringUtils.isEmpty(System.getProperty(SentinelConfig.COLD_FACTOR)) + && StringUtils.isNotBlank(properties.getFlow().getColdFactor())) { + System.setProperty(SentinelConfig.COLD_FACTOR, + properties.getFlow().getColdFactor()); + } + if (StringUtils.isNotBlank(properties.getBlockPage())) { + setConfig(BLOCK_PAGE_URL_CONF_KEY, properties.getBlockPage()); + } + + // earlier initialize + if (properties.isEager()) { + InitExecutor.doInit(); + } + + } + + @Bean + @ConditionalOnMissingBean + public SentinelResourceAspect sentinelResourceAspect() { + return new SentinelResourceAspect(); + } + + @Bean + @ConditionalOnMissingBean + @ConditionalOnClass(name = "org.springframework.web.client.RestTemplate") + @ConditionalOnProperty(name = "resttemplate.sentinel.enabled", havingValue = "true", + matchIfMissing = true) + public SentinelBeanPostProcessor sentinelBeanPostProcessor( + ApplicationContext applicationContext) { + return new SentinelBeanPostProcessor(applicationContext); + } + + @Bean + @ConditionalOnMissingBean + public SentinelDataSourceHandler sentinelDataSourceHandler( + DefaultListableBeanFactory beanFactory, SentinelProperties sentinelProperties, + Environment env) { + return new SentinelDataSourceHandler(beanFactory, sentinelProperties, env); + } + + @ConditionalOnClass(ObjectMapper.class) + @Configuration(proxyBeanMethods = false) + protected static class SentinelConverterConfiguration { + + @Configuration(proxyBeanMethods = false) + protected static class SentinelJsonConfiguration { + + private ObjectMapper objectMapper = new ObjectMapper(); + + public SentinelJsonConfiguration() { + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, + false); + } + + @Bean("sentinel-json-flow-converter") + public JsonConverter jsonFlowConverter() { + return new JsonConverter(objectMapper, FlowRule.class); + } + + @Bean("sentinel-json-degrade-converter") + public JsonConverter jsonDegradeConverter() { + return new JsonConverter(objectMapper, DegradeRule.class); + } + + @Bean("sentinel-json-system-converter") + public JsonConverter jsonSystemConverter() { + return new JsonConverter(objectMapper, SystemRule.class); + } + + @Bean("sentinel-json-authority-converter") + public JsonConverter jsonAuthorityConverter() { + return new JsonConverter(objectMapper, AuthorityRule.class); + } + + @Bean("sentinel-json-param-flow-converter") + public JsonConverter jsonParamFlowConverter() { + return new JsonConverter(objectMapper, ParamFlowRule.class); + } + + } + + @ConditionalOnClass(XmlMapper.class) + @Configuration(proxyBeanMethods = false) + protected static class SentinelXmlConfiguration { + + private XmlMapper xmlMapper = new XmlMapper(); + + public SentinelXmlConfiguration() { + xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, + false); + } + + @Bean("sentinel-xml-flow-converter") + public XmlConverter xmlFlowConverter() { + return new XmlConverter(xmlMapper, FlowRule.class); + } + + @Bean("sentinel-xml-degrade-converter") + public XmlConverter xmlDegradeConverter() { + return new XmlConverter(xmlMapper, DegradeRule.class); + } + + @Bean("sentinel-xml-system-converter") + public XmlConverter xmlSystemConverter() { + return new XmlConverter(xmlMapper, SystemRule.class); + } + + @Bean("sentinel-xml-authority-converter") + public XmlConverter xmlAuthorityConverter() { + return new XmlConverter(xmlMapper, AuthorityRule.class); + } + + @Bean("sentinel-xml-param-flow-converter") + public XmlConverter xmlParamFlowConverter() { + return new XmlConverter(xmlMapper, ParamFlowRule.class); + } + + } + + } + +} diff --git a/ruoyi-common/ruoyi-common-sentinel/src/main/java/com/ruoyi/common/sentinel/config/properties/SentinelCustomProperties.java b/ruoyi-common/ruoyi-common-sentinel/src/main/java/com/ruoyi/common/sentinel/config/properties/SentinelCustomProperties.java new file mode 100644 index 00000000..521ce529 --- /dev/null +++ b/ruoyi-common/ruoyi-common-sentinel/src/main/java/com/ruoyi/common/sentinel/config/properties/SentinelCustomProperties.java @@ -0,0 +1,17 @@ +package com.ruoyi.common.sentinel.config.properties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * sentinel自定义配置类 + * + * @author Lion Li + */ +@Data +@ConfigurationProperties(prefix = "spring.cloud.sentinel.transport") +public class SentinelCustomProperties { + + private String serverName; + +} diff --git a/ruoyi-common/ruoyi-common-sentinel/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/ruoyi-common/ruoyi-common-sentinel/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/ruoyi-common/ruoyi-common-sentinel/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ + diff --git a/ruoyi-gateway/pom.xml b/ruoyi-gateway/pom.xml index cd43d235..541d9878 100644 --- a/ruoyi-gateway/pom.xml +++ b/ruoyi-gateway/pom.xml @@ -44,24 +44,12 @@ spring-cloud-starter-alibaba-nacos-config - - - com.alibaba.cloud - spring-cloud-starter-alibaba-sentinel - - com.alibaba.cloud spring-cloud-alibaba-sentinel-gateway - - - com.alibaba.csp - sentinel-datasource-nacos - - org.springframework.boot @@ -91,6 +79,17 @@ ${satoken.version} + + com.ruoyi + ruoyi-common-sentinel + + + com.alibaba.csp + sentinel-apache-dubbo3-adapter + + + + com.ruoyi ruoyi-common-satoken diff --git a/ruoyi-modules/ruoyi-gen/pom.xml b/ruoyi-modules/ruoyi-gen/pom.xml index f096384f..44733407 100644 --- a/ruoyi-modules/ruoyi-gen/pom.xml +++ b/ruoyi-modules/ruoyi-gen/pom.xml @@ -29,12 +29,6 @@ spring-cloud-starter-alibaba-nacos-config - - - com.alibaba.cloud - spring-cloud-starter-alibaba-sentinel - - org.springframework.boot diff --git a/ruoyi-modules/ruoyi-job/pom.xml b/ruoyi-modules/ruoyi-job/pom.xml index 4ddc95fc..140d9c66 100644 --- a/ruoyi-modules/ruoyi-job/pom.xml +++ b/ruoyi-modules/ruoyi-job/pom.xml @@ -29,12 +29,6 @@ spring-cloud-starter-alibaba-nacos-config - - - com.alibaba.cloud - spring-cloud-starter-alibaba-sentinel - - org.springframework.boot diff --git a/ruoyi-modules/ruoyi-resource/pom.xml b/ruoyi-modules/ruoyi-resource/pom.xml index c8223093..27578470 100644 --- a/ruoyi-modules/ruoyi-resource/pom.xml +++ b/ruoyi-modules/ruoyi-resource/pom.xml @@ -29,12 +29,6 @@ spring-cloud-starter-alibaba-nacos-config - - - com.alibaba.cloud - spring-cloud-starter-alibaba-sentinel - - mysql @@ -47,6 +41,11 @@ spring-boot-starter-actuator + + com.ruoyi + ruoyi-common-sentinel + + com.ruoyi ruoyi-common-doc diff --git a/ruoyi-modules/ruoyi-system/pom.xml b/ruoyi-modules/ruoyi-system/pom.xml index 14438183..5ac7eee9 100644 --- a/ruoyi-modules/ruoyi-system/pom.xml +++ b/ruoyi-modules/ruoyi-system/pom.xml @@ -29,12 +29,6 @@ spring-cloud-starter-alibaba-nacos-config - - - com.alibaba.cloud - spring-cloud-starter-alibaba-sentinel - - org.springframework.boot @@ -47,6 +41,11 @@ mysql-connector-java + + com.ruoyi + ruoyi-common-sentinel + + com.ruoyi