diff --git a/spring-cloud-alibaba-dependencies/pom.xml b/spring-cloud-alibaba-dependencies/pom.xml index 21b18375..eb376120 100644 --- a/spring-cloud-alibaba-dependencies/pom.xml +++ b/spring-cloud-alibaba-dependencies/pom.xml @@ -16,7 +16,7 @@ Spring Cloud Alibaba Dependencies - 1.4.0 + 1.4.2 3.1.0 0.8.2 0.1.3 diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-example/pom.xml b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-example/pom.xml index fd6c6875..f8e1217a 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-example/pom.xml +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-example/pom.xml @@ -44,11 +44,6 @@ org.springframework.cloud spring-cloud-starter-alibaba-sentinel - - - org.springframework.cloud - spring-cloud-alicloud-context - diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/pom.xml b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/pom.xml index 0f28a7ac..9397b274 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/pom.xml +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/pom.xml @@ -29,11 +29,6 @@ org.springframework.boot spring-boot-starter-actuator - - - org.springframework.cloud - spring-cloud-alicloud-context - diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/ExceptionUtil.java b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/ExceptionUtil.java index 94ef5dde..c9f82e3b 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/ExceptionUtil.java +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/ExceptionUtil.java @@ -17,4 +17,4 @@ public class ExceptionUtil { return new SentinelClientHttpResponse("custom block info"); } -} +} \ No newline at end of file diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/ServiceApplication.java b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/ServiceApplication.java index f1fe28e6..c05c01af 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/ServiceApplication.java +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/ServiceApplication.java @@ -26,7 +26,7 @@ public class ServiceApplication { } @Bean - public Converter myParser() { + public Converter myConverter() { return new JsonFlowRuleListConverter(); } diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/application.properties b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/application.properties index 19c2868e..0f75d4b9 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/application.properties +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/application.properties @@ -7,10 +7,22 @@ spring.cloud.sentinel.eager=true spring.cloud.sentinel.datasource.ds1.file.file=classpath: flowrule.json spring.cloud.sentinel.datasource.ds1.file.data-type=json +spring.cloud.sentinel.datasource.ds1.file.rule-type=flow #spring.cloud.sentinel.datasource.ds1.file.file=classpath: flowrule.json #spring.cloud.sentinel.datasource.ds1.file.data-type=custom #spring.cloud.sentinel.datasource.ds1.file.converter-class=org.springframework.cloud.alibaba.cloud.examples.JsonFlowRuleListConverter +#spring.cloud.sentinel.datasource.ds1.file.rule-type=flow spring.cloud.sentinel.datasource.ds2.file.file=classpath: degraderule.json -spring.cloud.sentinel.datasource.ds2.file.data-type=json \ No newline at end of file +spring.cloud.sentinel.datasource.ds2.file.data-type=json +spring.cloud.sentinel.datasource.ds2.file.rule-type=degrade + +spring.cloud.sentinel.datasource.ds3.file.file=classpath: authority.json +spring.cloud.sentinel.datasource.ds3.file.rule-type=authority + +spring.cloud.sentinel.datasource.ds4.file.file=classpath: system.json +spring.cloud.sentinel.datasource.ds4.file.rule-type=system + +spring.cloud.sentinel.datasource.ds5.file.file=classpath: param-flow.json +spring.cloud.sentinel.datasource.ds5.file.rule-type=param-flow \ No newline at end of file diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/authority.json b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/authority.json new file mode 100644 index 00000000..3fb4b249 --- /dev/null +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/authority.json @@ -0,0 +1,17 @@ +[ + { + "resource": "good", + "limitApp": "abc", + "strategy": 0 + }, + { + "resource": "bad", + "limitApp": "bcd", + "strategy": 1 + }, + { + "resource": "terrible", + "limitApp": "aaa", + "strategy": 1 + } +] diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/param-flow.json b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/param-flow.json new file mode 100644 index 00000000..72e1c2dc --- /dev/null +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/param-flow.json @@ -0,0 +1,16 @@ +[ + { + "resource": "hotResource", + "count": 0, + "grade": 1, + "limitApp": "default", + "paramIdx": 0, + "paramFlowItemList": [ + { + "object": "2", + "classType": "int", + "count": 1 + } + ] + } +] diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/system.json b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/system.json new file mode 100644 index 00000000..7aa623a7 --- /dev/null +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/system.json @@ -0,0 +1,8 @@ +[ + { + "highestSystemLoad": -1, + "qps": 100, + "avgRt": -1, + "maxThread": 10 + } +] diff --git a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/NacosConfigBootstrapConfiguration.java b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/NacosConfigBootstrapConfiguration.java index 076d884f..94933a4d 100644 --- a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/NacosConfigBootstrapConfiguration.java +++ b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/NacosConfigBootstrapConfiguration.java @@ -17,6 +17,7 @@ package org.springframework.cloud.alibaba.nacos; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.cloud.alibaba.nacos.client.NacosPropertySourceLocator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -27,15 +28,17 @@ import org.springframework.context.annotation.Configuration; @Configuration public class NacosConfigBootstrapConfiguration { - @Bean - public NacosPropertySourceLocator nacosPropertySourceLocator() { - return new NacosPropertySourceLocator(); - } - @Bean @ConditionalOnMissingBean public NacosConfigProperties nacosConfigProperties() { return new NacosConfigProperties(); } + @Bean + @ConditionalOnProperty(name = "spring.cloud.nacos.config.enabled", matchIfMissing = true) + public NacosPropertySourceLocator nacosPropertySourceLocator( + NacosConfigProperties nacosConfigProperties) { + return new NacosPropertySourceLocator(nacosConfigProperties); + } + } diff --git a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/NacosConfigProperties.java b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/NacosConfigProperties.java index abeec2d7..c0e45492 100644 --- a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/NacosConfigProperties.java +++ b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/NacosConfigProperties.java @@ -44,9 +44,14 @@ public class NacosConfigProperties { public static final String PREFIX = "spring.cloud.nacos.config"; - private static final Logger LOGGER = LoggerFactory + private static final Logger log = LoggerFactory .getLogger(NacosConfigProperties.class); + /** + * whether to enable nacos config. + */ + private boolean enabled = true; + /** * nacos config server address */ @@ -137,11 +142,15 @@ public class NacosConfigProperties { this.activeProfiles = environment.getActiveProfiles(); } - public void setActiveProfiles(String[] activeProfiles) { - this.activeProfiles = activeProfiles; + // todo sts support + + public boolean isEnabled() { + return enabled; } - // todo sts support + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } public String getServerAddr() { return serverAddr; @@ -243,10 +252,6 @@ public class NacosConfigProperties { return name; } - public void setName(String name) { - this.name = name; - } - public String[] getActiveProfiles() { return activeProfiles; } @@ -275,6 +280,14 @@ public class NacosConfigProperties { this.extConfig = extConfig; } + public void setName(String name) { + this.name = name; + } + + public void setActiveProfiles(String[] activeProfiles) { + this.activeProfiles = activeProfiles; + } + public static class Config { /** * the data id of extended configuration @@ -316,16 +329,17 @@ public class NacosConfigProperties { @Override public String toString() { - return "NacosConfigProperties{" + "serverAddr='" + serverAddr + '\'' - + ", encode='" + encode + '\'' + ", group='" + group + '\'' - + ", sharedDataids='" + this.sharedDataids + '\'' - + ", refreshableDataids='" + this.refreshableDataids + '\'' + ", prefix='" - + prefix + '\'' + ", fileExtension='" + fileExtension + '\'' - + ", timeout=" + timeout + ", endpoint='" + endpoint + '\'' - + ", namespace='" + namespace + '\'' + ", accessKey='" + accessKey + '\'' - + ", secretKey='" + secretKey + '\'' + ", contextPath='" + contextPath - + '\'' + ", clusterName='" + clusterName + '\'' + ", name='" + name + '\'' - + ", activeProfiles=" + Arrays.toString(activeProfiles) + '}'; + return "NacosConfigProperties{" + "enabled=" + enabled + ", serverAddr='" + + serverAddr + '\'' + ", encode='" + encode + '\'' + ", group='" + group + + '\'' + ", prefix='" + prefix + '\'' + ", fileExtension='" + + fileExtension + '\'' + ", timeout=" + timeout + ", endpoint='" + + endpoint + '\'' + ", namespace='" + namespace + '\'' + ", accessKey='" + + accessKey + '\'' + ", secretKey='" + secretKey + '\'' + + ", contextPath='" + contextPath + '\'' + ", clusterName='" + clusterName + + '\'' + ", name='" + name + '\'' + ", activeProfiles=" + + Arrays.toString(activeProfiles) + ", sharedDataids='" + sharedDataids + + '\'' + ", refreshableDataids='" + refreshableDataids + '\'' + + ", extConfig=" + extConfig + '}'; } public ConfigService configServiceInstance() { @@ -348,7 +362,7 @@ public class NacosConfigProperties { return configService; } catch (Exception e) { - LOGGER.error("create config service error!properties={},e=,", this, e); + log.error("create config service error!properties={},e=,", this, e); return null; } } diff --git a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/client/NacosPropertySourceBuilder.java b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/client/NacosPropertySourceBuilder.java index d7e0766f..d5369007 100644 --- a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/client/NacosPropertySourceBuilder.java +++ b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/client/NacosPropertySourceBuilder.java @@ -33,7 +33,7 @@ import java.util.*; * @author pbting */ public class NacosPropertySourceBuilder { - private static final Logger LOGGER = LoggerFactory + private static final Logger log = LoggerFactory .getLogger(NacosPropertySourceBuilder.class); private static final Properties EMPTY_PROPERTIES = new Properties(); @@ -68,9 +68,6 @@ public class NacosPropertySourceBuilder { NacosPropertySource build(String dataId, String group, String fileExtension, boolean isRefreshable) { Properties p = loadNacosData(dataId, group, fileExtension); - if (p == null) { - p = EMPTY_PROPERTIES; - } NacosPropertySource nacosPropertySource = new NacosPropertySource(group, dataId, propertiesToMap(p), new Date(), isRefreshable); NacosPropertySourceRepository.collectNacosPropertySources(nacosPropertySource); @@ -82,7 +79,7 @@ public class NacosPropertySourceBuilder { try { data = configService.getConfig(dataId, group, timeout); if (!StringUtils.isEmpty(data)) { - LOGGER.info(String.format("Loading nacos data, dataId: '%s', group: '%s'", + log.info(String.format("Loading nacos data, dataId: '%s', group: '%s'", dataId, group)); if (fileExtension.equalsIgnoreCase("properties")) { @@ -101,21 +98,20 @@ public class NacosPropertySourceBuilder { } } catch (NacosException e) { - LOGGER.error("get data from Nacos error,dataId:{}, ", dataId, e); + log.error("get data from Nacos error,dataId:{}, ", dataId, e); } catch (Exception e) { - LOGGER.error("parse data from Nacos error,dataId:{},data:{},", dataId, data, - e); + log.error("parse data from Nacos error,dataId:{},data:{},", dataId, data, e); } - return null; + return EMPTY_PROPERTIES; } @SuppressWarnings("unchecked") private Map propertiesToMap(Properties properties) { Map result = new HashMap<>(16); - Enumeration tmpKeys = (Enumeration) properties.propertyNames(); - while (tmpKeys.hasMoreElements()) { - String key = tmpKeys.nextElement(); + Enumeration keys = (Enumeration) properties.propertyNames(); + while (keys.hasMoreElements()) { + String key = keys.nextElement(); Object value = properties.getProperty(key); if (value != null) { result.put(key, ((String) value).trim()); @@ -126,4 +122,5 @@ public class NacosPropertySourceBuilder { } return result; } + } diff --git a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/client/NacosPropertySourceLocator.java b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/client/NacosPropertySourceLocator.java index 647856b1..7a665d2b 100644 --- a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/client/NacosPropertySourceLocator.java +++ b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/client/NacosPropertySourceLocator.java @@ -19,7 +19,6 @@ package org.springframework.cloud.alibaba.nacos.client; import com.alibaba.nacos.api.config.ConfigService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.alibaba.nacos.NacosConfigProperties; import org.springframework.cloud.alibaba.nacos.NacosPropertySourceRepository; import org.springframework.cloud.alibaba.nacos.refresh.NacosContextRefresher; @@ -40,7 +39,7 @@ import java.util.List; @Order(0) public class NacosPropertySourceLocator implements PropertySourceLocator { - private static final Logger LOGGER = LoggerFactory + private static final Logger log = LoggerFactory .getLogger(NacosPropertySourceLocator.class); private static final String NACOS_PROPERTY_SOURCE_NAME = "NACOS"; private static final String SEP1 = "-"; @@ -49,22 +48,21 @@ public class NacosPropertySourceLocator implements PropertySourceLocator { private static final List SUPPORT_FILE_EXTENSION = Arrays.asList("properties", "yaml", "yml"); - @Autowired + private NacosPropertySourceBuilder nacosPropertySourceBuilder; + private NacosConfigProperties nacosConfigProperties; - public NacosPropertySourceLocator() { + public NacosPropertySourceLocator(NacosConfigProperties nacosConfigProperties) { + this.nacosConfigProperties = nacosConfigProperties; } - private NacosPropertySourceBuilder nacosPropertySourceBuilder; - @Override public PropertySource locate(Environment env) { ConfigService configService = nacosConfigProperties.configServiceInstance(); if (null == configService) { - LOGGER.warn( - "no instance of config service found, can't load config from nacos"); + log.warn("no instance of config service found, can't load config from nacos"); return null; } long timeout = nacosConfigProperties.getTimeout(); @@ -167,8 +165,7 @@ public class NacosPropertySourceLocator implements PropertySourceLocator { private void loadNacosDataIfPresent(final CompositePropertySource composite, final String dataId, final String group, String fileExtension, boolean isRefreshable) { - - if (NacosContextRefresher.loadCount.get() != 0) { + if (NacosContextRefresher.getRefreshCount() != 0) { NacosPropertySource ps; if (!isRefreshable) { ps = NacosPropertySourceRepository.getNacosPropertySource(dataId); @@ -184,18 +181,22 @@ public class NacosPropertySourceLocator implements PropertySourceLocator { fileExtension, isRefreshable); composite.addFirstPropertySource(ps); } - } - private static void checkDataIdFileExtension(String[] sharedDataIdArry) { + private static void checkDataIdFileExtension(String[] dataIdArray) { StringBuilder stringBuilder = new StringBuilder(); - outline: for (int i = 0; i < sharedDataIdArry.length; i++) { + for (int i = 0; i < dataIdArray.length; i++) { + boolean isLegal = false; for (String fileExtension : SUPPORT_FILE_EXTENSION) { - if (sharedDataIdArry[i].indexOf(fileExtension) > 0) { - continue outline; + if (dataIdArray[i].indexOf(fileExtension) > 0) { + isLegal = true; + break; } } - stringBuilder.append(sharedDataIdArry[i] + ","); + // add tips + if (!isLegal) { + stringBuilder.append(dataIdArray[i] + ","); + } } if (stringBuilder.length() > 0) { diff --git a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/refresh/NacosContextRefresher.java b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/refresh/NacosContextRefresher.java index 28a1d47e..1fc7e8b0 100644 --- a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/refresh/NacosContextRefresher.java +++ b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/refresh/NacosContextRefresher.java @@ -19,6 +19,7 @@ package org.springframework.cloud.alibaba.nacos.refresh; import com.alibaba.nacos.api.config.ConfigService; import com.alibaba.nacos.api.config.listener.Listener; import com.alibaba.nacos.api.exception.NacosException; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.context.event.ApplicationReadyEvent; @@ -51,10 +52,10 @@ import java.util.concurrent.atomic.AtomicLong; public class NacosContextRefresher implements ApplicationListener, ApplicationContextAware { - private final static Logger LOGGER = LoggerFactory + private final static Logger log = LoggerFactory .getLogger(NacosContextRefresher.class); - public static final AtomicLong loadCount = new AtomicLong(0); + private static final AtomicLong REFRESH_COUNT = new AtomicLong(0); private final NacosRefreshProperties refreshProperties; @@ -110,7 +111,7 @@ public class NacosContextRefresher listener = new Listener() { @Override public void receiveConfigInfo(String configInfo) { - loadCount.incrementAndGet(); + refreshCountIncrement(); String md5 = ""; if (!StringUtils.isEmpty(configInfo)) { try { @@ -120,16 +121,15 @@ public class NacosContextRefresher } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) { - LOGGER.warn("[Nacos] unable to get md5 for dataId: " + dataId, + log.warn("[Nacos] unable to get md5 for dataId: " + dataId, e); } } refreshHistory.add(dataId, md5); applicationContext.publishEvent( new RefreshEvent(this, null, "Refresh Nacos config")); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Refresh Nacos config group{},dataId{}", group, - dataId); + if (log.isDebugEnabled()) { + log.debug("Refresh Nacos config group{},dataId{}", group, dataId); } } @@ -149,4 +149,11 @@ public class NacosContextRefresher } } + public static long getRefreshCount() { + return REFRESH_COUNT.get(); + } + + public static void refreshCountIncrement() { + REFRESH_COUNT.incrementAndGet(); + } } diff --git a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryAutoConfiguration.java b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryAutoConfiguration.java index 6e087422..f53a0562 100644 --- a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryAutoConfiguration.java +++ b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryAutoConfiguration.java @@ -16,16 +16,23 @@ package org.springframework.cloud.alibaba.nacos; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnNotWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.cloud.alibaba.nacos.discovery.NacosDiscoveryClientAutoConfiguration; import org.springframework.cloud.alibaba.nacos.registry.NacosAutoServiceRegistration; import org.springframework.cloud.alibaba.nacos.registry.NacosRegistration; import org.springframework.cloud.alibaba.nacos.registry.NacosServiceRegistry; -import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration; +import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration; import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties; +import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -38,19 +45,28 @@ import org.springframework.context.annotation.Configuration; @ConditionalOnNacosDiscoveryEnabled @ConditionalOnClass(name = "org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent") @ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true) -@AutoConfigureBefore({ AutoServiceRegistrationAutoConfiguration.class, - NacosDiscoveryClientAutoConfiguration.class }) +@AutoConfigureBefore(NacosDiscoveryClientAutoConfiguration.class) +@AutoConfigureAfter(AutoServiceRegistrationConfiguration.class) public class NacosDiscoveryAutoConfiguration { @Bean - public NacosServiceRegistry nacosServiceRegistry() { - return new NacosServiceRegistry(); + @ConditionalOnMissingBean + public NacosDiscoveryProperties nacosProperties() { + return new NacosDiscoveryProperties(); + } + + @Bean + public NacosServiceRegistry nacosServiceRegistry( + NacosDiscoveryProperties nacosDiscoveryProperties) { + return new NacosServiceRegistry(nacosDiscoveryProperties); } @Bean @ConditionalOnBean(AutoServiceRegistrationProperties.class) - public NacosRegistration nacosRegistration() { - return new NacosRegistration(); + public NacosRegistration nacosRegistration( + NacosDiscoveryProperties nacosDiscoveryProperties, + ApplicationContext context) { + return new NacosRegistration(nacosDiscoveryProperties, context); } @Bean @@ -62,4 +78,31 @@ public class NacosDiscoveryAutoConfiguration { return new NacosAutoServiceRegistration(registry, autoServiceRegistrationProperties, registration); } + + @Bean + @ConditionalOnBean(NacosAutoServiceRegistration.class) // NacosAutoServiceRegistration + // should be present + @ConditionalOnNotWebApplication // Not Web Application + public ApplicationRunner applicationRunner( + final NacosAutoServiceRegistration nacosAutoServiceRegistration) { + + return new ApplicationRunner() { + @Override + public void run(ApplicationArguments args) throws Exception { + if (!nacosAutoServiceRegistration.isRunning()) { // If it's not running, + // let + // it start. + // FIXME: Please make sure "spring.cloud.nacos.discovery.port" must be + // configured on an available port, + // or the startup or Nacos health check will be failed. + nacosAutoServiceRegistration.start(); + // NacosAutoServiceRegistration will be stopped after its destroy() + // method + // is invoked. + // @PreDestroy destroy() -> stop() + } + } + }; + } + } \ No newline at end of file diff --git a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryProperties.java b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryProperties.java index 11fb1290..ecb0b136 100644 --- a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryProperties.java +++ b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryProperties.java @@ -27,7 +27,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.commons.util.InetUtils; import org.springframework.core.env.Environment; import org.springframework.util.StringUtils; - import javax.annotation.PostConstruct; import java.net.Inet4Address; import java.net.InetAddress; @@ -40,7 +39,7 @@ import static com.alibaba.nacos.api.PropertyKeyConst.*; /** * @author dungu.zpf * @author xiaojing - * @author pbting + * @author Mercy */ @ConfigurationProperties("spring.cloud.nacos.discovery") @@ -65,6 +64,11 @@ public class NacosDiscoveryProperties { */ private String namespace; + /** + * watch delay,duration to pull new service from nacos server. + */ + private long watchDelay = 5000; + /** * nacos naming log file name */ @@ -145,7 +149,14 @@ public class NacosDiscoveryProperties { @PostConstruct public void init() throws SocketException { + if (secure) { + metadata.put("secure", "true"); + } + serverAddr = Objects.toString(serverAddr, ""); + if (serverAddr.lastIndexOf("/") != -1) { + serverAddr.substring(0, serverAddr.length() - 1); + } endpoint = Objects.toString(endpoint, ""); namespace = Objects.toString(namespace, ""); logName = Objects.toString(logName, ""); @@ -158,7 +169,7 @@ public class NacosDiscoveryProperties { else { NetworkInterface netInterface = NetworkInterface .getByName(networkInterface); - if (null == networkInterface) { + if (null == netInterface) { throw new IllegalArgumentException( "no such interface " + networkInterface); } @@ -316,16 +327,25 @@ public class NacosDiscoveryProperties { this.namingLoadCacheAtStart = namingLoadCacheAtStart; } + public long getWatchDelay() { + return watchDelay; + } + + public void setWatchDelay(long watchDelay) { + this.watchDelay = watchDelay; + } + @Override public String toString() { return "NacosDiscoveryProperties{" + "serverAddr='" + serverAddr + '\'' + ", endpoint='" + endpoint + '\'' + ", namespace='" + namespace + '\'' - + ", logName='" + logName + '\'' + ", service='" + service + '\'' - + ", weight=" + weight + ", clusterName='" + clusterName + '\'' - + ", metadata=" + metadata + ", registerEnabled=" + registerEnabled - + ", ip='" + ip + '\'' + ", networkInterface='" + networkInterface + '\'' - + ", port=" + port + ", secure=" + secure + ", accessKey='" + accessKey - + ", namingLoadCacheAtStart=" + namingLoadCacheAtStart + '\'' + + ", watchDelay=" + watchDelay + ", logName='" + logName + '\'' + + ", service='" + service + '\'' + ", weight=" + weight + + ", clusterName='" + clusterName + '\'' + ", namingLoadCacheAtStart='" + + namingLoadCacheAtStart + '\'' + ", metadata=" + metadata + + ", registerEnabled=" + registerEnabled + ", ip='" + ip + '\'' + + ", networkInterface='" + networkInterface + '\'' + ", port=" + port + + ", secure=" + secure + ", accessKey='" + accessKey + '\'' + ", secretKey='" + secretKey + '\'' + '}'; } @@ -353,7 +373,7 @@ public class NacosDiscoveryProperties { } if (StringUtils.isEmpty(this.getClusterName())) { this.setClusterName(env.resolvePlaceholders( - "${spring.cloud.nacos.discovery.clusterName-name:}")); + "${spring.cloud.nacos.discovery.cluster-name:}")); } if (StringUtils.isEmpty(this.getEndpoint())) { this.setEndpoint( @@ -379,12 +399,12 @@ public class NacosDiscoveryProperties { try { namingService = NacosFactory.createNamingService(properties); - return namingService; } catch (Exception e) { LOGGER.error("create naming service error!properties={},e=,", this, e); return null; } + return namingService; } } diff --git a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryClient.java b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/discovery/NacosDiscoveryClient.java similarity index 85% rename from spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryClient.java rename to spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/discovery/NacosDiscoveryClient.java index eedc2ffe..1bc25ea5 100644 --- a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryClient.java +++ b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/discovery/NacosDiscoveryClient.java @@ -14,13 +14,14 @@ * limitations under the License. */ -package org.springframework.cloud.alibaba.nacos; +package org.springframework.cloud.alibaba.nacos.discovery; import com.alibaba.nacos.api.naming.pojo.Instance; import com.alibaba.nacos.api.naming.pojo.ListView; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties; +import org.springframework.cloud.alibaba.nacos.NacosServiceInstance; import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; @@ -30,7 +31,6 @@ import java.util.*; /** * @author xiaojing * @author renhaojun - * @author pbting */ public class NacosDiscoveryClient implements DiscoveryClient { @@ -38,9 +38,12 @@ public class NacosDiscoveryClient implements DiscoveryClient { .getLogger(NacosDiscoveryClient.class); public static final String DESCRIPTION = "Spring Cloud Nacos Discovery Client"; - @Autowired private NacosDiscoveryProperties discoveryProperties; + public NacosDiscoveryClient(NacosDiscoveryProperties discoveryProperties) { + this.discoveryProperties = discoveryProperties; + } + @Override public String description() { return DESCRIPTION; @@ -75,19 +78,24 @@ public class NacosDiscoveryClient implements DiscoveryClient { nacosServiceInstance.setHost(instance.getIp()); nacosServiceInstance.setPort(instance.getPort()); nacosServiceInstance.setServiceId(serviceId); - Map metadata = new HashMap(); + Map metadata = new HashMap<>(); metadata.put("instanceId", instance.getInstanceId()); metadata.put("weight", instance.getWeight() + ""); metadata.put("healthy", instance.isHealthy() + ""); metadata.put("cluster", instance.getClusterName() + ""); metadata.putAll(instance.getMetadata()); nacosServiceInstance.setMetadata(metadata); + + if (metadata.containsKey("secure")) { + boolean secure = Boolean.parseBoolean(metadata.get("secure")); + nacosServiceInstance.setSecure(secure); + } return nacosServiceInstance; } private static List hostToServiceInstanceList( List instances, String serviceId) { - List result = new ArrayList(instances.size()); + List result = new ArrayList<>(instances.size()); for (Instance instance : instances) { result.add(hostToServiceInstance(instance, serviceId)); } diff --git a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryClientAutoConfiguration.java b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/discovery/NacosDiscoveryClientAutoConfiguration.java similarity index 58% rename from spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryClientAutoConfiguration.java rename to spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/discovery/NacosDiscoveryClientAutoConfiguration.java index 05049f4b..5fe818b3 100644 --- a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryClientAutoConfiguration.java +++ b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/discovery/NacosDiscoveryClientAutoConfiguration.java @@ -14,11 +14,16 @@ * limitations under the License. */ -package org.springframework.cloud.alibaba.nacos; +package org.springframework.cloud.alibaba.nacos.discovery; +import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.cloud.alibaba.nacos.ConditionalOnNacosDiscoveryEnabled; +import org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties; +import org.springframework.cloud.client.CommonsClientAutoConfiguration; import org.springframework.cloud.client.discovery.DiscoveryClient; +import org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -26,20 +31,21 @@ import org.springframework.context.annotation.Configuration; * @author xiaojing */ @Configuration -@ConditionalOnMissingBean(DiscoveryClient.class) @ConditionalOnNacosDiscoveryEnabled @EnableConfigurationProperties +@AutoConfigureBefore({ SimpleDiscoveryClientAutoConfiguration.class, + CommonsClientAutoConfiguration.class }) public class NacosDiscoveryClientAutoConfiguration { @Bean - public DiscoveryClient nacosDiscoveryClient() { - return new NacosDiscoveryClient(); + public DiscoveryClient nacosDiscoveryClient( + NacosDiscoveryProperties discoveryProperties) { + return new NacosDiscoveryClient(discoveryProperties); } @Bean @ConditionalOnMissingBean - public NacosDiscoveryProperties nacosProperties() { - return new NacosDiscoveryProperties(); + public NacosWatch nacosWatch(NacosDiscoveryProperties nacosDiscoveryProperties) { + return new NacosWatch(nacosDiscoveryProperties); } - } diff --git a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/discovery/NacosWatch.java b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/discovery/NacosWatch.java new file mode 100644 index 00000000..05e92fbc --- /dev/null +++ b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/discovery/NacosWatch.java @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2019 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 + * + * http://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 org.springframework.cloud.alibaba.nacos.discovery; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; + +import com.alibaba.nacos.api.naming.NamingService; +import com.alibaba.nacos.api.naming.listener.Event; +import com.alibaba.nacos.api.naming.listener.EventListener; +import com.alibaba.nacos.api.naming.pojo.ListView; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties; +import org.springframework.cloud.client.discovery.event.HeartbeatEvent; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.context.ApplicationEventPublisherAware; +import org.springframework.context.SmartLifecycle; +import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; + +/** + * @author xiaojing + */ +public class NacosWatch implements ApplicationEventPublisherAware, SmartLifecycle { + + private static final Logger log = LoggerFactory.getLogger(NacosWatch.class); + + private final NacosDiscoveryProperties properties; + + private final TaskScheduler taskScheduler; + + private final AtomicLong nacosWatchIndex = new AtomicLong(0); + + private final AtomicBoolean running = new AtomicBoolean(false); + + private ApplicationEventPublisher publisher; + + private ScheduledFuture watchFuture; + + private Set cacheServices = new HashSet<>(); + + private HashMap subscribeListeners = new HashMap<>(); + + public NacosWatch(NacosDiscoveryProperties properties) { + this(properties, getTaskScheduler()); + } + + public NacosWatch(NacosDiscoveryProperties properties, TaskScheduler taskScheduler) { + this.properties = properties; + this.taskScheduler = taskScheduler; + } + + private static ThreadPoolTaskScheduler getTaskScheduler() { + ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); + taskScheduler.initialize(); + return taskScheduler; + } + + @Override + public void setApplicationEventPublisher(ApplicationEventPublisher publisher) { + this.publisher = publisher; + } + + @Override + public boolean isAutoStartup() { + return true; + } + + @Override + public void stop(Runnable callback) { + this.stop(); + callback.run(); + } + + @Override + public void start() { + if (this.running.compareAndSet(false, true)) { + this.watchFuture = this.taskScheduler.scheduleWithFixedDelay(new Runnable() { + @Override + public void run() { + NacosWatch.this.nacosServicesWatch(); + } + }, this.properties.getWatchDelay()); + } + } + + @Override + public void stop() { + if (this.running.compareAndSet(true, false) && this.watchFuture != null) { + this.watchFuture.cancel(true); + } + } + + @Override + public boolean isRunning() { + return false; + } + + @Override + public int getPhase() { + return 0; + } + + public void nacosServicesWatch() { + try { + + boolean changed = false; + NamingService namingService = properties.namingServiceInstance(); + + ListView listView = properties.namingServiceInstance() + .getServicesOfServer(1, Integer.MAX_VALUE); + + List serviceList = listView.getData(); + + // if there are new services found, publish event + Set currentServices = new HashSet<>(serviceList); + currentServices.removeAll(cacheServices); + if (currentServices.size() > 0) { + changed = true; + } + + // if some services disappear, publish event + if (cacheServices.removeAll(new HashSet<>(serviceList)) + && cacheServices.size() > 0) { + changed = true; + + for (String serviceName : cacheServices) { + namingService.unsubscribe(serviceName, + subscribeListeners.get(serviceName)); + subscribeListeners.remove(serviceName); + } + } + + cacheServices = new HashSet<>(serviceList); + + // subscribe services's node change, publish event if nodes changed + for (String serviceName : cacheServices) { + if (!subscribeListeners.containsKey(serviceName)) { + EventListener eventListener = new EventListener() { + @Override + public void onEvent(Event event) { + NacosWatch.this.publisher.publishEvent(new HeartbeatEvent( + NacosWatch.this, nacosWatchIndex.getAndIncrement())); + } + }; + subscribeListeners.put(serviceName, eventListener); + namingService.subscribe(serviceName, eventListener); + + } + } + + if (changed) { + this.publisher.publishEvent( + new HeartbeatEvent(this, nacosWatchIndex.getAndIncrement())); + } + + } + catch (Exception e) { + log.error("Error watching Nacos Service change", e); + } + } +} diff --git a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/endpoint/NacosDiscoveryEndpoint.java b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/endpoint/NacosDiscoveryEndpoint.java index ef29eae1..be0907c6 100644 --- a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/endpoint/NacosDiscoveryEndpoint.java +++ b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/endpoint/NacosDiscoveryEndpoint.java @@ -26,7 +26,6 @@ import com.alibaba.nacos.api.naming.pojo.ServiceInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.actuate.endpoint.AbstractEndpoint; import org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties; @@ -39,11 +38,11 @@ public class NacosDiscoveryEndpoint extends AbstractEndpoint private static final Logger LOGGER = LoggerFactory .getLogger(NacosDiscoveryEndpoint.class); - @Autowired private NacosDiscoveryProperties nacosDiscoveryProperties; - public NacosDiscoveryEndpoint() { + public NacosDiscoveryEndpoint(NacosDiscoveryProperties nacosDiscoveryProperties) { super("nacos_discovery", false); + this.nacosDiscoveryProperties = nacosDiscoveryProperties; } /** diff --git a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/endpoint/NacosDiscoveryEndpointAutoConfiguration.java b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/endpoint/NacosDiscoveryEndpointAutoConfiguration.java index eab95411..8e57c23a 100644 --- a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/endpoint/NacosDiscoveryEndpointAutoConfiguration.java +++ b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/endpoint/NacosDiscoveryEndpointAutoConfiguration.java @@ -18,7 +18,7 @@ package org.springframework.cloud.alibaba.nacos.endpoint; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -31,8 +31,9 @@ public class NacosDiscoveryEndpointAutoConfiguration { @Bean @ConditionalOnMissingBean - public NacosDiscoveryEndpoint nacosDiscoveryEndpoint() { - return new NacosDiscoveryEndpoint(); + public NacosDiscoveryEndpoint nacosDiscoveryEndpoint( + NacosDiscoveryProperties nacosDiscoveryProperties) { + return new NacosDiscoveryEndpoint(nacosDiscoveryProperties); } } diff --git a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/registry/NacosAutoServiceRegistration.java b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/registry/NacosAutoServiceRegistration.java index 66df7944..05c638dc 100644 --- a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/registry/NacosAutoServiceRegistration.java +++ b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/registry/NacosAutoServiceRegistration.java @@ -18,26 +18,25 @@ package org.springframework.cloud.alibaba.nacos.registry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration; import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties; +import org.springframework.cloud.client.serviceregistry.Registration; import org.springframework.cloud.client.serviceregistry.ServiceRegistry; import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** * @author xiaojing + * @author Mercy */ public class NacosAutoServiceRegistration - extends AbstractAutoServiceRegistration { + extends AbstractAutoServiceRegistration { private static final Logger LOGGER = LoggerFactory .getLogger(NacosAutoServiceRegistration.class); - @Autowired private NacosRegistration registration; - public NacosAutoServiceRegistration( - ServiceRegistry serviceRegistry, + public NacosAutoServiceRegistration(ServiceRegistry serviceRegistry, AutoServiceRegistrationProperties autoServiceRegistrationProperties, NacosRegistration registration) { super(serviceRegistry, autoServiceRegistrationProperties); diff --git a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/registry/NacosRegistration.java b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/registry/NacosRegistration.java index 3254bc75..584d454c 100644 --- a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/registry/NacosRegistration.java +++ b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/registry/NacosRegistration.java @@ -17,7 +17,6 @@ package org.springframework.cloud.alibaba.nacos.registry; import org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.ManagementServerPortUtils; @@ -38,16 +37,20 @@ import com.alibaba.nacos.api.naming.NamingService; */ public class NacosRegistration implements Registration, ServiceInstance { - private static final String MANAGEMENT_PORT = "management.port"; - private static final String MANAGEMENT_CONTEXT_PATH = "management.context-path"; - private static final String MANAGEMENT_ADDRESS = "management.address"; + public static final String MANAGEMENT_PORT = "management.port"; + public static final String MANAGEMENT_CONTEXT_PATH = "management.context-path"; + public static final String MANAGEMENT_ADDRESS = "management.address"; - @Autowired private NacosDiscoveryProperties nacosDiscoveryProperties; - @Autowired private ApplicationContext context; + public NacosRegistration(NacosDiscoveryProperties nacosDiscoveryProperties, + ApplicationContext context) { + this.nacosDiscoveryProperties = nacosDiscoveryProperties; + this.context = context; + } + @PostConstruct public void init() { @@ -121,11 +124,6 @@ public class NacosRegistration implements Registration, ServiceInstance { return nacosDiscoveryProperties.namingServiceInstance(); } - public void setNacosDiscoveryProperties( - NacosDiscoveryProperties nacosDiscoveryProperties) { - this.nacosDiscoveryProperties = nacosDiscoveryProperties; - } - @Override public String toString() { return "NacosRegistration{" + "nacosDiscoveryProperties=" diff --git a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/registry/NacosServiceRegistry.java b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/registry/NacosServiceRegistry.java index 8f8803fb..d2d5fa67 100644 --- a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/registry/NacosServiceRegistry.java +++ b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/registry/NacosServiceRegistry.java @@ -20,37 +20,43 @@ import com.alibaba.nacos.api.naming.NamingService; import com.alibaba.nacos.api.naming.pojo.Instance; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties; +import org.springframework.cloud.client.serviceregistry.Registration; import org.springframework.cloud.client.serviceregistry.ServiceRegistry; import org.springframework.util.StringUtils; /** * @author xiaojing - * @author pbting + * @author Mercy */ -public class NacosServiceRegistry implements ServiceRegistry { +public class NacosServiceRegistry implements ServiceRegistry { private static Logger logger = LoggerFactory.getLogger(NacosServiceRegistry.class); - @Override - public void register(NacosRegistration registration) { + private final NacosDiscoveryProperties nacosDiscoveryProperties; + + private final NamingService namingService; + + public NacosServiceRegistry(NacosDiscoveryProperties nacosDiscoveryProperties) { + this.nacosDiscoveryProperties = nacosDiscoveryProperties; + this.namingService = nacosDiscoveryProperties.namingServiceInstance(); + } + + @Override + public void register(Registration registration) { - if (!registration.isRegisterEnabled()) { - logger.info("Nacos Registration is disabled..."); - return; - } if (StringUtils.isEmpty(registration.getServiceId())) { logger.info("No service to register for nacos client..."); return; } - NamingService namingService = registration.getNacosNamingService(); String serviceId = registration.getServiceId(); Instance instance = new Instance(); instance.setIp(registration.getHost()); instance.setPort(registration.getPort()); - instance.setWeight(registration.getRegisterWeight()); - instance.setClusterName(registration.getCluster()); + instance.setWeight(nacosDiscoveryProperties.getWeight()); + instance.setClusterName(nacosDiscoveryProperties.getClusterName()); instance.setMetadata(registration.getMetadata()); try { @@ -65,7 +71,7 @@ public class NacosServiceRegistry implements ServiceRegistry } @Override - public void deregister(NacosRegistration registration) { + public void deregister(Registration registration) { logger.info("De-registering from Nacos Server now..."); @@ -74,12 +80,12 @@ public class NacosServiceRegistry implements ServiceRegistry return; } - NamingService namingService = registration.getNacosNamingService(); + NamingService namingService = nacosDiscoveryProperties.namingServiceInstance(); String serviceId = registration.getServiceId(); try { namingService.deregisterInstance(serviceId, registration.getHost(), - registration.getPort(), registration.getCluster()); + registration.getPort(), nacosDiscoveryProperties.getClusterName()); } catch (Exception e) { logger.error("ERR_NACOS_DEREGISTER, de-register failed...{},", @@ -95,12 +101,12 @@ public class NacosServiceRegistry implements ServiceRegistry } @Override - public void setStatus(NacosRegistration registration, String status) { + public void setStatus(Registration registration, String status) { // nacos doesn't support set status of a particular registration. } @Override - public T getStatus(NacosRegistration registration) { + public T getStatus(Registration registration) { // nacos doesn't support query status of a particular registration. return null; } diff --git a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/ribbon/NacosRibbonClientConfiguration.java b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/ribbon/NacosRibbonClientConfiguration.java index e3d1f732..ddd1696e 100644 --- a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/ribbon/NacosRibbonClientConfiguration.java +++ b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/ribbon/NacosRibbonClientConfiguration.java @@ -19,6 +19,7 @@ package org.springframework.cloud.alibaba.nacos.ribbon; import com.netflix.client.config.IClientConfig; import com.netflix.loadbalancer.ServerList; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -32,8 +33,8 @@ public class NacosRibbonClientConfiguration { @Bean @ConditionalOnMissingBean - public ServerList ribbonServerList(IClientConfig config) { - NacosServerList serverList = new NacosServerList(); + public ServerList ribbonServerList(IClientConfig config, NacosDiscoveryProperties nacosDiscoveryProperties) { + NacosServerList serverList = new NacosServerList(nacosDiscoveryProperties); serverList.initWithNiwsConfig(config); return serverList; } diff --git a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/ribbon/NacosServerList.java b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/ribbon/NacosServerList.java index 74dda2de..42fa9f8f 100644 --- a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/ribbon/NacosServerList.java +++ b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/ribbon/NacosServerList.java @@ -16,32 +16,26 @@ package org.springframework.cloud.alibaba.nacos.ribbon; +import com.alibaba.nacos.api.naming.pojo.Instance; import com.netflix.client.config.IClientConfig; import com.netflix.loadbalancer.AbstractServerList; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties; import java.util.ArrayList; import java.util.List; -import com.alibaba.nacos.api.naming.pojo.Instance; - /** * @author xiaojing * @author renhaojun */ public class NacosServerList extends AbstractServerList { - @Autowired private NacosDiscoveryProperties discoveryProperties; private String serviceId; - public NacosServerList() { - } - - public NacosServerList(String serviceId) { - this.serviceId = serviceId; + public NacosServerList(NacosDiscoveryProperties discoveryProperties) { + this.discoveryProperties = discoveryProperties; } @Override @@ -68,7 +62,10 @@ public class NacosServerList extends AbstractServerList { } private List instancesToServerList(List instances) { - List result = new ArrayList<>(instances.size()); + List result = new ArrayList<>(); + if (null == instances) { + return result; + } for (Instance instance : instances) { result.add(new NacosServer(instance)); } diff --git a/spring-cloud-alibaba-nacos-discovery/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-alibaba-nacos-discovery/src/main/resources/META-INF/additional-spring-configuration-metadata.json index 27f753ff..d0e82a51 100644 --- a/spring-cloud-alibaba-nacos-discovery/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-cloud-alibaba-nacos-discovery/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -1,5 +1,4 @@ -{ - "properties": [ +{"properties": [ { "name": "spring.cloud.nacos.discovery.service", "type": "java.lang.String", @@ -12,5 +11,4 @@ "defaultValue": "false", "description": "naming load from local cache at application start ." } - ] -} +]} diff --git a/spring-cloud-alibaba-nacos-discovery/src/main/resources/META-INF/spring.factories b/spring-cloud-alibaba-nacos-discovery/src/main/resources/META-INF/spring.factories index 723407fe..2fe11df1 100644 --- a/spring-cloud-alibaba-nacos-discovery/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-alibaba-nacos-discovery/src/main/resources/META-INF/spring.factories @@ -1,6 +1,5 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.cloud.alibaba.nacos.NacosDiscoveryAutoConfiguration,\ org.springframework.cloud.alibaba.nacos.ribbon.RibbonNacosAutoConfiguration,\ - org.springframework.cloud.alibaba.nacos.endpoint.NacosDiscoveryEndpointAutoConfiguration -org.springframework.cloud.client.discovery.EnableDiscoveryClient=\ -org.springframework.cloud.alibaba.nacos.NacosDiscoveryClientAutoConfiguration + org.springframework.cloud.alibaba.nacos.endpoint.NacosDiscoveryEndpointAutoConfiguration,\ + org.springframework.cloud.alibaba.nacos.discovery.NacosDiscoveryClientAutoConfiguration diff --git a/spring-cloud-alibaba-nacos-discovery/src/test/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryAutoConfigurationTests.java b/spring-cloud-alibaba-nacos-discovery/src/test/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryAutoConfigurationTests.java index 4be0dd92..7d6dfc8a 100644 --- a/spring-cloud-alibaba-nacos-discovery/src/test/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryAutoConfigurationTests.java +++ b/spring-cloud-alibaba-nacos-discovery/src/test/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryAutoConfigurationTests.java @@ -19,9 +19,9 @@ package org.springframework.cloud.alibaba.nacos; import org.junit.Before; import org.junit.Test; import org.springframework.boot.autoconfigure.AutoConfigureBefore; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.cloud.alibaba.nacos.discovery.NacosDiscoveryClientAutoConfiguration; import org.springframework.cloud.alibaba.nacos.registry.NacosRegistration; import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties; import org.springframework.cloud.commons.util.InetUtils; @@ -44,7 +44,7 @@ public class NacosDiscoveryAutoConfigurationTests { this.context = new SpringApplicationBuilder(NacosDiscoveryTestConfiguration.class, NacosDiscoveryClientAutoConfiguration.class, NacosDiscoveryAutoConfiguration.class).web(false).run( - "--spring.cloud.nacos.discovery.server-addr=127.0.0.1:8080", + "--spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848", "--spring.cloud.nacos.discovery.port=18080", "--spring.cloud.nacos.discovery.service=myapp"); } @@ -55,7 +55,7 @@ public class NacosDiscoveryAutoConfigurationTests { NacosDiscoveryProperties properties = context .getBean(NacosDiscoveryProperties.class); assertThat(properties.getPort()).isEqualTo(18080); - assertThat(properties.getServerAddr()).isEqualTo("127.0.0.1:8080"); + assertThat(properties.getServerAddr()).isEqualTo("127.0.0.1:8848"); assertThat(properties.getService()).isEqualTo("myapp"); } diff --git a/spring-cloud-alibaba-nacos-discovery/src/test/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryClientTests.java b/spring-cloud-alibaba-nacos-discovery/src/test/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryClientTests.java new file mode 100644 index 00000000..a0c144f3 --- /dev/null +++ b/spring-cloud-alibaba-nacos-discovery/src/test/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryClientTests.java @@ -0,0 +1,127 @@ +/* + * Copyright (C) 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 + * + * http://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 org.springframework.cloud.alibaba.nacos; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; + +import com.alibaba.nacos.api.naming.NamingService; +import com.alibaba.nacos.api.naming.pojo.Instance; +import com.alibaba.nacos.api.naming.pojo.ListView; + +import org.junit.Test; +import org.springframework.cloud.alibaba.nacos.discovery.NacosDiscoveryClient; +import org.springframework.cloud.client.ServiceInstance; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.springframework.cloud.alibaba.nacos.test.NacosMockTest.serviceInstance; + +/** + * @author xiaojing + */ +public class NacosDiscoveryClientTests { + + private String host = "123.123.123.123"; + private int port = 8888; + private String serviceName = "test-service"; + + @Test + public void testGetServers() throws Exception { + + ArrayList instances = new ArrayList<>(); + + HashMap map = new HashMap<>(); + map.put("test-key", "test-value"); + map.put("secure", "true"); + + instances.add(serviceInstance(serviceName, false, host, port, map)); + + NacosDiscoveryProperties nacosDiscoveryProperties = mock( + NacosDiscoveryProperties.class); + + NamingService namingService = mock(NamingService.class); + + when(nacosDiscoveryProperties.namingServiceInstance()).thenReturn(namingService); + when(namingService.selectInstances(eq(serviceName), eq(true))) + .thenReturn(instances); + + NacosDiscoveryClient discoveryClient = new NacosDiscoveryClient( + nacosDiscoveryProperties); + + List serviceInstances = discoveryClient + .getInstances(serviceName); + + assertThat(serviceInstances.size()).isEqualTo(1); + + ServiceInstance serviceInstance = serviceInstances.get(0); + + assertThat(serviceInstance.getServiceId()).isEqualTo(serviceName); + assertThat(serviceInstance.getHost()).isEqualTo(host); + assertThat(serviceInstance.getPort()).isEqualTo(port); + assertThat(serviceInstance.isSecure()).isEqualTo(true); + assertThat(serviceInstance.getUri().toString()) + .isEqualTo(getUri(serviceInstance)); + assertThat(serviceInstance.getMetadata().get("test-key")).isEqualTo("test-value"); + + } + + @Test + public void testGetAllService() throws Exception { + + ListView nacosServices = new ListView<>(); + + nacosServices.setData(new LinkedList()); + + nacosServices.getData().add(serviceName + "1"); + nacosServices.getData().add(serviceName + "2"); + nacosServices.getData().add(serviceName + "3"); + + NacosDiscoveryProperties nacosDiscoveryProperties = mock( + NacosDiscoveryProperties.class); + + NamingService namingService = mock(NamingService.class); + + NacosDiscoveryClient discoveryClient = new NacosDiscoveryClient( + nacosDiscoveryProperties); + + when(nacosDiscoveryProperties.namingServiceInstance()).thenReturn(namingService); + when(namingService.getServicesOfServer(eq(1), eq(Integer.MAX_VALUE))) + .thenReturn(nacosServices); + + List services = discoveryClient.getServices(); + + assertThat(services.size()).isEqualTo(3); + assertThat(services.contains(serviceName + "1")); + assertThat(services.contains(serviceName + "2")); + assertThat(services.contains(serviceName + "3")); + + } + + private String getUri(ServiceInstance instance) { + + if (instance.isSecure()) { + return "https://" + host + ":" + port; + } + + return "http://" + host + ":" + port; + } +} diff --git a/spring-cloud-alibaba-nacos-discovery/src/test/java/org/springframework/cloud/alibaba/nacos/registry/NacosAutoServiceRegistrationIpNetworkInterfaceTests.java b/spring-cloud-alibaba-nacos-discovery/src/test/java/org/springframework/cloud/alibaba/nacos/registry/NacosAutoServiceRegistrationIpNetworkInterfaceTests.java new file mode 100644 index 00000000..8ec4c7b1 --- /dev/null +++ b/spring-cloud-alibaba-nacos-discovery/src/test/java/org/springframework/cloud/alibaba/nacos/registry/NacosAutoServiceRegistrationIpNetworkInterfaceTests.java @@ -0,0 +1,147 @@ +/* + * Copyright (C) 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 + * + * http://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 org.springframework.cloud.alibaba.nacos.registry; + +import java.net.Inet4Address; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.util.Enumeration; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.ImportAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.alibaba.nacos.NacosDiscoveryAutoConfiguration; +import org.springframework.cloud.alibaba.nacos.discovery.NacosDiscoveryClientAutoConfiguration; +import org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties; +import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration; +import org.springframework.cloud.commons.util.InetUtils; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.junit4.SpringRunner; + +/** + * @author xiaojing + */ + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = NacosAutoServiceRegistrationIpNetworkInterfaceTests.TestConfig.class, properties = { + "spring.application.name=myTestService1", + "spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848" }, webEnvironment = RANDOM_PORT) +public class NacosAutoServiceRegistrationIpNetworkInterfaceTests { + + @Autowired + private NacosRegistration registration; + + @Autowired + private NacosAutoServiceRegistration nacosAutoServiceRegistration; + + @Autowired + private NacosDiscoveryProperties properties; + + @Autowired + private InetUtils inetUtils; + + @Test + public void contextLoads() throws Exception { + + assertNotNull("NacosRegistration was not created", registration); + assertNotNull("NacosDiscoveryProperties was not created", properties); + assertNotNull("NacosAutoServiceRegistration was not created", + nacosAutoServiceRegistration); + + checkoutNacosDiscoveryServiceIP(); + + } + + private void checkoutNacosDiscoveryServiceIP() { + assertEquals("NacosDiscoveryProperties service IP was wrong", + getIPFromNetworkInterface(TestConfig.netWorkInterfaceName), + registration.getHost()); + + } + + private String getIPFromNetworkInterface(String networkInterface) { + + if (!TestConfig.hasValidNetworkInterface) { + return inetUtils.findFirstNonLoopbackHostInfo().getIpAddress(); + } + + try { + NetworkInterface netInterface = NetworkInterface.getByName(networkInterface); + + Enumeration inetAddress = netInterface.getInetAddresses(); + while (inetAddress.hasMoreElements()) { + InetAddress currentAddress = inetAddress.nextElement(); + if (currentAddress instanceof Inet4Address + && !currentAddress.isLoopbackAddress()) { + return currentAddress.getHostAddress(); + } + } + return networkInterface; + } + catch (Exception e) { + return networkInterface; + } + } + + @Configuration + @EnableAutoConfiguration + @ImportAutoConfiguration({ AutoServiceRegistrationConfiguration.class, + NacosDiscoveryClientAutoConfiguration.class, + NacosDiscoveryAutoConfiguration.class }) + public static class TestConfig { + + static boolean hasValidNetworkInterface = false; + static String netWorkInterfaceName; + + static { + + try { + Enumeration enumeration = NetworkInterface + .getNetworkInterfaces(); + while (enumeration.hasMoreElements() && !hasValidNetworkInterface) { + NetworkInterface networkInterface = enumeration.nextElement(); + Enumeration inetAddress = networkInterface + .getInetAddresses(); + while (inetAddress.hasMoreElements()) { + InetAddress currentAddress = inetAddress.nextElement(); + if (currentAddress instanceof Inet4Address + && !currentAddress.isLoopbackAddress()) { + hasValidNetworkInterface = true; + netWorkInterfaceName = networkInterface.getName(); + System.setProperty( + "spring.cloud.nacos.discovery.network-interface", + networkInterface.getName()); + break; + } + } + } + + } + catch (Exception e) { + + } + } + } + +} diff --git a/spring-cloud-alibaba-nacos-discovery/src/test/java/org/springframework/cloud/alibaba/nacos/registry/NacosAutoServiceRegistrationIpTests.java b/spring-cloud-alibaba-nacos-discovery/src/test/java/org/springframework/cloud/alibaba/nacos/registry/NacosAutoServiceRegistrationIpTests.java new file mode 100644 index 00000000..872c22a1 --- /dev/null +++ b/spring-cloud-alibaba-nacos-discovery/src/test/java/org/springframework/cloud/alibaba/nacos/registry/NacosAutoServiceRegistrationIpTests.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 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 + * + * http://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 org.springframework.cloud.alibaba.nacos.registry; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.ImportAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.alibaba.nacos.NacosDiscoveryAutoConfiguration; +import org.springframework.cloud.alibaba.nacos.discovery.NacosDiscoveryClientAutoConfiguration; +import org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties; +import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.junit4.SpringRunner; + +/** + * @author xiaojing + */ + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = NacosAutoServiceRegistrationIpTests.TestConfig.class, properties = { + "spring.application.name=myTestService1", + "spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848", + "spring.cloud.nacos.discovery.ip=123.123.123.123" }, webEnvironment = RANDOM_PORT) +public class NacosAutoServiceRegistrationIpTests { + + @Autowired + private NacosRegistration registration; + + @Autowired + private NacosAutoServiceRegistration nacosAutoServiceRegistration; + + @Autowired + private NacosDiscoveryProperties properties; + + @Test + public void contextLoads() throws Exception { + + assertNotNull("NacosRegistration was not created", registration); + assertNotNull("NacosDiscoveryProperties was not created", properties); + assertNotNull("NacosAutoServiceRegistration was not created", + nacosAutoServiceRegistration); + + checkoutNacosDiscoveryServiceIP(); + + } + + private void checkoutNacosDiscoveryServiceIP() { + assertEquals("NacosDiscoveryProperties service IP was wrong", "123.123.123.123", + registration.getHost()); + + } + + @Configuration + @EnableAutoConfiguration + @ImportAutoConfiguration({ AutoServiceRegistrationConfiguration.class, + NacosDiscoveryClientAutoConfiguration.class, + NacosDiscoveryAutoConfiguration.class }) + public static class TestConfig { + } +} diff --git a/spring-cloud-alibaba-nacos-discovery/src/test/java/org/springframework/cloud/alibaba/nacos/registry/NacosAutoServiceRegistrationManagementPortTests.java b/spring-cloud-alibaba-nacos-discovery/src/test/java/org/springframework/cloud/alibaba/nacos/registry/NacosAutoServiceRegistrationManagementPortTests.java new file mode 100644 index 00000000..74cf1a5b --- /dev/null +++ b/spring-cloud-alibaba-nacos-discovery/src/test/java/org/springframework/cloud/alibaba/nacos/registry/NacosAutoServiceRegistrationManagementPortTests.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 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 + * + * http://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 org.springframework.cloud.alibaba.nacos.registry; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; +import static org.springframework.cloud.alibaba.nacos.registry.NacosRegistration.MANAGEMENT_PORT; +import static org.springframework.cloud.alibaba.nacos.registry.NacosRegistration.MANAGEMENT_CONTEXT_PATH; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.ImportAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.alibaba.nacos.NacosDiscoveryAutoConfiguration; +import org.springframework.cloud.alibaba.nacos.discovery.NacosDiscoveryClientAutoConfiguration; +import org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties; +import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.junit4.SpringRunner; + +/** + * @author xiaojing + */ + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = NacosAutoServiceRegistrationManagementPortTests.TestConfig.class, properties = { + "spring.application.name=myTestService1", "management.port=8888", + "management.context-path=/test-context-path", + "spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848", + "spring.cloud.nacos.discovery.port=8888" }, webEnvironment = RANDOM_PORT) +public class NacosAutoServiceRegistrationManagementPortTests { + + @Autowired + private NacosRegistration registration; + + @Autowired + private NacosAutoServiceRegistration nacosAutoServiceRegistration; + + @Autowired + private NacosDiscoveryProperties properties; + + @Test + public void contextLoads() throws Exception { + + assertNotNull("NacosRegistration was not created", registration); + assertNotNull("NacosDiscoveryProperties was not created", properties); + assertNotNull("NacosAutoServiceRegistration was not created", + nacosAutoServiceRegistration); + + checkoutNacosDiscoveryManagementData(); + + } + + private void checkoutNacosDiscoveryManagementData() { + assertEquals("NacosDiscoveryProperties management port was wrong", "8888", + properties.getMetadata().get(MANAGEMENT_PORT)); + + assertEquals("NacosDiscoveryProperties management context path was wrong", + "/test-context-path", + properties.getMetadata().get(MANAGEMENT_CONTEXT_PATH)); + + } + + @Configuration + @EnableAutoConfiguration + @ImportAutoConfiguration({ AutoServiceRegistrationConfiguration.class, + NacosDiscoveryClientAutoConfiguration.class, + NacosDiscoveryAutoConfiguration.class }) + public static class TestConfig { + } +} diff --git a/spring-cloud-alibaba-nacos-discovery/src/test/java/org/springframework/cloud/alibaba/nacos/registry/NacosAutoServiceRegistrationPortTests.java b/spring-cloud-alibaba-nacos-discovery/src/test/java/org/springframework/cloud/alibaba/nacos/registry/NacosAutoServiceRegistrationPortTests.java new file mode 100644 index 00000000..ab76dc97 --- /dev/null +++ b/spring-cloud-alibaba-nacos-discovery/src/test/java/org/springframework/cloud/alibaba/nacos/registry/NacosAutoServiceRegistrationPortTests.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 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 + * + * http://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 org.springframework.cloud.alibaba.nacos.registry; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.ImportAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.alibaba.nacos.NacosDiscoveryAutoConfiguration; +import org.springframework.cloud.alibaba.nacos.discovery.NacosDiscoveryClientAutoConfiguration; +import org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties; +import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.junit4.SpringRunner; + +/** + * @author xiaojing + */ + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = NacosAutoServiceRegistrationPortTests.TestConfig.class, properties = { + "spring.application.name=myTestService1", + "spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848", + "spring.cloud.nacos.discovery.port=8888" }, webEnvironment = RANDOM_PORT) +public class NacosAutoServiceRegistrationPortTests { + + @Autowired + private NacosRegistration registration; + + @Autowired + private NacosAutoServiceRegistration nacosAutoServiceRegistration; + + @Autowired + private NacosDiscoveryProperties properties; + + @Test + public void contextLoads() throws Exception { + + assertNotNull("NacosRegistration was not created", registration); + assertNotNull("NacosDiscoveryProperties was not created", properties); + assertNotNull("NacosAutoServiceRegistration was not created", + nacosAutoServiceRegistration); + + checkoutNacosDiscoveryServicePort(); + + } + + private void checkoutNacosDiscoveryServicePort() { + assertEquals("NacosDiscoveryProperties service Port was wrong", 8888, + registration.getPort()); + + } + + @Configuration + @EnableAutoConfiguration + @ImportAutoConfiguration({ AutoServiceRegistrationConfiguration.class, + NacosDiscoveryClientAutoConfiguration.class, + NacosDiscoveryAutoConfiguration.class }) + public static class TestConfig { + } +} diff --git a/spring-cloud-alibaba-nacos-discovery/src/test/java/org/springframework/cloud/alibaba/nacos/registry/NacosAutoServiceRegistrationTests.java b/spring-cloud-alibaba-nacos-discovery/src/test/java/org/springframework/cloud/alibaba/nacos/registry/NacosAutoServiceRegistrationTests.java new file mode 100644 index 00000000..0bca8136 --- /dev/null +++ b/spring-cloud-alibaba-nacos-discovery/src/test/java/org/springframework/cloud/alibaba/nacos/registry/NacosAutoServiceRegistrationTests.java @@ -0,0 +1,199 @@ +/* + * Copyright (C) 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 + * + * http://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 org.springframework.cloud.alibaba.nacos.registry; + +import java.util.Map; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.ImportAutoConfiguration; +import org.springframework.boot.context.embedded.LocalServerPort; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.alibaba.nacos.NacosDiscoveryAutoConfiguration; +import org.springframework.cloud.alibaba.nacos.discovery.NacosDiscoveryClientAutoConfiguration; +import org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties; +import org.springframework.cloud.alibaba.nacos.endpoint.NacosDiscoveryEndpoint; +import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration; +import org.springframework.cloud.commons.util.InetUtils; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; + +/** + * @author xiaojing + */ + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = NacosAutoServiceRegistrationTests.TestConfig.class, properties = { + "spring.application.name=myTestService1", + "spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848", + "spring.cloud.nacos.discovery.endpoint=test-endpoint", + "spring.cloud.nacos.discovery.namespace=test-namespace", + "spring.cloud.nacos.discovery.log-name=test-logName", + "spring.cloud.nacos.discovery.weight=2", + "spring.cloud.nacos.discovery.clusterName=test-cluster", + "spring.cloud.nacos.discovery.namingLoadCacheAtStart=true", + "spring.cloud.nacos.discovery.secure=true", + "spring.cloud.nacos.discovery.accessKey=test-accessKey", + "spring.cloud.nacos.discovery.secretKey=test-secretKey" }, webEnvironment = RANDOM_PORT) +public class NacosAutoServiceRegistrationTests { + + @Autowired + private NacosRegistration registration; + + @Autowired + private NacosAutoServiceRegistration nacosAutoServiceRegistration; + + @LocalServerPort + private int port; + + @Autowired + private NacosDiscoveryProperties properties; + + @Autowired + private InetUtils inetUtils; + + @Test + public void contextLoads() throws Exception { + + assertNotNull("NacosRegistration was not created", registration); + assertNotNull("NacosDiscoveryProperties was not created", properties); + assertNotNull("NacosAutoServiceRegistration was not created", + nacosAutoServiceRegistration); + + checkoutNacosDiscoveryServerAddr(); + checkoutNacosDiscoveryEndpoint(); + checkoutNacosDiscoveryNamespace(); + checkoutNacosDiscoveryLogName(); + checkoutNacosDiscoveryWeight(); + checkoutNacosDiscoveryClusterName(); + checkoutNacosDiscoveryCache(); + checkoutNacosDiscoverySecure(); + checkoutNacosDiscoveryAccessKey(); + checkoutNacosDiscoverySecrectKey(); + + checkoutNacosDiscoveryServiceName(); + checkoutNacosDiscoveryServiceIP(); + checkoutNacosDiscoveryServicePort(); + + checkAutoRegister(); + + checkoutEndpoint(); + + } + + private void checkAutoRegister() { + assertTrue("Nacos Auto Registration was not start", + nacosAutoServiceRegistration.isRunning()); + } + + private void checkoutNacosDiscoveryServerAddr() { + assertEquals("NacosDiscoveryProperties server address was wrong", + "127.0.0.1:8848", properties.getServerAddr()); + + } + + private void checkoutNacosDiscoveryEndpoint() { + assertEquals("NacosDiscoveryProperties endpoint was wrong", "test-endpoint", + properties.getEndpoint()); + + } + + private void checkoutNacosDiscoveryNamespace() { + assertEquals("NacosDiscoveryProperties namespace was wrong", "test-namespace", + properties.getNamespace()); + + } + + private void checkoutNacosDiscoveryLogName() { + assertEquals("NacosDiscoveryProperties logName was wrong", "test-logName", + properties.getLogName()); + } + + private void checkoutNacosDiscoveryWeight() { + assertEquals(2, properties.getWeight(), 0.00000001); + } + + private void checkoutNacosDiscoveryClusterName() { + assertEquals("NacosDiscoveryProperties cluster was wrong", "test-cluster", + properties.getClusterName()); + } + + private void checkoutNacosDiscoveryCache() { + assertEquals("NacosDiscoveryProperties naming load cache was wrong", "true", + properties.getNamingLoadCacheAtStart()); + } + + private void checkoutNacosDiscoverySecure() { + assertEquals("NacosDiscoveryProperties is secure was wrong", true, + properties.isSecure()); + assertEquals("NacosDiscoveryProperties is secure was wrong", "true", + properties.getMetadata().get("secure")); + } + + private void checkoutNacosDiscoveryAccessKey() { + assertEquals("NacosDiscoveryProperties is access key was wrong", "test-accessKey", + properties.getAccessKey()); + } + + private void checkoutNacosDiscoverySecrectKey() { + assertEquals("NacosDiscoveryProperties is secret key was wrong", "test-secretKey", + properties.getSecretKey()); + } + + private void checkoutNacosDiscoveryServiceName() { + assertEquals("NacosDiscoveryProperties service name was wrong", "myTestService1", + properties.getService()); + + } + + private void checkoutNacosDiscoveryServiceIP() { + assertEquals("NacosDiscoveryProperties service IP was wrong", + inetUtils.findFirstNonLoopbackHostInfo().getIpAddress(), + registration.getHost()); + + } + + private void checkoutNacosDiscoveryServicePort() { + assertEquals("NacosDiscoveryProperties service Port was wrong", port, + registration.getPort()); + + } + + private void checkoutEndpoint() throws Exception { + NacosDiscoveryEndpoint nacosDiscoveryEndpoint = new NacosDiscoveryEndpoint( + properties); + Map map = nacosDiscoveryEndpoint.invoke(); + assertEquals(map.get("NacosDiscoveryProperties"), properties); + assertEquals(map.get("subscribe").toString(), + properties.namingServiceInstance().getSubscribeServices().toString()); + } + + @Configuration + @EnableAutoConfiguration + @ImportAutoConfiguration({ AutoServiceRegistrationConfiguration.class, + NacosDiscoveryClientAutoConfiguration.class, + NacosDiscoveryAutoConfiguration.class }) + public static class TestConfig { + } +} diff --git a/spring-cloud-alibaba-nacos-discovery/src/test/java/org/springframework/cloud/alibaba/nacos/ribbon/NacosRibbonClientConfigurationTests.java b/spring-cloud-alibaba-nacos-discovery/src/test/java/org/springframework/cloud/alibaba/nacos/ribbon/NacosRibbonClientConfigurationTests.java deleted file mode 100644 index c0f808d9..00000000 --- a/spring-cloud-alibaba-nacos-discovery/src/test/java/org/springframework/cloud/alibaba/nacos/ribbon/NacosRibbonClientConfigurationTests.java +++ /dev/null @@ -1,82 +0,0 @@ -package org.springframework.cloud.alibaba.nacos.ribbon; - -import com.netflix.client.config.DefaultClientConfigImpl; -import com.netflix.client.config.IClientConfig; -import org.junit.Before; -import org.junit.Test; -import org.springframework.boot.autoconfigure.AutoConfigureBefore; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.cloud.alibaba.nacos.NacosDiscoveryAutoConfiguration; -import org.springframework.cloud.alibaba.nacos.NacosDiscoveryClientAutoConfiguration; -import org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties; -import org.springframework.cloud.client.discovery.EnableDiscoveryClient; -import org.springframework.cloud.client.loadbalancer.LoadBalanced; -import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties; -import org.springframework.cloud.commons.util.InetUtils; -import org.springframework.cloud.commons.util.InetUtilsProperties; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.client.RestTemplate; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author xiaojing - */ -public class NacosRibbonClientConfigurationTests { - - private ConfigurableApplicationContext context; - - @Before - public void setUp() throws Exception { - this.context = new SpringApplicationBuilder(NacosRibbonTestConfiguration.class, - NacosDiscoveryAutoConfiguration.class, - NacosDiscoveryClientAutoConfiguration.class, - NacosRibbonClientConfiguration.class, RibbonNacosAutoConfiguration.class) - .web(false).run("--server.port=18080", - "--spring.cloud.nacos.discovery.server-addr=127.0.0.1:8080", - "--spring.cloud.nacos.discovery.port=18080", - "--spring.cloud.nacos.discovery.service=myapp"); - } - - @Test - public void testProperties() { - - NacosServerList serverList = context.getBean(NacosServerList.class); - assertThat(serverList.getServiceId()).isEqualTo("myapp"); - } - - @Configuration - @AutoConfigureBefore(value = { NacosDiscoveryAutoConfiguration.class }) - static class NacosRibbonTestConfiguration { - - @Bean - @ConditionalOnMissingBean - AutoServiceRegistrationProperties autoServiceRegistrationProperties() { - return new AutoServiceRegistrationProperties(); - } - - @Bean - IClientConfig iClientConfig() { - DefaultClientConfigImpl config = new DefaultClientConfigImpl(); - config.setClientName("myapp"); - return config; - } - - @Bean - @LoadBalanced - RestTemplate restTemplate() { - return new RestTemplate(); - } - - @Bean - InetUtils inetUtils() { - return new InetUtils(new InetUtilsProperties()); - } - - } - -} diff --git a/spring-cloud-alibaba-nacos-discovery/src/test/java/org/springframework/cloud/alibaba/nacos/ribbon/NacosServerListTests.java b/spring-cloud-alibaba-nacos-discovery/src/test/java/org/springframework/cloud/alibaba/nacos/ribbon/NacosServerListTests.java new file mode 100644 index 00000000..0dc13855 --- /dev/null +++ b/spring-cloud-alibaba-nacos-discovery/src/test/java/org/springframework/cloud/alibaba/nacos/ribbon/NacosServerListTests.java @@ -0,0 +1,175 @@ +/* + * Copyright (C) 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 + * + * http://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 org.springframework.cloud.alibaba.nacos.ribbon; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; + +import com.alibaba.nacos.api.naming.NamingService; +import com.alibaba.nacos.api.naming.pojo.Instance; + +import com.netflix.client.config.IClientConfig; +import org.junit.Test; +import org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.springframework.cloud.alibaba.nacos.test.NacosMockTest.serviceInstance; + +/** + * @author xiaojing + */ + +public class NacosServerListTests { + + @Test + @SuppressWarnings("unchecked") + public void testEmptyInstancesReturnsEmptyList() throws Exception { + NacosDiscoveryProperties nacosDiscoveryProperties = mock( + NacosDiscoveryProperties.class); + + NamingService namingService = mock(NamingService.class); + + when(nacosDiscoveryProperties.namingServiceInstance()).thenReturn(namingService); + when(namingService.selectInstances(anyString(), eq(true))).thenReturn(null); + + NacosServerList serverList = new NacosServerList(nacosDiscoveryProperties); + List servers = serverList.getInitialListOfServers(); + assertThat(servers).isEmpty(); + } + + @Test + @SuppressWarnings("unchecked") + public void testGetServers() throws Exception { + + ArrayList instances = new ArrayList<>(); + instances.add(serviceInstance("test-service", false, + Collections. emptyMap())); + + NacosDiscoveryProperties nacosDiscoveryProperties = mock( + NacosDiscoveryProperties.class); + + NamingService namingService = mock(NamingService.class); + + when(nacosDiscoveryProperties.namingServiceInstance()).thenReturn(namingService); + when(namingService.selectInstances(eq("test-service"), eq(true))) + .thenReturn(instances); + + IClientConfig clientConfig = mock(IClientConfig.class); + when(clientConfig.getClientName()).thenReturn("test-service"); + NacosServerList serverList = new NacosServerList(nacosDiscoveryProperties); + serverList.initWithNiwsConfig(clientConfig); + List servers = serverList.getInitialListOfServers(); + assertThat(servers).hasSize(1); + + servers = serverList.getUpdatedListOfServers(); + assertThat(servers).hasSize(1); + } + + @Test + @SuppressWarnings("unchecked") + public void testGetServersWithInstanceStatus() throws Exception { + ArrayList instances = new ArrayList<>(); + + HashMap map1 = new HashMap<>(); + map1.put("instanceNum", "1"); + HashMap map2 = new HashMap<>(); + map2.put("instanceNum", "2"); + instances.add(serviceInstance("test-service", false, map1)); + instances.add(serviceInstance("test-service", true, map2)); + + NacosDiscoveryProperties nacosDiscoveryProperties = mock( + NacosDiscoveryProperties.class); + + NamingService namingService = mock(NamingService.class); + + when(nacosDiscoveryProperties.namingServiceInstance()).thenReturn(namingService); + + List returnInstances = new LinkedList<>(); + + for (Instance instance : instances) { + if (instance.isHealthy()) { + returnInstances.add(instance); + } + } + + when(namingService.selectInstances(eq("test-service"), eq(true))) + .thenReturn(returnInstances); + + IClientConfig clientConfig = mock(IClientConfig.class); + when(clientConfig.getClientName()).thenReturn("test-service"); + NacosServerList serverList = new NacosServerList(nacosDiscoveryProperties); + serverList.initWithNiwsConfig(clientConfig); + List servers = serverList.getInitialListOfServers(); + assertThat(servers).hasSize(1); + + NacosServer nacosServer = servers.get(0); + + assertThat(nacosServer.getMetaInfo().getInstanceId()) + .isEqualTo(instances.get(1).getInstanceId()); + assertThat(nacosServer.getMetadata()).isEqualTo(map2); + assertThat(nacosServer.getInstance().isHealthy()).isEqualTo(true); + assertThat(nacosServer.getInstance().getServiceName()).isEqualTo("test-service"); + assertThat(nacosServer.getInstance().getMetadata().get("instanceNum")) + .isEqualTo("2"); + + } + + @Test + public void testUpdateServers() throws Exception { + ArrayList instances = new ArrayList<>(); + + HashMap map = new HashMap<>(); + map.put("instanceNum", "1"); + instances.add(serviceInstance("test-service", true, map)); + + NacosDiscoveryProperties nacosDiscoveryProperties = mock( + NacosDiscoveryProperties.class); + + NamingService namingService = mock(NamingService.class); + + when(nacosDiscoveryProperties.namingServiceInstance()).thenReturn(namingService); + + List returnInstances = new LinkedList<>(); + for (Instance instance : instances) { + if (instance.isHealthy()) { + returnInstances.add(instance); + } + } + + when(namingService.selectInstances(eq("test-service"), eq(true))) + .thenReturn(returnInstances); + + IClientConfig clientConfig = mock(IClientConfig.class); + when(clientConfig.getClientName()).thenReturn("test-service"); + NacosServerList serverList = new NacosServerList(nacosDiscoveryProperties); + serverList.initWithNiwsConfig(clientConfig); + + List servers = serverList.getUpdatedListOfServers(); + assertThat(servers).hasSize(1); + + assertThat(servers.get(0).getInstance().isHealthy()).isEqualTo(true); + assertThat(servers.get(0).getInstance().getMetadata().get("instanceNum")) + .isEqualTo("1"); + } +} \ No newline at end of file diff --git a/spring-cloud-alibaba-nacos-discovery/src/test/java/org/springframework/cloud/alibaba/nacos/test/CommonTestConfig.java b/spring-cloud-alibaba-nacos-discovery/src/test/java/org/springframework/cloud/alibaba/nacos/test/CommonTestConfig.java new file mode 100644 index 00000000..3f9d2860 --- /dev/null +++ b/spring-cloud-alibaba-nacos-discovery/src/test/java/org/springframework/cloud/alibaba/nacos/test/CommonTestConfig.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 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 + * + * http://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 org.springframework.cloud.alibaba.nacos.test; + +import org.springframework.cloud.client.loadbalancer.LoadBalanced; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; + +/** + * @author xiaojing + */ + +@Configuration +public class CommonTestConfig { + + @Bean + @LoadBalanced + RestTemplate loadBalancedRestTemplate() { + return new RestTemplate(); + } +} \ No newline at end of file diff --git a/spring-cloud-alibaba-nacos-discovery/src/test/java/org/springframework/cloud/alibaba/nacos/test/NacosMockTest.java b/spring-cloud-alibaba-nacos-discovery/src/test/java/org/springframework/cloud/alibaba/nacos/test/NacosMockTest.java new file mode 100644 index 00000000..33efb8eb --- /dev/null +++ b/spring-cloud-alibaba-nacos-discovery/src/test/java/org/springframework/cloud/alibaba/nacos/test/NacosMockTest.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 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 + * + * http://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 org.springframework.cloud.alibaba.nacos.test; + +import java.util.Map; +import java.util.UUID; + +import com.alibaba.nacos.api.naming.pojo.Instance; + +/** + * @author xiaojing + */ +public class NacosMockTest { + + public static Instance serviceInstance(String serviceName, boolean isHealthy, + Map metadata) { + Instance instance = new Instance(); + instance.setInstanceId(UUID.randomUUID().toString()); + instance.setServiceName(serviceName); + instance.setHealthy(isHealthy); + instance.setMetadata(metadata); + return instance; + } + + public static Instance serviceInstance(String serviceName, boolean isHealthy, + String host, int port, Map metadata) { + Instance instance = new Instance(); + instance.setIp(host); + instance.setPort(port); + instance.setServiceName(serviceName); + instance.setHealthy(isHealthy); + instance.setMetadata(metadata); + return instance; + } +} diff --git a/spring-cloud-alibaba-sentinel-datasource/pom.xml b/spring-cloud-alibaba-sentinel-datasource/pom.xml index b5e9217a..141236e1 100644 --- a/spring-cloud-alibaba-sentinel-datasource/pom.xml +++ b/spring-cloud-alibaba-sentinel-datasource/pom.xml @@ -83,13 +83,18 @@ true + + javax.validation + validation-api + true + + org.springframework.boot spring-boot-starter-test test - \ No newline at end of file diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/NacosDataSourceWithAuthorization.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/NacosDataSourceWithAuthorization.java deleted file mode 100644 index 6d63c401..00000000 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/NacosDataSourceWithAuthorization.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (C) 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 - * - * http://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 org.springframework.cloud.alibaba.sentinel.datasource; - -import java.util.Properties; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -import com.alibaba.csp.sentinel.concurrent.NamedThreadFactory; -import com.alibaba.csp.sentinel.datasource.AbstractDataSource; -import com.alibaba.csp.sentinel.datasource.Converter; -import com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource; -import com.alibaba.csp.sentinel.log.RecordLog; -import com.alibaba.csp.sentinel.util.StringUtil; -import com.alibaba.nacos.api.NacosFactory; -import com.alibaba.nacos.api.config.ConfigService; -import com.alibaba.nacos.api.config.listener.Listener; - -/** - * {@link NacosDataSource} now is not support ak、sk,namespace and endpoint. This class may - * be delete when {@link NacosDataSource} support commercialized - * - * @author Jim - */ -public class NacosDataSourceWithAuthorization extends AbstractDataSource { - - private static final int DEFAULT_TIMEOUT = 3000; - - private final ExecutorService pool = new ThreadPoolExecutor(1, 1, 0, - TimeUnit.MILLISECONDS, new ArrayBlockingQueue(1), - new NamedThreadFactory("sentinel-nacos-auth-ds-update"), - new ThreadPoolExecutor.DiscardOldestPolicy()); - - private final Listener configListener; - private final Properties properties; - private final String dataId; - private final String groupId; - - private ConfigService configService = null; - - public NacosDataSourceWithAuthorization(final Properties properties, - final String groupId, final String dataId, Converter parser) { - super(parser); - if (StringUtil.isBlank(groupId) || StringUtil.isBlank(dataId)) { - throw new IllegalArgumentException(String - .format("Bad argument: groupId=[%s], dataId=[%s]", groupId, dataId)); - } - this.groupId = groupId; - this.dataId = dataId; - this.properties = properties; - this.configListener = new Listener() { - @Override - public Executor getExecutor() { - return pool; - } - - @Override - public void receiveConfigInfo(final String configInfo) { - RecordLog.info(String.format( - "[NacosDataSourceWithAuthorization] New property value received for %s", - properties.toString())); - T newValue = NacosDataSourceWithAuthorization.this.parser - .convert(configInfo); - // Update the new value to the property. - getProperty().updateValue(newValue); - } - }; - initNacosListener(); - loadInitialConfig(); - } - - private void loadInitialConfig() { - try { - T newValue = loadConfig(); - if (newValue == null) { - RecordLog.warn( - "[NacosDataSourceWithAuthorization] WARN: initial config is null, you may have to check your data source"); - } - getProperty().updateValue(newValue); - } - catch (Exception ex) { - RecordLog.warn( - "[NacosDataSourceWithAuthorization] Error when loading initial config", - ex); - } - } - - private void initNacosListener() { - try { - this.configService = NacosFactory.createConfigService(properties); - // Add config listener. - configService.addListener(dataId, groupId, configListener); - } - catch (Exception e) { - RecordLog.warn( - "[NacosDataSourceWithAuthorization] Error occurred when initializing Nacos data source", - e); - e.printStackTrace(); - } - } - - @Override - public String readSource() throws Exception { - if (configService == null) { - throw new IllegalStateException( - "Nacos config service has not been initialized or error occurred"); - } - return configService.getConfig(dataId, groupId, DEFAULT_TIMEOUT); - } - - @Override - public void close() { - if (configService != null) { - configService.removeListener(dataId, groupId, configListener); - } - pool.shutdownNow(); - } -} diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/RuleType.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/RuleType.java new file mode 100644 index 00000000..e64c360c --- /dev/null +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/RuleType.java @@ -0,0 +1,102 @@ +/* + * Copyright (C) 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 + * + * http://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 org.springframework.cloud.alibaba.sentinel.datasource; + +import org.springframework.cloud.alibaba.sentinel.datasource.config.AbstractDataSourceProperties; +import org.springframework.util.StringUtils; + +import com.alibaba.csp.sentinel.slots.block.AbstractRule; +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; + +/** + * Enum for {@link AbstractRule} class, using in + * {@link AbstractDataSourceProperties#ruleType} + * + * @author Jim + */ +public enum RuleType { + + /** + * flow + */ + FLOW("flow", FlowRule.class), + /** + * degrade + */ + DEGRADE("degrade", DegradeRule.class), + /** + * param flow + */ + PARAM_FLOW("param-flow", ParamFlowRule.class), + /** + * system + */ + SYSTEM("system", SystemRule.class), + /** + * authority + */ + AUTHORITY("authority", AuthorityRule.class); + + /** + * alias for {@link AbstractRule} + */ + private final String name; + + /** + * concrete {@link AbstractRule} class + */ + private final Class clazz; + + RuleType(String name, Class clazz) { + this.name = name; + this.clazz = clazz; + } + + public String getName() { + return name; + } + + public Class getClazz() { + return clazz; + } + + public static RuleType getByName(String name) { + if (StringUtils.isEmpty(name)) { + return null; + } + for (RuleType ruleType : RuleType.values()) { + if (name.equals(ruleType.getName())) { + return ruleType; + } + } + return null; + } + + public static RuleType getByClass(Class clazz) { + for (RuleType ruleType : RuleType.values()) { + if (clazz.equals(ruleType.getClazz())) { + return ruleType; + } + } + return null; + } + +} \ No newline at end of file diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourceConstants.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourceConstants.java index 8903b700..345b443d 100644 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourceConstants.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourceConstants.java @@ -23,14 +23,4 @@ public interface SentinelDataSourceConstants { String PROPERTY_PREFIX = "spring.cloud.sentinel"; - String NACOS_DATASOURCE_AK = PROPERTY_PREFIX + ".nacos.config.access-key"; - - String NACOS_DATASOURCE_SK = PROPERTY_PREFIX + ".nacos.config.secret-key"; - - String NACOS_DATASOURCE_NAMESPACE = PROPERTY_PREFIX + ".nacos.config.namespace"; - - String NACOS_DATASOURCE_ENDPOINT = PROPERTY_PREFIX + ".nacos.config.endpoint"; - - String PROJECT_NAME = PROPERTY_PREFIX + ".nacos.config.project-name"; - } diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/AbstractDataSourceProperties.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/AbstractDataSourceProperties.java index b8843537..7b6f5a49 100644 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/AbstractDataSourceProperties.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/AbstractDataSourceProperties.java @@ -1,5 +1,32 @@ +/* + * Copyright (C) 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 + * + * http://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 org.springframework.cloud.alibaba.sentinel.datasource.config; +import javax.validation.constraints.NotNull; + +import org.springframework.cloud.alibaba.sentinel.datasource.RuleType; + +import com.alibaba.csp.sentinel.datasource.AbstractDataSource; +import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRuleManager; +import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; +import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; +import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRuleManager; +import com.alibaba.csp.sentinel.slots.system.SystemRuleManager; + import com.fasterxml.jackson.annotation.JsonIgnore; /** @@ -9,10 +36,13 @@ import com.fasterxml.jackson.annotation.JsonIgnore; */ public class AbstractDataSourceProperties { + @NotNull private String dataType = "json"; + @NotNull + private RuleType ruleType; private String converterClass; @JsonIgnore - protected String factoryBeanName; + private final String factoryBeanName; public AbstractDataSourceProperties(String factoryBeanName) { this.factoryBeanName = factoryBeanName; @@ -26,6 +56,14 @@ public class AbstractDataSourceProperties { this.dataType = dataType; } + public RuleType getRuleType() { + return ruleType; + } + + public void setRuleType(RuleType ruleType) { + this.ruleType = ruleType; + } + public String getConverterClass() { return converterClass; } @@ -38,12 +76,29 @@ public class AbstractDataSourceProperties { return factoryBeanName; } - public void setFactoryBeanName(String factoryBeanName) { - this.factoryBeanName = factoryBeanName; - } - - public void preCheck() { + public void preCheck(String dataSourceName) { } -} + public void postRegister(AbstractDataSource dataSource) { + switch (this.getRuleType()) { + case FLOW: + FlowRuleManager.register2Property(dataSource.getProperty()); + break; + case DEGRADE: + DegradeRuleManager.register2Property(dataSource.getProperty()); + break; + case PARAM_FLOW: + ParamFlowRuleManager.register2Property(dataSource.getProperty()); + break; + case SYSTEM: + SystemRuleManager.register2Property(dataSource.getProperty()); + break; + case AUTHORITY: + AuthorityRuleManager.register2Property(dataSource.getProperty()); + break; + default: + break; + } + } +} \ No newline at end of file diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/ApolloDataSourceProperties.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/ApolloDataSourceProperties.java index 28d803ea..acfb222e 100644 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/ApolloDataSourceProperties.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/ApolloDataSourceProperties.java @@ -1,5 +1,23 @@ +/* + * Copyright (C) 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 + * + * http://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 org.springframework.cloud.alibaba.sentinel.datasource.config; +import javax.validation.constraints.NotNull; + import org.springframework.cloud.alibaba.sentinel.datasource.factorybean.ApolloDataSourceFactoryBean; /** @@ -10,7 +28,9 @@ import org.springframework.cloud.alibaba.sentinel.datasource.factorybean.ApolloD */ public class ApolloDataSourceProperties extends AbstractDataSourceProperties { + @NotNull private String namespaceName; + @NotNull private String flowRulesKey; private String defaultFlowRuleValue; diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/DataSourcePropertiesConfiguration.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/DataSourcePropertiesConfiguration.java index ccd1b9b1..1f270cca 100644 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/DataSourcePropertiesConfiguration.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/DataSourcePropertiesConfiguration.java @@ -4,6 +4,8 @@ import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; +import javax.validation.Valid; + import org.springframework.util.ObjectUtils; import com.fasterxml.jackson.annotation.JsonIgnore; @@ -19,12 +21,16 @@ import com.fasterxml.jackson.annotation.JsonIgnore; */ public class DataSourcePropertiesConfiguration { + @Valid private FileDataSourceProperties file; + @Valid private NacosDataSourceProperties nacos; + @Valid private ZookeeperDataSourceProperties zk; + @Valid private ApolloDataSourceProperties apollo; public DataSourcePropertiesConfiguration() { diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/FileDataSourceProperties.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/FileDataSourceProperties.java index d6594c2b..e1084260 100644 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/FileDataSourceProperties.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/FileDataSourceProperties.java @@ -1,7 +1,25 @@ +/* + * Copyright (C) 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 + * + * http://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 org.springframework.cloud.alibaba.sentinel.datasource.config; import java.io.IOException; +import javax.validation.constraints.NotNull; + import org.springframework.cloud.alibaba.sentinel.datasource.factorybean.FileRefreshableDataSourceFactoryBean; import org.springframework.util.ResourceUtils; import org.springframework.util.StringUtils; @@ -14,6 +32,7 @@ import org.springframework.util.StringUtils; */ public class FileDataSourceProperties extends AbstractDataSourceProperties { + @NotNull private String file; private String charset = "utf-8"; private long recommendRefreshMs = 3000L; @@ -56,16 +75,17 @@ public class FileDataSourceProperties extends AbstractDataSourceProperties { } @Override - public void preCheck() { - super.preCheck(); + public void preCheck(String dataSourceName) { + super.preCheck(dataSourceName); try { this.setFile( ResourceUtils.getFile(StringUtils.trimAllWhitespace(this.getFile())) .getAbsolutePath()); } catch (IOException e) { - throw new RuntimeException("[Sentinel Starter] " + " handle file [" - + this.getFile() + "] error: " + e.getMessage(), e); + throw new RuntimeException("[Sentinel Starter] DataSource " + dataSourceName + + " handle file [" + this.getFile() + "] error: " + e.getMessage(), + e); } } diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/NacosDataSourceProperties.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/NacosDataSourceProperties.java index 88831102..fd5eb195 100644 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/NacosDataSourceProperties.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/NacosDataSourceProperties.java @@ -1,8 +1,24 @@ +/* + * Copyright (C) 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 + * + * http://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 org.springframework.cloud.alibaba.sentinel.datasource.config; -import org.springframework.cloud.alibaba.sentinel.datasource.SentinelDataSourceConstants; +import javax.validation.constraints.NotNull; + import org.springframework.cloud.alibaba.sentinel.datasource.factorybean.NacosDataSourceFactoryBean; -import org.springframework.cloud.alibaba.sentinel.datasource.factorybean.NacosDataSourceWithAuthorizationFactoryBean; import org.springframework.util.StringUtils; /** @@ -14,10 +30,12 @@ import org.springframework.util.StringUtils; public class NacosDataSourceProperties extends AbstractDataSourceProperties { private String serverAddr; - private String groupId; - private String dataId; - // commercialized usage + @NotNull + private String groupId = "DEFAULT_GROUP"; + + @NotNull + private String dataId; private String endpoint; private String namespace; @@ -29,20 +47,10 @@ public class NacosDataSourceProperties extends AbstractDataSourceProperties { } @Override - public void preCheck() { - if (!StringUtils.isEmpty(System.getProperties() - .getProperty(SentinelDataSourceConstants.NACOS_DATASOURCE_ENDPOINT))) { - this.setServerAddr(null); - this.setFactoryBeanName( - NacosDataSourceWithAuthorizationFactoryBean.class.getName()); - this.setEndpoint(System.getProperties() - .getProperty(SentinelDataSourceConstants.NACOS_DATASOURCE_ENDPOINT)); - this.setNamespace(System.getProperties() - .getProperty(SentinelDataSourceConstants.NACOS_DATASOURCE_NAMESPACE)); - this.setAccessKey(System.getProperties() - .getProperty(SentinelDataSourceConstants.NACOS_DATASOURCE_AK)); - this.setSecretKey(System.getProperties() - .getProperty(SentinelDataSourceConstants.NACOS_DATASOURCE_SK)); + public void preCheck(String dataSourceName) { + if (StringUtils.isEmpty(serverAddr) && acmPropertiesInvalid()) { + throw new IllegalArgumentException( + "NacosDataSource properties value not correct. serverAddr is empty but there is empty value in accessKey, secretKey, endpoint, namespace property"); } } @@ -102,30 +110,9 @@ public class NacosDataSourceProperties extends AbstractDataSourceProperties { this.secretKey = secretKey; } - public static NacosDataSourceProperties buildFlowByEDAS() { - return buildByEDAS("flow"); + public boolean acmPropertiesInvalid() { + return StringUtils.isEmpty(endpoint) || StringUtils.isEmpty(accessKey) + || StringUtils.isEmpty(secretKey) || StringUtils.isEmpty(namespace); } - public static NacosDataSourceProperties buildDegradeByEDAS() { - return buildByEDAS("degrade"); - } - - public static NacosDataSourceProperties buildByEDAS(String type) { - NacosDataSourceProperties result = new NacosDataSourceProperties(); - result.setFactoryBeanName( - NacosDataSourceWithAuthorizationFactoryBean.class.getName()); - result.setEndpoint(System.getProperties() - .getProperty(SentinelDataSourceConstants.NACOS_DATASOURCE_ENDPOINT)); - result.setNamespace(System.getProperties() - .getProperty(SentinelDataSourceConstants.NACOS_DATASOURCE_NAMESPACE)); - result.setAccessKey(System.getProperties() - .getProperty(SentinelDataSourceConstants.NACOS_DATASOURCE_AK)); - result.setSecretKey(System.getProperties() - .getProperty(SentinelDataSourceConstants.NACOS_DATASOURCE_SK)); - result.setDataType("json"); - result.setDataId(System.getProperties() - .getProperty(SentinelDataSourceConstants.PROJECT_NAME) + "-" + type); - result.setGroupId("nacos-sentinel"); - return result; - } } diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/ZookeeperDataSourceProperties.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/ZookeeperDataSourceProperties.java index a1d61667..6138b872 100644 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/ZookeeperDataSourceProperties.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/config/ZookeeperDataSourceProperties.java @@ -1,5 +1,23 @@ +/* + * Copyright (C) 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 + * + * http://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 org.springframework.cloud.alibaba.sentinel.datasource.config; +import javax.validation.constraints.NotNull; + import org.springframework.cloud.alibaba.sentinel.datasource.factorybean.ZookeeperDataSourceFactoryBean; /** @@ -14,6 +32,7 @@ public class ZookeeperDataSourceProperties extends AbstractDataSourceProperties super(ZookeeperDataSourceFactoryBean.class.getName()); } + @NotNull private String serverAddr; private String path; diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/converter/JsonConverter.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/converter/JsonConverter.java index e0275b15..bb60dc19 100644 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/converter/JsonConverter.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/converter/JsonConverter.java @@ -1,27 +1,27 @@ +/* + * Copyright (C) 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 + * + * http://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 org.springframework.cloud.alibaba.sentinel.datasource.converter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.util.ObjectUtils; -import org.springframework.util.StringUtils; - -import com.alibaba.csp.sentinel.datasource.Converter; -import com.alibaba.csp.sentinel.slots.block.AbstractRule; 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.degrade.DegradeRuleManager; import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; -import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleUtil; import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule; import com.alibaba.csp.sentinel.slots.system.SystemRule; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; /** @@ -35,138 +35,10 @@ import com.fasterxml.jackson.databind.ObjectMapper; * @see ParamFlowRule * @see ObjectMapper */ -public class JsonConverter implements Converter> { +public class JsonConverter extends SentinelConverter { - private static final Logger logger = LoggerFactory.getLogger(JsonConverter.class); - - private final ObjectMapper objectMapper; - - public JsonConverter(ObjectMapper objectMapper) { - this.objectMapper = objectMapper; - } - - @Override - public List convert(String source) { - List ruleList = new ArrayList<>(); - if (StringUtils.isEmpty(source)) { - logger.warn( - "Sentinel JsonConverter can not convert rules because source is empty"); - return ruleList; - } - try { - List jsonArray = objectMapper.readValue(source, - new TypeReference>() { - }); - - for (Object obj : jsonArray) { - String itemJson = null; - try { - itemJson = objectMapper.writeValueAsString(obj); - } - catch (JsonProcessingException e) { - // won't be happen - } - - List rules = Arrays.asList(convertFlowRule(itemJson), - convertDegradeRule(itemJson), convertSystemRule(itemJson), - convertAuthorityRule(itemJson), convertParamFlowRule(itemJson)); - - List convertRuleList = new ArrayList<>(); - - for (AbstractRule rule : rules) { - if (!ObjectUtils.isEmpty(rule)) { - convertRuleList.add(rule); - } - } - - if (convertRuleList.size() == 0) { - logger.warn( - "Sentinel JsonConverter can not convert {} to any rules, ignore", - itemJson); - } - else if (convertRuleList.size() > 1) { - logger.warn( - "Sentinel JsonConverter convert {} and match multi rules, ignore", - itemJson); - } - else { - ruleList.add(convertRuleList.get(0)); - } - - } - - if (jsonArray.size() != ruleList.size()) { - logger.warn( - "Sentinel JsonConverter Source list size is not equals to Target List, maybe a " - + "part of json is invalid. Source List: " + jsonArray - + ", Target List: " + ruleList); - } - } - catch (Exception e) { - logger.error("Sentinel JsonConverter convert error: " + e.getMessage()); - throw new RuntimeException( - "Sentinel JsonConverter convert error: " + e.getMessage(), e); - } - return ruleList; - } - - private FlowRule convertFlowRule(String json) { - try { - FlowRule rule = objectMapper.readValue(json, FlowRule.class); - if (FlowRuleUtil.isValidRule(rule)) { - return rule; - } - } - catch (Exception e) { - // ignore - } - return null; - } - - private DegradeRule convertDegradeRule(String json) { - try { - DegradeRule rule = objectMapper.readValue(json, DegradeRule.class); - if (DegradeRuleManager.isValidRule(rule)) { - return rule; - } - } - catch (Exception e) { - // ignore - } - return null; - } - - private SystemRule convertSystemRule(String json) { - SystemRule rule = null; - try { - rule = objectMapper.readValue(json, SystemRule.class); - } - catch (Exception e) { - // ignore - } - return rule; - } - - private AuthorityRule convertAuthorityRule(String json) { - AuthorityRule rule = null; - try { - rule = objectMapper.readValue(json, AuthorityRule.class); - } - catch (Exception e) { - // ignore - } - return rule; - } - - private ParamFlowRule convertParamFlowRule(String json) { - ParamFlowRule rule = null; - try { - rule = objectMapper.readValue(json, ParamFlowRule.class); - } - catch (Exception e) { - // ignore - } - return rule; + public JsonConverter(ObjectMapper objectMapper, Class ruleClass) { + super(objectMapper, ruleClass); } } diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/converter/SentinelConverter.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/converter/SentinelConverter.java new file mode 100644 index 00000000..06d2f65b --- /dev/null +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/converter/SentinelConverter.java @@ -0,0 +1,133 @@ +/* + * Copyright (C) 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 + * + * http://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 org.springframework.cloud.alibaba.sentinel.datasource.converter; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.cloud.alibaba.sentinel.datasource.RuleType; +import org.springframework.util.StringUtils; + +import com.alibaba.csp.sentinel.datasource.Converter; +import com.alibaba.csp.sentinel.slots.block.AbstractRule; +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.degrade.DegradeRuleManager; +import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; +import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleUtil; +import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule; +import com.alibaba.csp.sentinel.slots.system.SystemRule; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * Convert sentinel rules for json or xml array Using strict mode to parse json or xml + * + * @author Jim + * @see FlowRule + * @see DegradeRule + * @see SystemRule + * @see AuthorityRule + * @see ParamFlowRule + * @see ObjectMapper + */ +public abstract class SentinelConverter + implements Converter> { + + private static final Logger log = LoggerFactory.getLogger(SentinelConverter.class); + + private final ObjectMapper objectMapper; + + private final Class ruleClass; + + public SentinelConverter(ObjectMapper objectMapper, Class ruleClass) { + this.objectMapper = objectMapper; + this.ruleClass = ruleClass; + } + + @Override + public List convert(String source) { + List ruleList = new ArrayList<>(); + if (StringUtils.isEmpty(source)) { + log.warn("converter can not convert rules because source is empty"); + return ruleList; + } + try { + List sourceArray = objectMapper.readValue(source, + new TypeReference>() { + }); + + for (Object obj : sourceArray) { + String item = null; + try { + item = objectMapper.writeValueAsString(obj); + } + catch (JsonProcessingException e) { + // won't be happen + } + + AbstractRule rule = convertRule(item); + if (rule != null) { + ruleList.add(rule); + } + + } + + if (ruleList.size() != sourceArray.size()) { + throw new IllegalArgumentException("convert " + ruleList.size() + + " rules but there are " + sourceArray.size() + + " rules from datasource. RuleClass: " + + ruleClass.getSimpleName()); + } + } + catch (Exception e) { + throw new RuntimeException("convert error: " + e.getMessage(), e); + } + return ruleList; + } + + private AbstractRule convertRule(String ruleStr) { + try { + final AbstractRule rule = objectMapper.readValue(ruleStr, ruleClass); + RuleType ruleType = RuleType.getByClass(ruleClass); + switch (ruleType) { + case FLOW: + if (!FlowRuleUtil.isValidRule((FlowRule) rule)) { + return null; + } + break; + case DEGRADE: + if (!DegradeRuleManager.isValidRule((DegradeRule) rule)) { + return null; + } + default: + break; + } + return rule; + } + catch (Exception e) { + // ignore + } + return null; + } + +} diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/converter/XmlConverter.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/converter/XmlConverter.java index 20961058..710a0da5 100644 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/converter/XmlConverter.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/converter/XmlConverter.java @@ -1,27 +1,28 @@ +/* + * Copyright (C) 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 + * + * http://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 org.springframework.cloud.alibaba.sentinel.datasource.converter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.util.ObjectUtils; -import org.springframework.util.StringUtils; - -import com.alibaba.csp.sentinel.datasource.Converter; -import com.alibaba.csp.sentinel.slots.block.AbstractRule; 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.degrade.DegradeRuleManager; import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; -import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleUtil; import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule; import com.alibaba.csp.sentinel.slots.system.SystemRule; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.xml.XmlMapper; /** @@ -33,139 +34,12 @@ import com.fasterxml.jackson.dataformat.xml.XmlMapper; * @see SystemRule * @see AuthorityRule * @see ParamFlowRule - * @see XmlMapper + * @see ObjectMapper */ -public class XmlConverter implements Converter> { +public class XmlConverter extends SentinelConverter { - private static final Logger logger = LoggerFactory.getLogger(XmlConverter.class); - - private final XmlMapper xmlMapper; - - public XmlConverter(XmlMapper xmlMapper) { - this.xmlMapper = xmlMapper; - } - - @Override - public List convert(String source) { - List ruleList = new ArrayList<>(); - if (StringUtils.isEmpty(source)) { - logger.warn( - "Sentinel XmlConverter can not convert rules because source is empty"); - return ruleList; - } - try { - List xmlArray = xmlMapper.readValue(source, - new TypeReference>() { - }); - - for (Object obj : xmlArray) { - String itemXml = null; - try { - itemXml = xmlMapper.writeValueAsString(obj); - } - catch (JsonProcessingException e) { - // won't be happen - } - - List rules = Arrays.asList(convertFlowRule(itemXml), - convertDegradeRule(itemXml), convertSystemRule(itemXml), - convertAuthorityRule(itemXml), convertParamFlowRule(itemXml)); - - List convertRuleList = new ArrayList<>(); - - for (AbstractRule rule : rules) { - if (!ObjectUtils.isEmpty(rule)) { - convertRuleList.add(rule); - } - } - - if (convertRuleList.size() == 0) { - logger.warn( - "Sentinel XmlConverter can not convert {} to any rules, ignore", - itemXml); - } - else if (convertRuleList.size() > 1) { - logger.warn( - "Sentinel XmlConverter convert {} and match multi rules, ignore", - itemXml); - } - else { - ruleList.add(convertRuleList.get(0)); - } - } - - if (xmlArray.size() != ruleList.size()) { - logger.warn( - "Sentinel XmlConverter Source list size is not equals to Target List, maybe a " - + "part of xml is invalid. Source List: " + xmlArray - + ", Target List: " + ruleList); - } - } - catch (Exception e) { - logger.error("Sentinel XmlConverter convert error: " + e.getMessage()); - throw new RuntimeException( - "Sentinel XmlConverter convert error: " + e.getMessage(), e); - } - return ruleList; - } - - private FlowRule convertFlowRule(String xml) { - try { - FlowRule rule = xmlMapper.readValue(xml, FlowRule.class); - if (FlowRuleUtil.isValidRule(rule)) { - return rule; - } - } - catch (Exception e) { - // ignore - } - return null; - } - - private DegradeRule convertDegradeRule(String xml) { - try { - DegradeRule rule = xmlMapper.readValue(xml, DegradeRule.class); - if (DegradeRuleManager.isValidRule(rule)) { - return rule; - } - } - catch (Exception e) { - // ignore - } - return null; - } - - private SystemRule convertSystemRule(String xml) { - SystemRule rule = null; - try { - rule = xmlMapper.readValue(xml, SystemRule.class); - } - catch (Exception e) { - // ignore - } - return rule; - } - - private AuthorityRule convertAuthorityRule(String xml) { - AuthorityRule rule = null; - try { - rule = xmlMapper.readValue(xml, AuthorityRule.class); - } - catch (Exception e) { - // ignore - } - return rule; - } - - private ParamFlowRule convertParamFlowRule(String json) { - ParamFlowRule rule = null; - try { - rule = xmlMapper.readValue(json, ParamFlowRule.class); - } - catch (Exception e) { - // ignore - } - return rule; + public XmlConverter(XmlMapper xmlMapper, Class ruleClass) { + super(xmlMapper, ruleClass); } } diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/NacosDataSourceFactoryBean.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/NacosDataSourceFactoryBean.java index 51218912..8a51bc55 100644 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/NacosDataSourceFactoryBean.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/NacosDataSourceFactoryBean.java @@ -1,9 +1,29 @@ +/* + * Copyright (C) 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 + * + * http://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 org.springframework.cloud.alibaba.sentinel.datasource.factorybean; +import java.util.Properties; + +import org.springframework.beans.factory.FactoryBean; +import org.springframework.util.StringUtils; + import com.alibaba.csp.sentinel.datasource.Converter; import com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource; - -import org.springframework.beans.factory.FactoryBean; +import com.alibaba.nacos.api.PropertyKeyConst; /** * A {@link FactoryBean} for creating {@link NacosDataSource} instance. @@ -13,55 +33,104 @@ import org.springframework.beans.factory.FactoryBean; */ public class NacosDataSourceFactoryBean implements FactoryBean { - private String serverAddr; - private String groupId; - private String dataId; - private Converter converter; + private String serverAddr; + private String groupId; + private String dataId; + private Converter converter; - @Override - public NacosDataSource getObject() throws Exception { - return new NacosDataSource(serverAddr, groupId, dataId, converter); - } + private String endpoint; + private String namespace; + private String accessKey; + private String secretKey; - @Override - public Class getObjectType() { - return NacosDataSource.class; - } + @Override + public NacosDataSource getObject() throws Exception { + Properties properties = new Properties(); + if (!StringUtils.isEmpty(this.serverAddr)) { + properties.setProperty(PropertyKeyConst.SERVER_ADDR, this.serverAddr); + } + else { + properties.setProperty(PropertyKeyConst.ACCESS_KEY, this.accessKey); + properties.setProperty(PropertyKeyConst.SECRET_KEY, this.secretKey); + properties.setProperty(PropertyKeyConst.ENDPOINT, this.endpoint); + } + if (!StringUtils.isEmpty(this.namespace)) { + properties.setProperty(PropertyKeyConst.NAMESPACE, this.namespace); + } + return new NacosDataSource(properties, groupId, dataId, converter); + } - @Override - public boolean isSingleton() { - return true; - } + @Override + public boolean isSingleton() { + return true; + } - public String getServerAddr() { - return serverAddr; - } + @Override + public Class getObjectType() { + return NacosDataSource.class; + } - public void setServerAddr(String serverAddr) { - this.serverAddr = serverAddr; - } + public String getServerAddr() { + return serverAddr; + } - public String getGroupId() { - return groupId; - } + public void setServerAddr(String serverAddr) { + this.serverAddr = serverAddr; + } - public void setGroupId(String groupId) { - this.groupId = groupId; - } + public String getGroupId() { + return groupId; + } - public String getDataId() { - return dataId; - } + public void setGroupId(String groupId) { + this.groupId = groupId; + } - public void setDataId(String dataId) { - this.dataId = dataId; - } + public String getDataId() { + return dataId; + } - public Converter getConverter() { - return converter; - } + public void setDataId(String dataId) { + this.dataId = dataId; + } - public void setConverter(Converter converter) { - this.converter = converter; - } + public Converter getConverter() { + return converter; + } + + public void setConverter(Converter converter) { + this.converter = converter; + } + + public String getEndpoint() { + return endpoint; + } + + public void setEndpoint(String endpoint) { + this.endpoint = endpoint; + } + + public String getNamespace() { + return namespace; + } + + public void setNamespace(String namespace) { + this.namespace = namespace; + } + + public String getAccessKey() { + return accessKey; + } + + public void setAccessKey(String accessKey) { + this.accessKey = accessKey; + } + + public String getSecretKey() { + return secretKey; + } + + public void setSecretKey(String secretKey) { + this.secretKey = secretKey; + } } diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/NacosDataSourceWithAuthorizationFactoryBean.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/NacosDataSourceWithAuthorizationFactoryBean.java deleted file mode 100644 index dabe65b9..00000000 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/NacosDataSourceWithAuthorizationFactoryBean.java +++ /dev/null @@ -1,106 +0,0 @@ -package org.springframework.cloud.alibaba.sentinel.datasource.factorybean; - -import java.util.Properties; - -import org.springframework.beans.factory.FactoryBean; -import org.springframework.cloud.alibaba.sentinel.datasource.NacosDataSourceWithAuthorization; - -import com.alibaba.csp.sentinel.datasource.Converter; -import com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource; -import com.alibaba.nacos.api.PropertyKeyConst; - -/** - * A {@link FactoryBean} for creating {@link NacosDataSource} instance. - * - * @author Jim - * @see NacosDataSource - */ -public class NacosDataSourceWithAuthorizationFactoryBean - implements FactoryBean { - - private String endpoint; - private String namespace; - private String accessKey; - private String secretKey; - - private String groupId; - private String dataId; - private Converter converter; - - @Override - public NacosDataSourceWithAuthorization getObject() throws Exception { - Properties properties = new Properties(); - properties.put(PropertyKeyConst.ACCESS_KEY, accessKey); - properties.put(PropertyKeyConst.SECRET_KEY, secretKey); - properties.put(PropertyKeyConst.NAMESPACE, namespace); - properties.put(PropertyKeyConst.ENDPOINT, endpoint); - return new NacosDataSourceWithAuthorization(properties, groupId, dataId, - converter); - } - - @Override - public Class getObjectType() { - return NacosDataSourceWithAuthorization.class; - } - - @Override - public boolean isSingleton() { - return true; - } - - public String getEndpoint() { - return endpoint; - } - - public void setEndpoint(String endpoint) { - this.endpoint = endpoint; - } - - public String getNamespace() { - return namespace; - } - - public void setNamespace(String namespace) { - this.namespace = namespace; - } - - public String getAccessKey() { - return accessKey; - } - - public void setAccessKey(String accessKey) { - this.accessKey = accessKey; - } - - public String getSecretKey() { - return secretKey; - } - - public void setSecretKey(String secretKey) { - this.secretKey = secretKey; - } - - public String getGroupId() { - return groupId; - } - - public void setGroupId(String groupId) { - this.groupId = groupId; - } - - public String getDataId() { - return dataId; - } - - public void setDataId(String dataId) { - this.dataId = dataId; - } - - public Converter getConverter() { - return converter; - } - - public void setConverter(Converter converter) { - this.converter = converter; - } -} diff --git a/spring-cloud-alibaba-sentinel/pom.xml b/spring-cloud-alibaba-sentinel/pom.xml index bcfd5d6a..e855b287 100644 --- a/spring-cloud-alibaba-sentinel/pom.xml +++ b/spring-cloud-alibaba-sentinel/pom.xml @@ -52,6 +52,12 @@ true + + org.springframework.cloud + spring-cloud-commons + true + + com.alibaba.csp sentinel-parameter-flow-control diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelConstants.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelConstants.java index aa6079ac..0c2a9d09 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelConstants.java +++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelConstants.java @@ -23,7 +23,10 @@ public interface SentinelConstants { String PROPERTY_PREFIX = "spring.cloud.sentinel"; - // commercialized + String BLOCK_TYPE = "block"; + String FALLBACK_TYPE = "fallback"; + + // commercialization String FLOW_DATASOURCE_NAME = "edas-flow"; String DEGRADE_DATASOURCE_NAME = "edas-degrade"; diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelProperties.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelProperties.java index 3f174118..274d36de 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelProperties.java +++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelProperties.java @@ -20,77 +20,76 @@ import java.util.List; import java.util.Map; import java.util.TreeMap; +import javax.validation.Valid; + import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.boot.context.properties.NestedConfigurationProperty; import org.springframework.cloud.alibaba.sentinel.datasource.config.DataSourcePropertiesConfiguration; import org.springframework.core.Ordered; +import org.springframework.validation.annotation.Validated; import com.alibaba.csp.sentinel.config.SentinelConfig; import com.alibaba.csp.sentinel.log.LogBase; import com.alibaba.csp.sentinel.transport.config.TransportConfig; /** + * {@link ConfigurationProperties} for Sentinel. + * * @author xiaojing * @author hengyunabc * @author jiashuai.xie * @author Jim */ @ConfigurationProperties(prefix = SentinelConstants.PROPERTY_PREFIX) +@Validated public class SentinelProperties { /** - * earlier initialize heart-beat when the spring container starts when the - * transport dependency is on classpath ,the configuration is effective + * Earlier initialize heart-beat when the spring container starts when the transport + * dependency is on classpath, the configuration is effective. */ private boolean eager = false; /** - * enable sentinel auto configure, the default value is true + * Enable sentinel auto configure, the default value is true. */ private boolean enabled = true; /** - * configurations about datasource, like 'nacos', 'apollo', 'file', 'zookeeper' + * Configurations about datasource, like 'nacos', 'apollo', 'file', 'zookeeper'. */ + @Valid private Map datasource = new TreeMap<>( String.CASE_INSENSITIVE_ORDER); /** - * transport configuration about dashboard and client + * Transport configuration about dashboard and client. */ - @NestedConfigurationProperty private Transport transport = new Transport(); /** - * metric configuration about resource + * Metric configuration about resource. */ - @NestedConfigurationProperty private Metric metric = new Metric(); /** - * web servlet configuration when the application is web ,the configuration is - * effective + * Web servlet configuration when the application is web, the configuration is + * effective. */ - @NestedConfigurationProperty private Servlet servlet = new Servlet(); /** - * sentinel filter when the application is web ,the configuration is effective - * + * Sentinel filter when the application is web, the configuration is effective. */ - @NestedConfigurationProperty private Filter filter = new Filter(); /** - * flow configuration + * Sentinel Flow configuration. */ - @NestedConfigurationProperty private Flow flow = new Flow(); /** - * sentinel log configuration {@link LogBase} + * Sentinel log configuration {@link LogBase}. */ - @NestedConfigurationProperty private Log log = new Log(); public boolean isEager() { @@ -168,7 +167,7 @@ public class SentinelProperties { public static class Flow { /** - * the cold factor {@link SentinelConfig#COLD_FACTOR} + * The cold factor {@link SentinelConfig#COLD_FACTOR}. */ private String coldFactor = "3"; @@ -185,7 +184,7 @@ public class SentinelProperties { public static class Servlet { /** - * The process page when the flow control is triggered + * The process page when the flow control is triggered. */ private String blockPage; @@ -201,17 +200,17 @@ public class SentinelProperties { public static class Metric { /** - * the metric file size {@link SentinelConfig#SINGLE_METRIC_FILE_SIZE} + * The metric file size {@link SentinelConfig#SINGLE_METRIC_FILE_SIZE}. */ private String fileSingleSize; /** - * the total metric file count {@link SentinelConfig#TOTAL_METRIC_FILE_COUNT} + * The total metric file count {@link SentinelConfig#TOTAL_METRIC_FILE_COUNT}. */ private String fileTotalCount; /** - * charset when sentinel write or search metric file + * Charset when sentinel write or search metric file. * {@link SentinelConfig#CHARSET} */ private String charset = "UTF-8"; @@ -244,22 +243,28 @@ public class SentinelProperties { public static class Transport { /** - * sentinel api port,default value is 8719 {@link TransportConfig#SERVER_PORT} + * Sentinel api port, default value is 8719 {@link TransportConfig#SERVER_PORT}. */ private String port = "8719"; /** - * sentinel dashboard address, won't try to connect dashboard when address is - * empty {@link TransportConfig#CONSOLE_SERVER} + * Sentinel dashboard address, won't try to connect dashboard when address is + * empty {@link TransportConfig#CONSOLE_SERVER}. */ private String dashboard = ""; /** - * send heartbeat interval millisecond - * {@link TransportConfig#HEARTBEAT_INTERVAL_MS} + * Send heartbeat interval millisecond + * {@link TransportConfig#HEARTBEAT_INTERVAL_MS}. */ private String heartbeatIntervalMs; + /** + * Get heartbeat client local ip. If the client ip not configured, it will be the + * address of local host. + */ + private String clientIp; + public String getHeartbeatIntervalMs() { return heartbeatIntervalMs; } @@ -284,17 +289,24 @@ public class SentinelProperties { this.dashboard = dashboard; } + public String getClientIp() { + return clientIp; + } + + public void setClientIp(String clientIp) { + this.clientIp = clientIp; + } } public static class Filter { /** - * sentinel filter chain order. + * Sentinel filter chain order. */ private int order = Ordered.HIGHEST_PRECEDENCE; /** - * URL pattern for sentinel filter,default is /* + * URL pattern for sentinel filter, default is /* */ private List urlPatterns; @@ -318,12 +330,12 @@ public class SentinelProperties { public static class Log { /** - * sentinel log base dir + * Sentinel log base dir. */ private String dir; /** - * distinguish the log file by pid number + * Distinguish the log file by pid number. */ private boolean switchPid = false; diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelWebAutoConfiguration.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelWebAutoConfiguration.java index ee8e9b8c..0280fb1d 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelWebAutoConfiguration.java +++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelWebAutoConfiguration.java @@ -21,8 +21,6 @@ import java.util.List; import javax.servlet.Filter; -import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -33,6 +31,8 @@ import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter; + /** * @author xiaojing */ @@ -42,38 +42,33 @@ import org.springframework.context.annotation.Configuration; @EnableConfigurationProperties(SentinelProperties.class) public class SentinelWebAutoConfiguration { - private static final Logger logger = LoggerFactory - .getLogger(SentinelWebAutoConfiguration.class); + private static final Logger log = LoggerFactory + .getLogger(SentinelWebAutoConfiguration.class); - @Autowired - private SentinelProperties properties; + @Autowired + private SentinelProperties properties; - @Bean - public FilterRegistrationBean servletRequestListener() { - FilterRegistrationBean registration = new FilterRegistrationBean(); + @Bean + public FilterRegistrationBean servletRequestListener() { + FilterRegistrationBean registration = new FilterRegistrationBean(); - SentinelProperties.Filter filterConfig = properties.getFilter(); + SentinelProperties.Filter filterConfig = properties.getFilter(); - if (null == filterConfig) { - filterConfig = new SentinelProperties.Filter(); - properties.setFilter(filterConfig); - } + if (filterConfig.getUrlPatterns() == null + || filterConfig.getUrlPatterns().isEmpty()) { + List defaultPatterns = new ArrayList<>(); + defaultPatterns.add("/*"); + filterConfig.setUrlPatterns(defaultPatterns); + } - if (filterConfig.getUrlPatterns() == null - || filterConfig.getUrlPatterns().isEmpty()) { - List defaultPatterns = new ArrayList<>(); - defaultPatterns.add("/*"); - filterConfig.setUrlPatterns(defaultPatterns); - } + registration.addUrlPatterns(filterConfig.getUrlPatterns().toArray(new String[0])); + Filter filter = new CommonFilter(); + registration.setFilter(filter); + registration.setOrder(filterConfig.getOrder()); + log.info("[Sentinel Starter] register Sentinel with urlPatterns: {}.", + filterConfig.getUrlPatterns()); + return registration; - registration.addUrlPatterns(filterConfig.getUrlPatterns().toArray(new String[0])); - Filter filter = new CommonFilter(); - registration.setFilter(filter); - registration.setOrder(filterConfig.getOrder()); - logger.info("[Sentinel Starter] register Sentinel with urlPatterns: {}.", - filterConfig.getUrlPatterns()); - return registration; - - } + } } \ No newline at end of file diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/BlockClassRegistry.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/BlockClassRegistry.java index 3a3b967f..42eeca3c 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/BlockClassRegistry.java +++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/BlockClassRegistry.java @@ -27,33 +27,33 @@ import com.alibaba.csp.sentinel.util.StringUtil; */ final class BlockClassRegistry { - private static final Map FALLBACK_MAP = new ConcurrentHashMap<>(); - private static final Map BLOCK_HANDLER_MAP = new ConcurrentHashMap<>(); + private static final Map FALLBACK_MAP = new ConcurrentHashMap<>(); + private static final Map BLOCK_HANDLER_MAP = new ConcurrentHashMap<>(); - static Method lookupFallback(Class clazz, String name) { - return FALLBACK_MAP.get(getKey(clazz, name)); - } + static Method lookupFallback(Class clazz, String name) { + return FALLBACK_MAP.get(getKey(clazz, name)); + } - static Method lookupBlockHandler(Class clazz, String name) { - return BLOCK_HANDLER_MAP.get(getKey(clazz, name)); - } + static Method lookupBlockHandler(Class clazz, String name) { + return BLOCK_HANDLER_MAP.get(getKey(clazz, name)); + } - static void updateFallbackFor(Class clazz, String name, Method method) { - if (clazz == null || StringUtil.isBlank(name)) { - throw new IllegalArgumentException("Bad argument"); - } - FALLBACK_MAP.put(getKey(clazz, name), method); - } + static void updateFallbackFor(Class clazz, String name, Method method) { + if (clazz == null || StringUtil.isBlank(name)) { + throw new IllegalArgumentException("Bad argument"); + } + FALLBACK_MAP.put(getKey(clazz, name), method); + } - static void updateBlockHandlerFor(Class clazz, String name, Method method) { - if (clazz == null || StringUtil.isBlank(name)) { - throw new IllegalArgumentException("Bad argument"); - } - BLOCK_HANDLER_MAP.put(getKey(clazz, name), method); - } + static void updateBlockHandlerFor(Class clazz, String name, Method method) { + if (clazz == null || StringUtil.isBlank(name)) { + throw new IllegalArgumentException("Bad argument"); + } + BLOCK_HANDLER_MAP.put(getKey(clazz, name), method); + } - private static String getKey(Class clazz, String name) { - return String.format("%s:%s", clazz.getCanonicalName(), name); - } + private static String getKey(Class clazz, String name) { + return String.format("%s:%s", clazz.getCanonicalName(), name); + } } diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelAutoConfiguration.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelAutoConfiguration.java index 317d27c8..3c908bec 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelAutoConfiguration.java +++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelAutoConfiguration.java @@ -20,6 +20,7 @@ import javax.annotation.PostConstruct; 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; @@ -27,10 +28,12 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.cloud.alibaba.sentinel.SentinelProperties; import org.springframework.cloud.alibaba.sentinel.datasource.converter.JsonConverter; import org.springframework.cloud.alibaba.sentinel.datasource.converter.XmlConverter; +import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.util.StringUtils; +import com.alibaba.csp.sentinel.adapter.servlet.callback.RequestOriginParser; import com.alibaba.csp.sentinel.adapter.servlet.callback.UrlBlockHandler; import com.alibaba.csp.sentinel.adapter.servlet.callback.UrlCleaner; import com.alibaba.csp.sentinel.adapter.servlet.callback.WebCallbackManager; @@ -39,6 +42,11 @@ 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.alibaba.csp.sentinel.util.AppNameUtil; @@ -47,6 +55,7 @@ import com.fasterxml.jackson.dataformat.xml.XmlMapper; /** * @author xiaojing + * @author jiashuai.xie * @author Jim */ @Configuration @@ -66,8 +75,20 @@ public class SentinelAutoConfiguration { @Autowired(required = false) private UrlBlockHandler urlBlockHandler; + @Autowired(required = false) + private RequestOriginParser requestOriginParser; + @PostConstruct private void init() { + if (StringUtils.isEmpty(System.getProperty(LogBase.LOG_DIR)) + && StringUtils.hasText(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(AppNameUtil.APP_NAME)) && StringUtils.hasText(projectName)) { System.setProperty(AppNameUtil.APP_NAME, projectName); @@ -88,6 +109,11 @@ public class SentinelAutoConfiguration { System.setProperty(TransportConfig.HEARTBEAT_INTERVAL_MS, properties.getTransport().getHeartbeatIntervalMs()); } + if (StringUtils.isEmpty(System.getProperty(TransportConfig.HEARTBEAT_CLIENT_IP)) + && StringUtils.hasText(properties.getTransport().getClientIp())) { + System.setProperty(TransportConfig.HEARTBEAT_CLIENT_IP, + properties.getTransport().getClientIp()); + } if (StringUtils.isEmpty(System.getProperty(SentinelConfig.CHARSET)) && StringUtils.hasText(properties.getMetric().getCharset())) { System.setProperty(SentinelConfig.CHARSET, @@ -110,30 +136,25 @@ public class SentinelAutoConfiguration { System.setProperty(SentinelConfig.COLD_FACTOR, properties.getFlow().getColdFactor()); } - if (StringUtils.isEmpty(System.getProperty(LogBase.LOG_DIR)) - && StringUtils.hasText(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.hasText(properties.getServlet().getBlockPage())) { WebServletConfig.setBlockPage(properties.getServlet().getBlockPage()); } + if (urlBlockHandler != null) { WebCallbackManager.setUrlBlockHandler(urlBlockHandler); } if (urlCleaner != null) { WebCallbackManager.setUrlCleaner(urlCleaner); } + if (requestOriginParser != null) { + WebCallbackManager.setRequestOriginParser(requestOriginParser); + } // earlier initialize if (properties.isEager()) { InitExecutor.doInit(); } + } @Bean @@ -145,34 +166,78 @@ public class SentinelAutoConfiguration { @Bean @ConditionalOnMissingBean @ConditionalOnClass(name = "org.springframework.web.client.RestTemplate") - public SentinelBeanPostProcessor sentinelBeanPostProcessor() { - return new SentinelBeanPostProcessor(); + public SentinelBeanPostProcessor sentinelBeanPostProcessor( + ApplicationContext applicationContext) { + return new SentinelBeanPostProcessor(applicationContext); } @Bean - public SentinelDataSourceHandler sentinelDataSourceHandler() { - return new SentinelDataSourceHandler(); + public SentinelDataSourceHandler sentinelDataSourceHandler( + DefaultListableBeanFactory beanFactory) { + return new SentinelDataSourceHandler(beanFactory); } - @Bean("sentinel-json-converter") - public JsonConverter jsonConverter() { - return new JsonConverter(objectMapper()); - } + protected static class SentinelConverterConfiguration { + + private ObjectMapper objectMapper = new ObjectMapper(); + + @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); + } - private ObjectMapper objectMapper() { - return new ObjectMapper(); } @ConditionalOnClass(XmlMapper.class) protected static class SentinelXmlConfiguration { - @Bean("sentinel-xml-converter") - public XmlConverter xmlConverter() { - return new XmlConverter(xmlMapper()); + + private XmlMapper xmlMapper = new XmlMapper(); + + @Bean("sentinel-xml-flow-converter") + public XmlConverter xmlFlowConverter() { + return new XmlConverter(xmlMapper, FlowRule.class); } - private XmlMapper xmlMapper() { - return new XmlMapper(); + @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/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelBeanPostProcessor.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelBeanPostProcessor.java index 4fb9a6cf..7b44dca7 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelBeanPostProcessor.java +++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelBeanPostProcessor.java @@ -16,21 +16,34 @@ package org.springframework.cloud.alibaba.sentinel.custom; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import java.util.concurrent.ConcurrentHashMap; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor; import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.cloud.alibaba.sentinel.SentinelConstants; import org.springframework.cloud.alibaba.sentinel.annotation.SentinelRestTemplate; import org.springframework.context.ApplicationContext; import org.springframework.core.type.StandardMethodMetadata; +import org.springframework.core.type.classreading.MethodMetadataReadingVisitor; +import org.springframework.http.HttpRequest; +import org.springframework.http.client.ClientHttpRequestExecution; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; import org.springframework.web.client.RestTemplate; +import com.alibaba.csp.sentinel.slots.block.BlockException; + /** * PostProcessor handle @SentinelRestTemplate Annotation, add interceptor for RestTemplate * @@ -40,8 +53,14 @@ import org.springframework.web.client.RestTemplate; */ public class SentinelBeanPostProcessor implements MergedBeanDefinitionPostProcessor { - @Autowired - private ApplicationContext applicationContext; + private static final Logger log = LoggerFactory + .getLogger(SentinelBeanPostProcessor.class); + + private final ApplicationContext applicationContext; + + public SentinelBeanPostProcessor(ApplicationContext applicationContext) { + this.applicationContext = applicationContext; + } private ConcurrentHashMap cache = new ConcurrentHashMap<>(); @@ -49,21 +68,113 @@ public class SentinelBeanPostProcessor implements MergedBeanDefinitionPostProces public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName) { if (checkSentinelProtect(beanDefinition, beanType)) { - SentinelRestTemplate sentinelRestTemplate = ((StandardMethodMetadata) beanDefinition - .getSource()).getIntrospectedMethod() - .getAnnotation(SentinelRestTemplate.class); + SentinelRestTemplate sentinelRestTemplate; + if (beanDefinition.getSource() instanceof StandardMethodMetadata) { + sentinelRestTemplate = ((StandardMethodMetadata) beanDefinition + .getSource()).getIntrospectedMethod() + .getAnnotation(SentinelRestTemplate.class); + } + else { + sentinelRestTemplate = beanDefinition.getResolvedFactoryMethod() + .getAnnotation(SentinelRestTemplate.class); + } + // check class and method validation + checkSentinelRestTemplate(sentinelRestTemplate, beanName); cache.put(beanName, sentinelRestTemplate); } } + private void checkSentinelRestTemplate(SentinelRestTemplate sentinelRestTemplate, + String beanName) { + checkBlock4RestTemplate(sentinelRestTemplate.blockHandlerClass(), + sentinelRestTemplate.blockHandler(), beanName, + SentinelConstants.BLOCK_TYPE); + checkBlock4RestTemplate(sentinelRestTemplate.fallbackClass(), + sentinelRestTemplate.fallback(), beanName, + SentinelConstants.FALLBACK_TYPE); + } + + private void checkBlock4RestTemplate(Class blockClass, String blockMethod, + String beanName, String type) { + if (blockClass == void.class && StringUtils.isEmpty(blockMethod)) { + return; + } + if (blockClass != void.class && StringUtils.isEmpty(blockMethod)) { + log.error( + "{} class attribute exists but {} method attribute is not exists in bean[{}]", + type, type, beanName); + throw new IllegalArgumentException(type + " class attribute exists but " + + type + " method attribute is not exists in bean[" + beanName + "]"); + } + else if (blockClass == void.class && !StringUtils.isEmpty(blockMethod)) { + log.error( + "{} method attribute exists but {} class attribute is not exists in bean[{}]", + type, type, beanName); + throw new IllegalArgumentException(type + " method attribute exists but " + + type + " class attribute is not exists in bean[" + beanName + "]"); + } + Class[] args = new Class[] { HttpRequest.class, byte[].class, + ClientHttpRequestExecution.class, BlockException.class }; + + List argList = new ArrayList<>(); + for (Class argClazz : args) { + argList.add(argClazz.getSimpleName()); + } + String argsStr = Arrays.toString(argList.toArray()); + Method foundMethod = ClassUtils.getStaticMethod(blockClass, blockMethod, args); + if (foundMethod == null) { + log.error( + "{} static method can not be found in bean[{}]. The right method signature is {}#{}{}, please check your class name, method name and arguments", + type, beanName, blockClass.getName(), blockMethod, argsStr); + throw new IllegalArgumentException(type + + " static method can not be found in bean[" + beanName + + "]. The right method signature is " + blockClass.getName() + "#" + + blockMethod + argsStr + + ", please check your class name, method name and arguments"); + } + + if (!ClientHttpResponse.class.isAssignableFrom(foundMethod.getReturnType())) { + log.error( + "{} method return value in bean[{}] is not ClientHttpResponse: {}#{}{}", + type, beanName, blockClass.getName(), blockMethod, argsStr); + throw new IllegalArgumentException(type + " method return value in bean[" + + beanName + "] is not ClientHttpResponse: " + blockClass.getName() + + "#" + blockMethod + argsStr); + } + if (type.equals(SentinelConstants.BLOCK_TYPE)) { + BlockClassRegistry.updateBlockHandlerFor(blockClass, blockMethod, + foundMethod); + } + else { + BlockClassRegistry.updateFallbackFor(blockClass, blockMethod, foundMethod); + } + } + private boolean checkSentinelProtect(RootBeanDefinition beanDefinition, Class beanType) { return beanType == RestTemplate.class - && beanDefinition.getSource() instanceof StandardMethodMetadata + && (checkStandardMethodMetadata(beanDefinition) + || checkMethodMetadataReadingVisitor(beanDefinition)); + } + + private boolean checkStandardMethodMetadata(RootBeanDefinition beanDefinition) { + return beanDefinition.getSource() instanceof StandardMethodMetadata && ((StandardMethodMetadata) beanDefinition.getSource()) .isAnnotated(SentinelRestTemplate.class.getName()); } + private boolean checkMethodMetadataReadingVisitor(RootBeanDefinition beanDefinition) { + return beanDefinition.getSource() instanceof MethodMetadataReadingVisitor + && ((MethodMetadataReadingVisitor) beanDefinition.getSource()) + .isAnnotated(SentinelRestTemplate.class.getName()); + } + + @Override + public Object postProcessBeforeInitialization(Object o, String s) + throws BeansException { + return o; + } + @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { @@ -84,7 +195,7 @@ public class SentinelBeanPostProcessor implements MergedBeanDefinitionPostProces SentinelProtectInterceptor sentinelProtectInterceptor = applicationContext .getBean(interceptorBeanName.toString(), SentinelProtectInterceptor.class); - restTemplate.getInterceptors().add(sentinelProtectInterceptor); + restTemplate.getInterceptors().add(0, sentinelProtectInterceptor); } return bean; } @@ -103,10 +214,4 @@ public class SentinelBeanPostProcessor implements MergedBeanDefinitionPostProces interceptorBeanDefinition); } - @Override - public Object postProcessBeforeInitialization(Object bean, String beanName) - throws BeansException { - return bean; - } - } \ No newline at end of file diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelCircuitBreakerConfiguration.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelCircuitBreakerConfiguration.java new file mode 100644 index 00000000..a13acf8a --- /dev/null +++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelCircuitBreakerConfiguration.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 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 + * + * http://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 org.springframework.cloud.alibaba.sentinel.custom; + +import org.springframework.context.annotation.Configuration; + +/** + * @author lengleng + *

+ * support @EnableCircuitBreaker ,Do nothing + */ +@Configuration +public class SentinelCircuitBreakerConfiguration { +} diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelDataSourceHandler.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelDataSourceHandler.java index 8489c7d8..9e79ec48 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelDataSourceHandler.java +++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelDataSourceHandler.java @@ -17,47 +17,29 @@ package org.springframework.cloud.alibaba.sentinel.custom; import java.lang.reflect.Field; -import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.TreeMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.SmartInitializingSingleton; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.DefaultListableBeanFactory; -import org.springframework.boot.context.event.ApplicationReadyEvent; -import org.springframework.cloud.alibaba.sentinel.SentinelConstants; import org.springframework.cloud.alibaba.sentinel.SentinelProperties; -import org.springframework.cloud.alibaba.sentinel.datasource.SentinelDataSourceConstants; import org.springframework.cloud.alibaba.sentinel.datasource.config.AbstractDataSourceProperties; import org.springframework.cloud.alibaba.sentinel.datasource.config.DataSourcePropertiesConfiguration; -import org.springframework.cloud.alibaba.sentinel.datasource.config.NacosDataSourceProperties; import org.springframework.cloud.alibaba.sentinel.datasource.converter.JsonConverter; import org.springframework.cloud.alibaba.sentinel.datasource.converter.XmlConverter; -import org.springframework.context.event.EventListener; import org.springframework.util.CollectionUtils; import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; import com.alibaba.csp.sentinel.datasource.AbstractDataSource; import com.alibaba.csp.sentinel.datasource.ReadableDataSource; -import com.alibaba.csp.sentinel.property.SentinelProperty; import com.alibaba.csp.sentinel.slots.block.AbstractRule; -import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule; -import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRuleManager; -import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; -import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; -import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; -import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; -import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule; -import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRuleManager; -import com.alibaba.csp.sentinel.slots.system.SystemRule; -import com.alibaba.csp.sentinel.slots.system.SystemRuleManager; /** * Sentinel {@link ReadableDataSource} Handler Handle the configurations of @@ -68,113 +50,53 @@ import com.alibaba.csp.sentinel.slots.system.SystemRuleManager; * @see JsonConverter * @see XmlConverter */ -public class SentinelDataSourceHandler { +public class SentinelDataSourceHandler implements SmartInitializingSingleton { - private static final Logger logger = LoggerFactory + private static final Logger log = LoggerFactory .getLogger(SentinelDataSourceHandler.class); private List dataTypeList = Arrays.asList("json", "xml"); - private List> rulesList = Arrays.asList(FlowRule.class, - DegradeRule.class, SystemRule.class, AuthorityRule.class, - ParamFlowRule.class); + private final String DATA_TYPE_FIELD = "dataType"; + private final String CUSTOM_DATA_TYPE = "custom"; + private final String CONVERTER_CLASS_FIELD = "converterClass"; - private List dataSourceBeanNameList = Collections - .synchronizedList(new ArrayList()); + private final DefaultListableBeanFactory beanFactory; - private final String DATATYPE_FIELD = "dataType"; - private final String CUSTOM_DATATYPE = "custom"; - private final String CONVERTERCLASS_FIELD = "converterClass"; + public SentinelDataSourceHandler(DefaultListableBeanFactory beanFactory) { + this.beanFactory = beanFactory; + } @Autowired private SentinelProperties sentinelProperties; - @EventListener(classes = ApplicationReadyEvent.class) - public void buildDataSource(ApplicationReadyEvent event) throws Exception { - - DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) event - .getApplicationContext().getAutowireCapableBeanFactory(); - - // commercialization - if (!StringUtils.isEmpty(System.getProperties() - .getProperty(SentinelDataSourceConstants.NACOS_DATASOURCE_ENDPOINT))) { - Map newDataSourceMap = new TreeMap<>( - String.CASE_INSENSITIVE_ORDER); - for (Map.Entry entry : sentinelProperties - .getDatasource().entrySet()) { - if (entry.getValue().getValidDataSourceProperties() - .getClass() != NacosDataSourceProperties.class) { - newDataSourceMap.put(entry.getKey(), entry.getValue()); - } - } - newDataSourceMap.put(SentinelConstants.FLOW_DATASOURCE_NAME, - new DataSourcePropertiesConfiguration( - NacosDataSourceProperties.buildFlowByEDAS())); - newDataSourceMap.put(SentinelConstants.DEGRADE_DATASOURCE_NAME, - new DataSourcePropertiesConfiguration( - NacosDataSourceProperties.buildDegradeByEDAS())); - sentinelProperties.setDatasource(newDataSourceMap); - } - - for (Map.Entry entry : sentinelProperties - .getDatasource().entrySet()) { - String dataSourceName = entry.getKey(); - DataSourcePropertiesConfiguration dataSourceProperties = entry.getValue(); - - List validFields = dataSourceProperties.getValidField(); - if (validFields.size() != 1) { - logger.error("[Sentinel Starter] DataSource " + dataSourceName - + " multi datasource active and won't loaded: " - + dataSourceProperties.getValidField()); - return; - } - - AbstractDataSourceProperties abstractDataSourceProperties = dataSourceProperties - .getValidDataSourceProperties(); - abstractDataSourceProperties.preCheck(); - registerBean(beanFactory, abstractDataSourceProperties, - dataSourceName + "-sentinel-" + validFields.get(0) + "-datasource"); - - } - - for (String beanName : dataSourceBeanNameList) { - ReadableDataSource dataSource = beanFactory.getBean(beanName, - ReadableDataSource.class); - Object ruleConfig; + @Override + public void afterSingletonsInstantiated() { + for (String dataSourceName : sentinelProperties.getDatasource().keySet()) { + DataSourcePropertiesConfiguration dataSourceProperties = sentinelProperties + .getDatasource().get(dataSourceName); try { - logger.info("[Sentinel Starter] DataSource " + beanName - + " start to loadConfig"); - ruleConfig = dataSource.loadConfig(); + List validFields = dataSourceProperties.getValidField(); + if (validFields.size() != 1) { + log.error("[Sentinel Starter] DataSource " + dataSourceName + + " multi datasource active and won't loaded: " + + dataSourceProperties.getValidField()); + return; + } + AbstractDataSourceProperties abstractDataSourceProperties = dataSourceProperties + .getValidDataSourceProperties(); + abstractDataSourceProperties.preCheck(dataSourceName); + registerBean(abstractDataSourceProperties, dataSourceName + "-sentinel-" + + validFields.get(0) + "-datasource"); } catch (Exception e) { - logger.error("[Sentinel Starter] DataSource " + beanName - + " loadConfig error: " + e.getMessage(), e); - return; - } - SentinelProperty sentinelProperty = dataSource.getProperty(); - Class ruleType = getAndCheckRuleType(ruleConfig, beanName); - if (ruleType != null) { - if (ruleType == FlowRule.class) { - FlowRuleManager.register2Property(sentinelProperty); - } - else if (ruleType == DegradeRule.class) { - DegradeRuleManager.register2Property(sentinelProperty); - } - else if (ruleType == SystemRule.class) { - SystemRuleManager.register2Property(sentinelProperty); - } - else if (ruleType == AuthorityRule.class) { - AuthorityRuleManager.register2Property(sentinelProperty); - } - else { - ParamFlowRuleManager.register2Property(sentinelProperty); - } + log.error("[Sentinel Starter] DataSource " + dataSourceName + + " build error: " + e.getMessage(), e); } } } - private void registerBean(DefaultListableBeanFactory beanFactory, - final AbstractDataSourceProperties dataSourceProperties, + private void registerBean(final AbstractDataSourceProperties dataSourceProperties, String dataSourceName) { Map propertyMap = new HashMap<>(); @@ -187,15 +109,16 @@ public class SentinelDataSourceHandler { } } catch (IllegalAccessException e) { - logger.error("[Sentinel Starter] DataSource " + dataSourceName - + " field: " + field.getName() + " invoke error"); + log.error("[Sentinel Starter] DataSource " + dataSourceName + " field: " + + field.getName() + " invoke error"); throw new RuntimeException("[Sentinel Starter] DataSource " + dataSourceName + " field: " + field.getName() + " invoke error", e); } } - propertyMap.put(CONVERTERCLASS_FIELD, dataSourceProperties.getConverterClass()); - propertyMap.put(DATATYPE_FIELD, dataSourceProperties.getDataType()); + + propertyMap.put(CONVERTER_CLASS_FIELD, dataSourceProperties.getConverterClass()); + propertyMap.put(DATA_TYPE_FIELD, dataSourceProperties.getDataType()); BeanDefinitionBuilder builder = BeanDefinitionBuilder .genericBeanDefinition(dataSourceProperties.getFactoryBeanName()); @@ -205,166 +128,136 @@ public class SentinelDataSourceHandler { Object propertyValue = entry.getValue(); Field field = ReflectionUtils.findField(dataSourceProperties.getClass(), propertyName); - if (field != null) { - if (DATATYPE_FIELD.equals(propertyName)) { - String dataType = StringUtils - .trimAllWhitespace(propertyValue.toString()); - if (CUSTOM_DATATYPE.equals(dataType)) { - try { - if (StringUtils - .isEmpty(dataSourceProperties.getConverterClass())) { - throw new RuntimeException( - "[Sentinel Starter] DataSource " + dataSourceName - + "dataType is custom, please set converter-class " - + "property"); - } - // construct custom Converter with 'converterClass' - // configuration and register - String customConvertBeanName = "sentinel-" - + dataSourceProperties.getConverterClass(); - if (!beanFactory.containsBean(customConvertBeanName)) { - beanFactory.registerBeanDefinition(customConvertBeanName, - BeanDefinitionBuilder - .genericBeanDefinition( - Class.forName(dataSourceProperties - .getConverterClass())) - .getBeanDefinition()); - } - builder.addPropertyReference("converter", - customConvertBeanName); - } - catch (ClassNotFoundException e) { - logger.error("[Sentinel Starter] DataSource " + dataSourceName - + " handle " - + dataSourceProperties.getClass().getSimpleName() - + " error, class name: " - + dataSourceProperties.getConverterClass()); - throw new RuntimeException( - "[Sentinel Starter] DataSource " + dataSourceName - + " handle " - + dataSourceProperties.getClass() - .getSimpleName() - + " error, class name: " - + dataSourceProperties.getConverterClass(), - e); - } - } - else { - if (!dataTypeList.contains(StringUtils - .trimAllWhitespace(propertyValue.toString()))) { + if (null == field) { + continue; + } + if (DATA_TYPE_FIELD.equals(propertyName)) { + String dataType = StringUtils.trimAllWhitespace(propertyValue.toString()); + if (CUSTOM_DATA_TYPE.equals(dataType)) { + try { + if (StringUtils + .isEmpty(dataSourceProperties.getConverterClass())) { throw new RuntimeException("[Sentinel Starter] DataSource " - + dataSourceName + " dataType: " + propertyValue - + " is not support now. please using these types: " - + dataTypeList.toString()); + + dataSourceName + + "dataType is custom, please set converter-class " + + "property"); } - // converter type now support xml or json. - // The bean name of these converters wrapped by - // 'sentinel-{converterType}-converter' - builder.addPropertyReference("converter", - "sentinel-" + propertyValue.toString() + "-converter"); + // construct custom Converter with 'converterClass' + // configuration and register + String customConvertBeanName = "sentinel-" + + dataSourceProperties.getConverterClass(); + if (!this.beanFactory.containsBean(customConvertBeanName)) { + this.beanFactory.registerBeanDefinition(customConvertBeanName, + BeanDefinitionBuilder + .genericBeanDefinition( + Class.forName(dataSourceProperties + .getConverterClass())) + .getBeanDefinition()); + } + builder.addPropertyReference("converter", customConvertBeanName); + } + catch (ClassNotFoundException e) { + log.error("[Sentinel Starter] DataSource " + dataSourceName + + " handle " + + dataSourceProperties.getClass().getSimpleName() + + " error, class name: " + + dataSourceProperties.getConverterClass()); + throw new RuntimeException("[Sentinel Starter] DataSource " + + dataSourceName + " handle " + + dataSourceProperties.getClass().getSimpleName() + + " error, class name: " + + dataSourceProperties.getConverterClass(), e); } } - else if (CONVERTERCLASS_FIELD.equals(propertyName)) { - continue; - } else { - // wired properties - if (propertyValue != null) { - builder.addPropertyValue(propertyName, propertyValue); + if (!dataTypeList.contains( + StringUtils.trimAllWhitespace(propertyValue.toString()))) { + throw new RuntimeException("[Sentinel Starter] DataSource " + + dataSourceName + " dataType: " + propertyValue + + " is not support now. please using these types: " + + dataTypeList.toString()); } + // converter type now support xml or json. + // The bean name of these converters wrapped by + // 'sentinel-{converterType}-{ruleType}-converter' + builder.addPropertyReference("converter", + "sentinel-" + propertyValue.toString() + "-" + + dataSourceProperties.getRuleType().getName() + + "-converter"); } } - } - - beanFactory.registerBeanDefinition(dataSourceName, builder.getBeanDefinition()); - // init in Spring - AbstractDataSource newDataSource = (AbstractDataSource) beanFactory - .getBean(dataSourceName); - // commercialization - if (!StringUtils.isEmpty(System.getProperties() - .getProperty(SentinelDataSourceConstants.NACOS_DATASOURCE_ENDPOINT))) { - if (dataSourceName.contains(SentinelConstants.FLOW_DATASOURCE_NAME)) { - FlowRuleManager.register2Property(newDataSource.getProperty()); - } - else if (dataSourceName.contains(SentinelConstants.DEGRADE_DATASOURCE_NAME)) { - DegradeRuleManager.register2Property(newDataSource.getProperty()); - } - } - dataSourceBeanNameList.add(dataSourceName); - } - - private Class getAndCheckRuleType(Object ruleConfig, String dataSourceName) { - if (rulesList.contains(ruleConfig.getClass())) { - logger.info("[Sentinel Starter] DataSource {} load {} {}", dataSourceName, 1, - ruleConfig.getClass().getSimpleName()); - return ruleConfig.getClass(); - } - else if (ruleConfig instanceof List) { - List convertedRuleList = (List) ruleConfig; - if (CollectionUtils.isEmpty(convertedRuleList)) { - logger.warn("[Sentinel Starter] DataSource {} rule list is empty.", - dataSourceName); - return null; - } - - if (checkRuleTypeValid(convertedRuleList)) { - if (checkAllRuleTypeSame(convertedRuleList)) { - logger.info("[Sentinel Starter] DataSource {} load {} {}", - dataSourceName, convertedRuleList.size(), - convertedRuleList.get(0).getClass().getSimpleName()); - return convertedRuleList.get(0).getClass(); - } - else { - logger.warn( - "[Sentinel Starter] DataSource {} all rules are not same rule type and it will not be used. " - + "Rule List: {}", - dataSourceName, convertedRuleList.toString()); - } + else if (CONVERTER_CLASS_FIELD.equals(propertyName)) { + continue; } else { - List classList = new ArrayList<>(); - for (Object rule : convertedRuleList) { - classList.add(rule.getClass()); + // wired properties + if (propertyValue != null) { + builder.addPropertyValue(propertyName, propertyValue); } - logger.error("[Sentinel Starter] DataSource " + dataSourceName - + " rule class is invalid. Class List: " + classList); - throw new RuntimeException( - "[Sentinel Starter] DataSource " + dataSourceName - + " rule class is invalid. Class List: " + classList); + } + } + + this.beanFactory.registerBeanDefinition(dataSourceName, + builder.getBeanDefinition()); + // init in Spring + AbstractDataSource newDataSource = (AbstractDataSource) this.beanFactory + .getBean(dataSourceName); + + logAndCheckRuleType(newDataSource, dataSourceName, + dataSourceProperties.getRuleType().getClazz()); + + // register property in RuleManager + dataSourceProperties.postRegister(newDataSource); + } + + private void logAndCheckRuleType(AbstractDataSource dataSource, String dataSourceName, + Class ruleClass) { + Object ruleConfig; + try { + ruleConfig = dataSource.loadConfig(); + } + catch (Exception e) { + log.error("[Sentinel Starter] DataSource " + dataSourceName + + " loadConfig error: " + e.getMessage(), e); + return; + } + if (ruleConfig instanceof List) { + List convertedRuleList = (List) ruleConfig; + if (CollectionUtils.isEmpty(convertedRuleList)) { + log.warn("[Sentinel Starter] DataSource {} rule list is empty.", + dataSourceName); + return; + } + int matchCount = 0; + for (Object rule : convertedRuleList) { + if (rule.getClass() == ruleClass) { + matchCount++; + } + } + if (matchCount == 0) { + log.error("[Sentinel Starter] DataSource {} none rules are {} type.", + dataSourceName, ruleClass.getSimpleName()); + throw new IllegalArgumentException("[Sentinel Starter] DataSource " + + dataSourceName + " none rules are " + ruleClass.getSimpleName() + + " type."); + } + else if (matchCount != convertedRuleList.size()) { + log.warn("[Sentinel Starter] DataSource {} all rules are not {} type.", + dataSourceName, ruleClass.getSimpleName()); + } + else { + log.info("[Sentinel Starter] DataSource {} load {} {}", dataSourceName, + convertedRuleList.size(), ruleClass.getSimpleName()); } } else { - logger.error("[Sentinel Starter] DataSource " + dataSourceName - + " rule class is invalid. Class: " + ruleConfig.getClass()); - throw new RuntimeException("[Sentinel Starter] DataSource " + dataSourceName - + " rule class is invalid. Class: " + ruleConfig.getClass()); + log.error("[Sentinel Starter] DataSource " + dataSourceName + + " rule class is not List<" + ruleClass.getSimpleName() + + ">. Class: " + ruleConfig.getClass()); + throw new IllegalArgumentException("[Sentinel Starter] DataSource " + + dataSourceName + " rule class is not List<" + + ruleClass.getSimpleName() + ">. Class: " + ruleConfig.getClass()); } - return null; - } - - private boolean checkRuleTypeValid(List convertedRuleList) { - int matchCount = 0; - for (Object rule : convertedRuleList) { - if (rulesList.contains(rule.getClass())) { - matchCount++; - } - } - return matchCount == convertedRuleList.size(); - } - - private boolean checkAllRuleTypeSame(List convertedRuleList) { - int matchCount = 0; - for (Object rule : convertedRuleList) { - if (rulesList.contains(rule.getClass()) - && rule.getClass() == convertedRuleList.get(0).getClass()) { - matchCount++; - } - } - return matchCount == convertedRuleList.size(); - } - - public List getDataSourceBeanNameList() { - return dataSourceBeanNameList; } } diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelProtectInterceptor.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelProtectInterceptor.java index a1ab9e22..f41601ab 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelProtectInterceptor.java +++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/custom/SentinelProtectInterceptor.java @@ -17,19 +17,16 @@ package org.springframework.cloud.alibaba.sentinel.custom; import java.io.IOException; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.URI; -import java.util.Arrays; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.cloud.alibaba.sentinel.annotation.SentinelRestTemplate; import org.springframework.cloud.alibaba.sentinel.rest.SentinelClientHttpResponse; import org.springframework.http.HttpRequest; import org.springframework.http.client.ClientHttpRequestExecution; import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.http.client.ClientHttpResponse; -import org.springframework.util.ClassUtils; import com.alibaba.csp.sentinel.Entry; import com.alibaba.csp.sentinel.SphU; @@ -37,19 +34,15 @@ import com.alibaba.csp.sentinel.Tracer; import com.alibaba.csp.sentinel.context.ContextUtil; import com.alibaba.csp.sentinel.slots.block.BlockException; import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException; -import com.alibaba.csp.sentinel.util.StringUtil; /** * Interceptor using by SentinelRestTemplate * - * @author fangjian + * @author Jim */ public class SentinelProtectInterceptor implements ClientHttpRequestInterceptor { - private static final Logger logger = LoggerFactory - .getLogger(SentinelProtectInterceptor.class); - - private SentinelRestTemplate sentinelRestTemplate; + private final SentinelRestTemplate sentinelRestTemplate; public SentinelProtectInterceptor(SentinelRestTemplate sentinelRestTemplate) { this.sentinelRestTemplate = sentinelRestTemplate; @@ -82,18 +75,7 @@ public class SentinelProtectInterceptor implements ClientHttpRequestInterceptor throw new IllegalStateException(e); } else { - try { - return handleBlockException(request, body, execution, - (BlockException) e); - } - catch (Exception ex) { - if (ex instanceof IllegalStateException) { - throw (IllegalStateException) ex; - } - throw new IllegalStateException( - "sentinel handle BlockException error: " + ex.getMessage(), - ex); - } + return handleBlockException(request, body, execution, (BlockException) e); } } finally { @@ -109,84 +91,49 @@ public class SentinelProtectInterceptor implements ClientHttpRequestInterceptor } private ClientHttpResponse handleBlockException(HttpRequest request, byte[] body, - ClientHttpRequestExecution execution, BlockException ex) throws Exception { + ClientHttpRequestExecution execution, BlockException ex) { Object[] args = new Object[] { request, body, execution, ex }; // handle degrade if (isDegradeFailure(ex)) { - Method method = extractFallbackMethod(sentinelRestTemplate.fallback(), + Method fallbackMethod = extractFallbackMethod(sentinelRestTemplate.fallback(), sentinelRestTemplate.fallbackClass()); - if (method != null) { - return (ClientHttpResponse) method.invoke(null, args); + if (fallbackMethod != null) { + return methodInvoke(fallbackMethod, args); } else { return new SentinelClientHttpResponse(); } } - // handle block + // handle flow Method blockHandler = extractBlockHandlerMethod( sentinelRestTemplate.blockHandler(), sentinelRestTemplate.blockHandlerClass()); if (blockHandler != null) { - return (ClientHttpResponse) blockHandler.invoke(null, args); + return methodInvoke(blockHandler, args); } else { return new SentinelClientHttpResponse(); } } + private ClientHttpResponse methodInvoke(Method method, Object... args) { + try { + return (ClientHttpResponse) method.invoke(null, args); + } + catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + catch (InvocationTargetException e) { + throw new RuntimeException(e); + } + } + private Method extractFallbackMethod(String fallback, Class fallbackClass) { - if (StringUtil.isBlank(fallback) || fallbackClass == void.class) { - return null; - } - Method cachedMethod = BlockClassRegistry.lookupFallback(fallbackClass, fallback); - Class[] args = new Class[] { HttpRequest.class, byte[].class, - ClientHttpRequestExecution.class, BlockException.class }; - if (cachedMethod == null) { - cachedMethod = ClassUtils.getStaticMethod(fallbackClass, fallback, args); - if (cachedMethod != null) { - if (!ClientHttpResponse.class - .isAssignableFrom(cachedMethod.getReturnType())) { - throw new IllegalStateException(String.format( - "the return type of method [%s] in class [%s] is not ClientHttpResponse in degrade", - cachedMethod.getName(), fallbackClass.getCanonicalName())); - } - BlockClassRegistry.updateFallbackFor(fallbackClass, fallback, - cachedMethod); - } - else { - throw new IllegalStateException(String.format( - "Cannot find method [%s] in class [%s] with parameters %s in degrade", - fallback, fallbackClass.getCanonicalName(), Arrays.asList(args))); - } - } - return cachedMethod; + return BlockClassRegistry.lookupFallback(fallbackClass, fallback); } private Method extractBlockHandlerMethod(String block, Class blockClass) { - if (StringUtil.isBlank(block) || blockClass == void.class) { - return null; - } - Method cachedMethod = BlockClassRegistry.lookupBlockHandler(blockClass, block); - Class[] args = new Class[] { HttpRequest.class, byte[].class, - ClientHttpRequestExecution.class, BlockException.class }; - if (cachedMethod == null) { - cachedMethod = ClassUtils.getStaticMethod(blockClass, block, args); - if (cachedMethod != null) { - if (!ClientHttpResponse.class - .isAssignableFrom(cachedMethod.getReturnType())) { - throw new IllegalStateException(String.format( - "the return type of method [%s] in class [%s] is not ClientHttpResponse in flow control", - cachedMethod.getName(), blockClass.getCanonicalName())); - } - BlockClassRegistry.updateBlockHandlerFor(blockClass, block, cachedMethod); - } - else { - throw new IllegalStateException(String.format( - "Cannot find method [%s] in class [%s] with parameters %s in flow control", - block, blockClass.getCanonicalName(), Arrays.asList(args))); - } - } - return cachedMethod; + return BlockClassRegistry.lookupBlockHandler(blockClass, block); } private boolean isDegradeFailure(BlockException ex) { diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/endpoint/SentinelEndpoint.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/endpoint/SentinelEndpoint.java index d7e3e9da..cbd8d044 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/endpoint/SentinelEndpoint.java +++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/endpoint/SentinelEndpoint.java @@ -17,24 +17,20 @@ package org.springframework.cloud.alibaba.sentinel.endpoint; import java.util.HashMap; -import java.util.List; import java.util.Map; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.actuate.endpoint.AbstractEndpoint; import org.springframework.cloud.alibaba.sentinel.SentinelProperties; -import org.springframework.cloud.alibaba.sentinel.custom.SentinelDataSourceHandler; -import org.springframework.context.ApplicationContext; -import com.alibaba.csp.sentinel.datasource.ReadableDataSource; -import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; +import com.alibaba.csp.sentinel.adapter.servlet.config.WebServletConfig; +import com.alibaba.csp.sentinel.config.SentinelConfig; +import com.alibaba.csp.sentinel.log.LogBase; +import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRuleManager; import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; -import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; -import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule; import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRuleManager; -import com.alibaba.csp.sentinel.slots.system.SystemRule; import com.alibaba.csp.sentinel.slots.system.SystemRuleManager; +import com.alibaba.csp.sentinel.transport.config.TransportConfig; /** * Endpoint for Sentinel, contains ans properties and rules @@ -42,45 +38,39 @@ import com.alibaba.csp.sentinel.slots.system.SystemRuleManager; */ public class SentinelEndpoint extends AbstractEndpoint> { - @Autowired - private SentinelProperties sentinelProperties; + private final SentinelProperties sentinelProperties; - @Autowired - private SentinelDataSourceHandler dataSourceHandler; - - @Autowired - private ApplicationContext applicationContext; - - public SentinelEndpoint() { + public SentinelEndpoint(SentinelProperties sentinelProperties) { super("sentinel"); + this.sentinelProperties = sentinelProperties; } @Override public Map invoke() { - Map result = new HashMap<>(); + final Map result = new HashMap<>(); + if (sentinelProperties.isEnabled()) { - List flowRules = FlowRuleManager.getRules(); - List degradeRules = DegradeRuleManager.getRules(); - List systemRules = SystemRuleManager.getRules(); - List paramFlowRules = ParamFlowRuleManager.getRules(); - result.put("properties", sentinelProperties); - result.put("FlowRules", flowRules); - result.put("DegradeRules", degradeRules); - result.put("SystemRules", systemRules); - result.put("ParamFlowRule", paramFlowRules); - result.put("datasources", new HashMap()); + result.put("logDir", LogBase.getLogBaseDir()); + result.put("logUsePid", LogBase.isLogNameUsePid()); + result.put("blockPage", WebServletConfig.getBlockPage()); + result.put("metricsFileSize", SentinelConfig.singleMetricFileSize()); + result.put("metricsFileCharset", SentinelConfig.charset()); + result.put("totalMetricsFileCount", SentinelConfig.totalMetricFileCount()); + result.put("consoleServer", TransportConfig.getConsoleServer()); + result.put("clientIp", TransportConfig.getHeartbeatClientIp()); + result.put("heartbeatIntervalMs", TransportConfig.getHeartbeatIntervalMs()); + result.put("clientPort", TransportConfig.getPort()); + result.put("coldFactor", sentinelProperties.getFlow().getColdFactor()); + result.put("filter", sentinelProperties.getFilter()); + result.put("datasource", sentinelProperties.getDatasource()); - for (String dataSourceBeanName : dataSourceHandler.getDataSourceBeanNameList()) { - ReadableDataSource dataSource = applicationContext.getBean(dataSourceBeanName, - ReadableDataSource.class); - try { - ((HashMap) result.get("datasources")).put(dataSourceBeanName, - dataSource.loadConfig()); - } - catch (Exception e) { - ((HashMap) result.get("datasources")).put(dataSourceBeanName, - "load error: " + e.getMessage()); - } + final Map rules = new HashMap<>(); + result.put("rules", rules); + rules.put("flowRules", FlowRuleManager.getRules()); + rules.put("degradeRules", DegradeRuleManager.getRules()); + rules.put("systemRules", SystemRuleManager.getRules()); + rules.put("authorityRule", AuthorityRuleManager.getRules()); + rules.put("paramFlowRule", ParamFlowRuleManager.getRules()); } return result; } diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/endpoint/SentinelEndpointAutoConfiguration.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/endpoint/SentinelEndpointAutoConfiguration.java index 728347b4..b49fb20e 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/endpoint/SentinelEndpointAutoConfiguration.java +++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/endpoint/SentinelEndpointAutoConfiguration.java @@ -34,8 +34,8 @@ public class SentinelEndpointAutoConfiguration { @Bean @ConditionalOnMissingBean @ConditionalOnEnabledEndpoint("sentinel") - public SentinelEndpoint sentinelEndPoint() { - return new SentinelEndpoint(); + public SentinelEndpoint sentinelEndPoint(SentinelProperties sentinelProperties) { + return new SentinelEndpoint(sentinelProperties); } } diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/rest/SentinelClientHttpResponse.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/rest/SentinelClientHttpResponse.java index 6de453d4..78282a19 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/rest/SentinelClientHttpResponse.java +++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/rest/SentinelClientHttpResponse.java @@ -16,13 +16,6 @@ package org.springframework.cloud.alibaba.sentinel.rest; -import org.springframework.cloud.alibaba.sentinel.annotation.SentinelRestTemplate; -import org.springframework.cloud.alibaba.sentinel.custom.SentinelProtectInterceptor; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.client.AbstractClientHttpResponse; - import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; @@ -31,6 +24,13 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import org.springframework.cloud.alibaba.sentinel.annotation.SentinelRestTemplate; +import org.springframework.cloud.alibaba.sentinel.custom.SentinelProtectInterceptor; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.client.AbstractClientHttpResponse; + /** * Using by {@link SentinelRestTemplate} and {@link SentinelProtectInterceptor} * @@ -41,7 +41,6 @@ public class SentinelClientHttpResponse extends AbstractClientHttpResponse { private String blockResponse = "RestTemplate request block by sentinel"; public SentinelClientHttpResponse() { - } public SentinelClientHttpResponse(String blockResponse) { diff --git a/spring-cloud-alibaba-sentinel/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-alibaba-sentinel/src/main/resources/META-INF/additional-spring-configuration-metadata.json index d05b0863..b445fc6a 100644 --- a/spring-cloud-alibaba-sentinel/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-cloud-alibaba-sentinel/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -18,6 +18,11 @@ "defaultValue": "8719", "description": "sentinel api port." }, + { + "name": "spring.cloud.sentinel.transport.clientIp", + "type": "java.lang.String", + "description": "sentinel client ip connect to dashboard." + }, { "name": "spring.cloud.sentinel.transport.dashboard", "type": "java.lang.String", diff --git a/spring-cloud-alibaba-sentinel/src/main/resources/META-INF/spring.factories b/spring-cloud-alibaba-sentinel/src/main/resources/META-INF/spring.factories index 702bb5bb..181c30b8 100644 --- a/spring-cloud-alibaba-sentinel/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-alibaba-sentinel/src/main/resources/META-INF/spring.factories @@ -3,3 +3,6 @@ org.springframework.cloud.alibaba.sentinel.SentinelWebAutoConfiguration,\ org.springframework.cloud.alibaba.sentinel.endpoint.SentinelEndpointAutoConfiguration,\ org.springframework.cloud.alibaba.sentinel.custom.SentinelAutoConfiguration,\ org.springframework.cloud.alibaba.sentinel.feign.SentinelFeignAutoConfiguration + +org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker=\ +org.springframework.cloud.alibaba.sentinel.custom.SentinelCircuitBreakerConfiguration \ No newline at end of file diff --git a/spring-cloud-alibaba-sentinel/src/test/java/org/springframework/cloud/alibaba/sentinel/SentinelAutoConfigurationTests.java b/spring-cloud-alibaba-sentinel/src/test/java/org/springframework/cloud/alibaba/sentinel/SentinelAutoConfigurationTests.java index eaa682ca..65fe21ce 100644 --- a/spring-cloud-alibaba-sentinel/src/test/java/org/springframework/cloud/alibaba/sentinel/SentinelAutoConfigurationTests.java +++ b/spring-cloud-alibaba-sentinel/src/test/java/org/springframework/cloud/alibaba/sentinel/SentinelAutoConfigurationTests.java @@ -27,8 +27,12 @@ import org.springframework.cloud.alibaba.sentinel.annotation.SentinelRestTemplat import org.springframework.cloud.alibaba.sentinel.custom.SentinelAutoConfiguration; import org.springframework.cloud.alibaba.sentinel.custom.SentinelBeanPostProcessor; import org.springframework.cloud.alibaba.sentinel.custom.SentinelProtectInterceptor; +import org.springframework.cloud.alibaba.sentinel.rest.SentinelClientHttpResponse; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpRequest; +import org.springframework.http.client.ClientHttpRequestExecution; +import org.springframework.http.client.ClientHttpResponse; import org.springframework.web.client.RestTemplate; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; @@ -109,8 +113,9 @@ public class SentinelAutoConfigurationTests { } static class ExceptionUtil { - public static void handleException(BlockException ex) { - System.out.println("Oops: " + ex.getClass().getCanonicalName()); + public static ClientHttpResponse handleException(HttpRequest request, byte[] body, + ClientHttpRequestExecution execution, BlockException ex) { + return new SentinelClientHttpResponse("custom block info"); } } diff --git a/spring-cloud-alicloud-acm/pom.xml b/spring-cloud-alicloud-acm/pom.xml index 6b57a4f7..49012835 100644 --- a/spring-cloud-alicloud-acm/pom.xml +++ b/spring-cloud-alicloud-acm/pom.xml @@ -11,6 +11,7 @@ spring-cloud-alicloud-acm + Spring Cloud Alibaba Cloud ACM @@ -43,6 +44,7 @@ org.springframework.boot spring-boot-starter-actuator + provided true diff --git a/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/bootstrap/AcmPropertySource.java b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/bootstrap/AcmPropertySource.java index 3ebae277..fb7b58ad 100644 --- a/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/bootstrap/AcmPropertySource.java +++ b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/bootstrap/AcmPropertySource.java @@ -27,29 +27,29 @@ import java.util.Map; */ public class AcmPropertySource extends MapPropertySource { - private final String dataId; + private final String dataId; - private final Date timestamp; + private final Date timestamp; - private final boolean groupLevel; + private final boolean groupLevel; - AcmPropertySource(String dataId, Map source, Date timestamp, - boolean groupLevel) { - super(dataId, source); - this.dataId = dataId; - this.timestamp = timestamp; - this.groupLevel = groupLevel; - } + AcmPropertySource(String dataId, Map source, Date timestamp, + boolean groupLevel) { + super(dataId, source); + this.dataId = dataId; + this.timestamp = timestamp; + this.groupLevel = groupLevel; + } - public String getDataId() { - return dataId; - } + public String getDataId() { + return dataId; + } - public Date getTimestamp() { - return timestamp; - } + public Date getTimestamp() { + return timestamp; + } - public boolean isGroupLevel() { - return groupLevel; - } + public boolean isGroupLevel() { + return groupLevel; + } } diff --git a/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/bootstrap/AcmPropertySourceBuilder.java b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/bootstrap/AcmPropertySourceBuilder.java index 2bf9cbba..7afabd83 100644 --- a/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/bootstrap/AcmPropertySourceBuilder.java +++ b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/bootstrap/AcmPropertySourceBuilder.java @@ -33,64 +33,68 @@ import java.util.*; */ class AcmPropertySourceBuilder { - private Logger logger = LoggerFactory.getLogger(AcmPropertySourceBuilder.class); + private Logger log = LoggerFactory.getLogger(AcmPropertySourceBuilder.class); - /** - * 传入 ACM 的 DataId 和 groupID,获取到解析后的 AcmProperty 对象 - * - * @param dataId - * @param diamondGroup - * @param groupLevel - * @return - */ - AcmPropertySource build(String dataId, String diamondGroup, boolean groupLevel) { - Properties properties = loadDiamondData(dataId, diamondGroup); - if (properties == null) { - return null; - } - return new AcmPropertySource(dataId, toMap(properties), new Date(), groupLevel); - } + /** + * 传入 ACM 的 DataId 和 groupID,获取到解析后的 AcmProperty 对象 + * + * @param dataId + * @param diamondGroup + * @param groupLevel + * @return + */ + AcmPropertySource build(String dataId, String diamondGroup, boolean groupLevel) { + Properties properties = loadDiamondData(dataId, diamondGroup); + if (properties == null) { + return null; + } + return new AcmPropertySource(dataId, toMap(properties), new Date(), groupLevel); + } - private Properties loadDiamondData(String dataId, String diamondGroup) { - try { - String data = ConfigService.getConfig(dataId, diamondGroup, 3000L); - if (StringUtils.isEmpty(data)) { - return null; - } - if (dataId.endsWith(".properties")) { - Properties properties = new Properties(); - logger.info(String.format("Loading acm data, dataId: '%s', group: '%s'", - dataId, diamondGroup)); - properties.load(new StringReader(data)); - return properties; - } else if (dataId.endsWith(".yaml") || dataId.endsWith(".yml")) { - YamlPropertiesFactoryBean yamlFactory = new YamlPropertiesFactoryBean(); - yamlFactory.setResources(new ByteArrayResource(data.getBytes())); - return yamlFactory.getObject(); - } - } catch (Exception e) { - if (e instanceof ConfigException) { - logger.error("DIAMOND-100500:" + dataId + ", " + e.toString(), e); - } else { - logger.error("DIAMOND-100500:" + dataId, e); - } - } - return null; - } + private Properties loadDiamondData(String dataId, String diamondGroup) { + try { + String data = ConfigService.getConfig(dataId, diamondGroup, 3000L); + if (StringUtils.isEmpty(data)) { + return null; + } + if (dataId.endsWith(".properties")) { + Properties properties = new Properties(); + log.info(String.format("Loading acm data, dataId: '%s', group: '%s'", + dataId, diamondGroup)); + properties.load(new StringReader(data)); + return properties; + } + else if (dataId.endsWith(".yaml") || dataId.endsWith(".yml")) { + YamlPropertiesFactoryBean yamlFactory = new YamlPropertiesFactoryBean(); + yamlFactory.setResources(new ByteArrayResource(data.getBytes())); + return yamlFactory.getObject(); + } + } + catch (Exception e) { + if (e instanceof ConfigException) { + log.error("DIAMOND-100500:" + dataId + ", " + e.toString(), e); + } + else { + log.error("DIAMOND-100500:" + dataId, e); + } + } + return null; + } - @SuppressWarnings("unchecked") - private Map toMap(Properties properties) { - Map result = new HashMap<>(); - Enumeration keys = (Enumeration)properties.propertyNames(); - while (keys.hasMoreElements()) { - String key = keys.nextElement(); - Object value = properties.getProperty(key); - if (value != null) { - result.put(key, ((String)value).trim()); - } else { - result.put(key, null); - } - } - return result; - } + @SuppressWarnings("unchecked") + private Map toMap(Properties properties) { + Map result = new HashMap<>(); + Enumeration keys = (Enumeration) properties.propertyNames(); + while (keys.hasMoreElements()) { + String key = keys.nextElement(); + Object value = properties.getProperty(key); + if (value != null) { + result.put(key, ((String) value).trim()); + } + else { + result.put(key, null); + } + } + return result; + } } diff --git a/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/endpoint/AcmHealthIndicator.java b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/endpoint/AcmHealthIndicator.java index 27569ec1..c6052ae1 100644 --- a/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/endpoint/AcmHealthIndicator.java +++ b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/endpoint/AcmHealthIndicator.java @@ -33,39 +33,40 @@ import java.util.List; */ public class AcmHealthIndicator extends AbstractHealthIndicator { - private final AcmProperties acmProperties; + private final AcmProperties acmProperties; - private final AcmPropertySourceRepository acmPropertySourceRepository; + private final AcmPropertySourceRepository acmPropertySourceRepository; - private final List dataIds; + private final List dataIds; - public AcmHealthIndicator(AcmProperties acmProperties, - AcmPropertySourceRepository acmPropertySourceRepository) { - this.acmProperties = acmProperties; - this.acmPropertySourceRepository = acmPropertySourceRepository; + public AcmHealthIndicator(AcmProperties acmProperties, + AcmPropertySourceRepository acmPropertySourceRepository) { + this.acmProperties = acmProperties; + this.acmPropertySourceRepository = acmPropertySourceRepository; - this.dataIds = new ArrayList<>(); - for (AcmPropertySource acmPropertySource : this.acmPropertySourceRepository - .getAll()) { - this.dataIds.add(acmPropertySource.getDataId()); - } - } + this.dataIds = new ArrayList<>(); + for (AcmPropertySource acmPropertySource : this.acmPropertySourceRepository + .getAll()) { + this.dataIds.add(acmPropertySource.getDataId()); + } + } - @Override - protected void doHealthCheck(Health.Builder builder) throws Exception { - for (String dataId : dataIds) { - try { - String config = ConfigService.getConfig(dataId, acmProperties.getGroup(), - acmProperties.getTimeout()); - if (StringUtils.isEmpty(config)) { - builder.down().withDetail(String.format("dataId: '%s', group: '%s'", - dataId, acmProperties.getGroup()), "config is empty"); - } - } catch (Exception e) { - builder.down().withDetail(String.format("dataId: '%s', group: '%s'", - dataId, acmProperties.getGroup()), e.getMessage()); - } - } - builder.up().withDetail("dataIds", dataIds); - } + @Override + protected void doHealthCheck(Health.Builder builder) throws Exception { + for (String dataId : dataIds) { + try { + String config = ConfigService.getConfig(dataId, acmProperties.getGroup(), + acmProperties.getTimeout()); + if (StringUtils.isEmpty(config)) { + builder.down().withDetail(String.format("dataId: '%s', group: '%s'", + dataId, acmProperties.getGroup()), "config is empty"); + } + } + catch (Exception e) { + builder.down().withDetail(String.format("dataId: '%s', group: '%s'", + dataId, acmProperties.getGroup()), e.getMessage()); + } + } + builder.up().withDetail("dataIds", dataIds); + } } diff --git a/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/refresh/AcmContextRefresher.java b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/refresh/AcmContextRefresher.java index 58457c07..18308b59 100644 --- a/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/refresh/AcmContextRefresher.java +++ b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/refresh/AcmContextRefresher.java @@ -28,7 +28,6 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.cloud.alicloud.acm.AcmPropertySourceRepository; -import org.springframework.cloud.alicloud.acm.bootstrap.AcmPropertySource; import org.springframework.cloud.alicloud.context.acm.AcmIntegrationProperties; import org.springframework.cloud.context.refresh.ContextRefresher; import org.springframework.cloud.endpoint.event.RefreshEvent; @@ -50,7 +49,7 @@ import com.alibaba.edas.acm.listener.ConfigChangeListener; public class AcmContextRefresher implements ApplicationListener, ApplicationContextAware { - private Logger logger = LoggerFactory.getLogger(AcmContextRefresher.class); + private Logger log = LoggerFactory.getLogger(AcmContextRefresher.class); private final ContextRefresher contextRefresher; @@ -103,7 +102,7 @@ public class AcmContextRefresher } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) { - logger.warn("unable to get md5 for dataId: " + dataId, e); + log.warn("unable to get md5 for dataId: " + dataId, e); } } refreshHistory.add(dataId, md5); diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/AnsAutoConfiguration.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/AnsAutoConfiguration.java index 144520fc..4a39ded0 100644 --- a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/AnsAutoConfiguration.java +++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/AnsAutoConfiguration.java @@ -16,6 +16,7 @@ package org.springframework.cloud.alicloud.ans; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -26,7 +27,7 @@ import org.springframework.cloud.alicloud.ans.registry.AnsAutoServiceRegistratio import org.springframework.cloud.alicloud.ans.registry.AnsRegistration; import org.springframework.cloud.alicloud.ans.registry.AnsServiceRegistry; import org.springframework.cloud.alicloud.context.ans.AnsProperties; -import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration; +import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration; import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; @@ -42,8 +43,8 @@ import org.springframework.context.annotation.Configuration; @ConditionalOnClass(name = "org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent") @ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true) @ConditionalOnAnsEnabled -@AutoConfigureBefore({ AutoServiceRegistrationAutoConfiguration.class, - AnsDiscoveryClientAutoConfiguration.class }) +@AutoConfigureBefore(AnsDiscoveryClientAutoConfiguration.class) +@AutoConfigureAfter(AutoServiceRegistrationConfiguration.class) public class AnsAutoConfiguration { @Bean diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/endpoint/AnsEndpoint.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/endpoint/AnsEndpoint.java index 7a35ef6f..056bd878 100644 --- a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/endpoint/AnsEndpoint.java +++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/endpoint/AnsEndpoint.java @@ -18,8 +18,8 @@ package org.springframework.cloud.alicloud.ans.endpoint; import com.alibaba.ans.core.NamingService; import com.alibaba.ans.shaded.com.taobao.vipserver.client.core.Host; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.boot.actuate.endpoint.AbstractEndpoint; import org.springframework.cloud.alicloud.context.ans.AnsProperties; @@ -34,7 +34,7 @@ import java.util.Set; */ public class AnsEndpoint extends AbstractEndpoint> { - private static final Log log = LogFactory.getLog(AnsEndpoint.class); + private static final Logger log = LoggerFactory.getLogger(AnsEndpoint.class); private AnsProperties ansProperties; diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateEndpoint.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateEndpoint.java index 53d559a1..e8609648 100644 --- a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateEndpoint.java +++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateEndpoint.java @@ -1,7 +1,7 @@ package org.springframework.cloud.alicloud.ans.migrate; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.boot.actuate.endpoint.AbstractEndpoint; import java.util.Map; @@ -13,7 +13,7 @@ import java.util.concurrent.ConcurrentMap; public class MigrateEndpoint extends AbstractEndpoint>> { - private static final Log log = LogFactory.getLog(MigrateEndpoint.class); + private static final Logger log = LoggerFactory.getLogger(MigrateEndpoint.class); public MigrateEndpoint() { super("migrate"); diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateOnConditionClass.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateOnConditionClass.java index 391173d2..9e99c9f8 100644 --- a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateOnConditionClass.java +++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateOnConditionClass.java @@ -1,7 +1,7 @@ package org.springframework.cloud.alicloud.ans.migrate; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; @@ -10,7 +10,8 @@ import org.springframework.core.type.AnnotatedTypeMetadata; */ public class MigrateOnConditionClass extends MigrateOnCondition { - protected static final Log log = LogFactory.getLog(MigrateOnConditionClass.class); + private static final Logger log = LoggerFactory + .getLogger(MigrateOnConditionClass.class); @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateOnConditionMissingClass.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateOnConditionMissingClass.java index da19cb3a..b5653bb7 100644 --- a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateOnConditionMissingClass.java +++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateOnConditionMissingClass.java @@ -1,7 +1,7 @@ package org.springframework.cloud.alicloud.ans.migrate; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; @@ -9,8 +9,8 @@ import org.springframework.core.type.AnnotatedTypeMetadata; * @author pbting */ public class MigrateOnConditionMissingClass extends MigrateOnConditionClass { - protected static final Log log = LogFactory - .getLog(MigrateOnConditionMissingClass.class); + private static final Logger log = LoggerFactory + .getLogger(MigrateOnConditionMissingClass.class); @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateProxyManager.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateProxyManager.java index 06f673fb..8b62c22e 100644 --- a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateProxyManager.java +++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateProxyManager.java @@ -7,8 +7,8 @@ import com.netflix.loadbalancer.ServerList; import org.aopalliance.aop.Advice; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.aop.framework.ProxyFactory; import java.util.*; @@ -20,7 +20,7 @@ import java.util.concurrent.atomic.AtomicBoolean; */ final class MigrateProxyManager { - private final static Log log = LogFactory.getLog(MigrateProxyManager.class); + private static final Logger log = LoggerFactory.getLogger(MigrateProxyManager.class); private final static AtomicBoolean IS_PROXY = new AtomicBoolean(true); diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateRefreshEventListener.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateRefreshEventListener.java index f5144972..db941c84 100644 --- a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateRefreshEventListener.java +++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateRefreshEventListener.java @@ -7,8 +7,8 @@ import java.util.concurrent.TimeUnit; import javax.annotation.PostConstruct; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.cloud.context.named.NamedContextFactory; import org.springframework.cloud.endpoint.event.RefreshEvent; import org.springframework.context.ApplicationListener; @@ -22,7 +22,8 @@ import com.netflix.loadbalancer.ILoadBalancer; */ @Component public class MigrateRefreshEventListener implements ApplicationListener { - private final static Log log = LogFactory.getLog(MigrateRefreshEventListener.class); + private static final Logger log = LoggerFactory + .getLogger(MigrateRefreshEventListener.class); private final static int CHECK_INTERVAL = 1; diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateRibbonBeanPostProcessor.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateRibbonBeanPostProcessor.java index df246f18..74fa658a 100644 --- a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateRibbonBeanPostProcessor.java +++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateRibbonBeanPostProcessor.java @@ -1,7 +1,7 @@ package org.springframework.cloud.alicloud.ans.migrate; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.beans.factory.config.BeanPostProcessor; @@ -16,7 +16,7 @@ import com.netflix.loadbalancer.ServerList; public class MigrateRibbonBeanPostProcessor implements BeanPostProcessor, BeanClassLoaderAware { - protected static final Log log = LogFactory.getLog(MigrateOnCondition.class); + private static final Logger log = LoggerFactory.getLogger(MigrateOnCondition.class); private ClassLoader classLoader; private IClientConfig clientConfig; diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateServiceRegistry.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateServiceRegistry.java index b6c709ca..8220d377 100644 --- a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateServiceRegistry.java +++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateServiceRegistry.java @@ -2,8 +2,8 @@ package org.springframework.cloud.alicloud.ans.migrate; import java.util.concurrent.atomic.AtomicBoolean; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.cloud.alicloud.ans.registry.AnsRegistration; import org.springframework.cloud.alicloud.ans.registry.AnsServiceRegistry; @@ -19,7 +19,8 @@ import org.springframework.stereotype.Component; @Component public class MigrateServiceRegistry { - private static final Log log = LogFactory.getLog(MigrateServiceRegistry.class); + private static final Logger log = LoggerFactory + .getLogger(MigrateServiceRegistry.class); private AtomicBoolean running = new AtomicBoolean(false); diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/ServerListInvocationHandler.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/ServerListInvocationHandler.java index 5d6e108f..85ca5c3c 100644 --- a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/ServerListInvocationHandler.java +++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/ServerListInvocationHandler.java @@ -4,8 +4,8 @@ import com.netflix.client.config.IClientConfig; import com.netflix.loadbalancer.Server; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.cloud.alicloud.ans.ribbon.AnsServer; import org.springframework.cloud.alicloud.ans.ribbon.AnsServerList; @@ -21,7 +21,8 @@ import java.util.concurrent.atomic.AtomicLong; */ class ServerListInvocationHandler implements MethodInterceptor { - private final static Log log = LogFactory.getLog(ServerListInvocationHandler.class); + private static final Logger log = LoggerFactory + .getLogger(ServerListInvocationHandler.class); private final static ConcurrentMap SERVER_LIST_CONCURRENT_MAP = new ConcurrentHashMap<>(); diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/registry/AnsAutoServiceRegistration.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/registry/AnsAutoServiceRegistration.java index 5ea2258c..084f85a8 100644 --- a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/registry/AnsAutoServiceRegistration.java +++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/registry/AnsAutoServiceRegistration.java @@ -16,8 +16,8 @@ package org.springframework.cloud.alicloud.ans.registry; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent; import org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration; import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties; @@ -35,7 +35,8 @@ import org.springframework.util.StringUtils; public class AnsAutoServiceRegistration extends AbstractAutoServiceRegistration { - private static final Log log = LogFactory.getLog(AnsAutoServiceRegistration.class); + private static final Logger log = LoggerFactory + .getLogger(AnsAutoServiceRegistration.class); private AnsRegistration registration; @@ -115,11 +116,11 @@ public class AnsAutoServiceRegistration @Override protected int getConfiguredPort() { - return registration.getPort(); + return this.getPort().get(); } @Override protected void setConfiguredPort(int port) { - this.registration.setPort(port); + this.getPort().set(port); } } diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/registry/AnsServiceRegistry.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/registry/AnsServiceRegistry.java index 1ff187a3..924d2976 100644 --- a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/registry/AnsServiceRegistry.java +++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/registry/AnsServiceRegistry.java @@ -19,8 +19,8 @@ package org.springframework.cloud.alicloud.ans.registry; import com.alibaba.ans.core.NamingService; import com.alibaba.ans.shaded.com.taobao.vipserver.client.ipms.NodeReactor; import org.apache.commons.lang.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.cloud.client.serviceregistry.ServiceRegistry; import java.util.ArrayList; @@ -32,7 +32,7 @@ import java.util.Map; */ public class AnsServiceRegistry implements ServiceRegistry { - private static Log log = LogFactory.getLog(AnsServiceRegistry.class); + private static final Logger log = LoggerFactory.getLogger(AnsServiceRegistry.class); private static final String SEPARATOR = ","; diff --git a/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/sentinel/SentinelAliCloudListener.java b/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/sentinel/SentinelAliCloudListener.java deleted file mode 100644 index 9e64b835..00000000 --- a/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/sentinel/SentinelAliCloudListener.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 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 - * - * http://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 org.springframework.cloud.alicloud.context.sentinel; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; -import org.springframework.cloud.alicloud.context.Constants; -import org.springframework.cloud.alicloud.context.listener.AbstractOnceApplicationListener; - -import com.alibaba.cloud.context.edas.EdasChangeOrderConfiguration; -import com.alibaba.cloud.context.edas.EdasChangeOrderConfigurationFactory; - -/** - * @author Jim - */ -public class SentinelAliCloudListener - extends AbstractOnceApplicationListener { - - private static final Logger logger = LoggerFactory - .getLogger(SentinelAliCloudListener.class); - - @Override - protected void handleEvent(ApplicationEnvironmentPreparedEvent event) { - EdasChangeOrderConfiguration edasChangeOrderConfiguration = EdasChangeOrderConfigurationFactory - .getEdasChangeOrderConfiguration(); - logger.info("Sentinel Nacos datasource will" - + (edasChangeOrderConfiguration.isEdasManaged() ? " be " : " not be ") - + "changed by edas change order."); - if (!edasChangeOrderConfiguration.isEdasManaged()) { - return; - } - System.getProperties().setProperty(Constants.Sentinel.NACOS_DATASOURCE_ENDPOINT, - edasChangeOrderConfiguration.getAddressServerDomain()); - System.getProperties().setProperty(Constants.Sentinel.NACOS_DATASOURCE_NAMESPACE, - edasChangeOrderConfiguration.getTenantId()); - System.getProperties().setProperty(Constants.Sentinel.NACOS_DATASOURCE_AK, - edasChangeOrderConfiguration.getDauthAccessKey()); - System.getProperties().setProperty(Constants.Sentinel.NACOS_DATASOURCE_SK, - edasChangeOrderConfiguration.getDauthSecretKey()); - System.getProperties().setProperty(Constants.Sentinel.PROJECT_NAME, - edasChangeOrderConfiguration.getProjectName()); - } - - @Override - protected String conditionalOnClass() { - return "com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource"; - } - -} diff --git a/spring-cloud-alicloud-context/src/main/resources/META-INF/spring.factories b/spring-cloud-alicloud-context/src/main/resources/META-INF/spring.factories index b39c6499..0679da54 100644 --- a/spring-cloud-alicloud-context/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-alicloud-context/src/main/resources/META-INF/spring.factories @@ -11,5 +11,4 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.context.ApplicationListener=\ org.springframework.cloud.alicloud.context.ans.AnsContextApplicationListener,\ org.springframework.cloud.alicloud.context.nacos.NacosConfigParameterInitListener,\ - org.springframework.cloud.alicloud.context.nacos.NacosDiscoveryParameterInitListener,\ - org.springframework.cloud.alicloud.context.sentinel.SentinelAliCloudListener \ No newline at end of file + org.springframework.cloud.alicloud.context.nacos.NacosDiscoveryParameterInitListener \ No newline at end of file diff --git a/spring-cloud-alicloud-context/src/test/java/org/springframework/cloud/alicloud/context/sentinel/SentinelAliCloudListenerTests.java b/spring-cloud-alicloud-context/src/test/java/org/springframework/cloud/alicloud/context/sentinel/SentinelAliCloudListenerTests.java deleted file mode 100644 index de2a5bc0..00000000 --- a/spring-cloud-alicloud-context/src/test/java/org/springframework/cloud/alicloud/context/sentinel/SentinelAliCloudListenerTests.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 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 - * - * http://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 org.springframework.cloud.alicloud.context.sentinel; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.junit.BeforeClass; -import org.junit.Test; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.springframework.cloud.alicloud.context.BaseAliCloudSpringApplication; -import org.springframework.cloud.alicloud.context.Constants; -import org.springframework.cloud.alicloud.utils.ChangeOrderUtils; - -import com.alibaba.cloud.context.edas.EdasChangeOrderConfigurationFactory; - -/** - * @author xiaolongzuo - */ -@PrepareForTest({ EdasChangeOrderConfigurationFactory.class, - SentinelAliCloudListener.class }) -public class SentinelAliCloudListenerTests extends BaseAliCloudSpringApplication { - - @BeforeClass - public static void setUp() { - ChangeOrderUtils.mockChangeOrder(); - } - - @Test - public void testNacosParameterInitListener() { - assertThat(System.getProperty(Constants.Sentinel.NACOS_DATASOURCE_ENDPOINT)) - .isEqualTo("testDomain"); - assertThat(System.getProperty(Constants.Sentinel.PROJECT_NAME)) - .isEqualTo("testProjectName"); - assertThat(System.getProperty(Constants.Sentinel.NACOS_DATASOURCE_NAMESPACE)) - .isEqualTo("testTenantId"); - assertThat(System.getProperty(Constants.Sentinel.NACOS_DATASOURCE_AK)) - .isEqualTo("testAK"); - assertThat(System.getProperty(Constants.Sentinel.NACOS_DATASOURCE_SK)) - .isEqualTo("testSK"); - - } -}