Merge pull request #2 from yangjuanying/hoxton

Hoxton
pull/1095/head
melodyl 2 years ago committed by GitHub
commit a626ca2015
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,27 @@
name: Release
on:
release:
types: [ published ]
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
server-id: nexus-releases
server-username: MAVEN_USERNAME
server-password: MAVEN_PASSWORD
- name: Publish package
env:
MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }}
MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }}
run: |
cat <(echo -e "${{ secrets.OSSRH_GPG_SECRET_KEY }}") | gpg --batch --import;
mvn clean deploy -U -P release -Dgpg.passphrase=${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }} -DskipTests

@ -1,3 +1,20 @@
# Change Log # Change Log
--- ---
- feature: support reactive discovery client health indicator.
- feature: Enhance default configuration to support `application*.yaml` and `bootstrap*.yaml`.
- feat:adapt for nacos instance.
- Refactoring: Refactor Circuitbreaker ut.
- refactor:refactor rpc enhancement.
- feat:refactor SDKContext as static.
- docs:add release GitHub Action.
- docs:update Polaris test environment ip.
- fix:fix custom fallback exception.
- feat:sct-all package is now available as a shaded uber-jar.
- fix:use path parameter in `@FeignClient` for circuit-breaker.
- build(deps): bump guava in /spring-cloud-tencent-dependencies
- fix:fix reporting bug when port is -1.
- fix:update guava version.
- fix:fix circuit breaker bean load order bug when using Nacos discovery.
- refactor:refactor Polaris registration.
- feat:added automatic optimization for dynamic config refresh type.

@ -78,7 +78,7 @@ Spring Cloud Tencent 所有组件都已上传到 Maven 中央仓库,只需要
<groupId>com.tencent.cloud</groupId> <groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-dependencies</artifactId> <artifactId>spring-cloud-tencent-dependencies</artifactId>
<!--version number--> <!--version number-->
<version>1.11.7-Hoxton.SR12</version> <version>1.11.8-Hoxton.SR12</version>
<type>pom</type> <type>pom</type>
<scope>import</scope> <scope>import</scope>
</dependency> </dependency>

@ -81,7 +81,7 @@ For example:
<groupId>com.tencent.cloud</groupId> <groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-dependencies</artifactId> <artifactId>spring-cloud-tencent-dependencies</artifactId>
<!--version number--> <!--version number-->
<version>1.11.7-Hoxton.SR12</version> <version>1.11.8-Hoxton.SR12</version>
<type>pom</type> <type>pom</type>
<scope>import</scope> <scope>import</scope>
</dependency> </dependency>

@ -89,7 +89,7 @@
<properties> <properties>
<!-- Project revision --> <!-- Project revision -->
<revision>1.11.7-Hoxton.SR12</revision> <revision>1.12.0-Hoxton.SR12-SNAPSHOT</revision>
<!-- Spring Framework --> <!-- Spring Framework -->
<spring.framework.version>5.2.22.RELEASE</spring.framework.version> <spring.framework.version>5.2.22.RELEASE</spring.framework.version>
@ -105,6 +105,7 @@
<maven-source-plugin.version>3.2.0</maven-source-plugin.version> <maven-source-plugin.version>3.2.0</maven-source-plugin.version>
<flatten-maven-plugin.version>1.2.7</flatten-maven-plugin.version> <flatten-maven-plugin.version>1.2.7</flatten-maven-plugin.version>
<maven-gpg-plugin.version>3.0.1</maven-gpg-plugin.version> <maven-gpg-plugin.version>3.0.1</maven-gpg-plugin.version>
<maven-shade-plugin.version>3.4.1</maven-shade-plugin.version>
<!-- Checkstyle --> <!-- Checkstyle -->
<maven-checkstyle-plugin.failsOnError>true</maven-checkstyle-plugin.failsOnError> <maven-checkstyle-plugin.failsOnError>true</maven-checkstyle-plugin.failsOnError>
@ -161,6 +162,11 @@
<artifactId>jacoco-maven-plugin</artifactId> <artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.version}</version> <version>${jacoco.version}</version>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>${maven-shade-plugin.version}</version>
</plugin>
</plugins> </plugins>
</pluginManagement> </pluginManagement>
<plugins> <plugins>

@ -57,4 +57,49 @@
<artifactId>spring-boot-starter-actuator</artifactId> <artifactId>spring-boot-starter-actuator</artifactId>
</dependency> </dependency>
</dependencies> </dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<executions>
<execution>
<id>attach-javadocs</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
<executions>
<execution>
<id>sct-all-shade</id>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<createSourcesJar>true</createSourcesJar>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring/org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration.imports</resource>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports</resource>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project> </project>

@ -109,12 +109,6 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-contract-stub-runner</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>com.tencent.polaris</groupId> <groupId>com.tencent.polaris</groupId>
<artifactId>polaris-test-common</artifactId> <artifactId>polaris-test-common</artifactId>

@ -30,26 +30,20 @@ import com.tencent.cloud.polaris.circuitbreaker.resttemplate.PolarisCircuitBreak
import com.tencent.cloud.polaris.circuitbreaker.zuul.PolarisCircuitBreakerPostZuulFilter; import com.tencent.cloud.polaris.circuitbreaker.zuul.PolarisCircuitBreakerPostZuulFilter;
import com.tencent.cloud.polaris.circuitbreaker.zuul.PolarisCircuitBreakerZuulFilter; import com.tencent.cloud.polaris.circuitbreaker.zuul.PolarisCircuitBreakerZuulFilter;
import com.tencent.cloud.polaris.circuitbreaker.zuul.PolarisZuulFallbackFactory; import com.tencent.cloud.polaris.circuitbreaker.zuul.PolarisZuulFallbackFactory;
import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementAutoConfiguration; import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementAutoConfiguration;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties; import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.polaris.api.core.ConsumerAPI;
import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI;
import com.tencent.polaris.circuitbreak.factory.CircuitBreakAPIFactory;
import com.tencent.polaris.client.api.SDKContext;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory; import org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory;
import org.springframework.cloud.client.circuitbreaker.Customizer; import org.springframework.cloud.client.circuitbreaker.Customizer;
import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider; import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
import org.springframework.cloud.openfeign.PolarisFeignCircuitBreakerTargeterAutoConfiguration;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
@ -61,12 +55,6 @@ import org.springframework.core.env.Environment;
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@ConditionalOnPolarisCircuitBreakerEnabled @ConditionalOnPolarisCircuitBreakerEnabled
@AutoConfigureAfter(RpcEnhancementAutoConfiguration.class) @AutoConfigureAfter(RpcEnhancementAutoConfiguration.class)
@Import({
ReactivePolarisCircuitBreakerAutoConfiguration.class,
PolarisFeignCircuitBreakerTargeterAutoConfiguration.class,
PolarisCircuitBreakerFeignClientAutoConfiguration.class,
GatewayPolarisCircuitBreakerAutoConfiguration.class
})
public class PolarisCircuitBreakerAutoConfiguration { public class PolarisCircuitBreakerAutoConfiguration {
@Autowired(required = false) @Autowired(required = false)
@ -85,36 +73,30 @@ public class PolarisCircuitBreakerAutoConfiguration {
return new PolarisCircuitBreakerRestTemplateBeanPostProcessor(applicationContext); return new PolarisCircuitBreakerRestTemplateBeanPostProcessor(applicationContext);
} }
@Bean
@ConditionalOnMissingBean(CircuitBreakAPI.class)
public CircuitBreakAPI circuitBreakAPI(SDKContext polarisContext) {
return CircuitBreakAPIFactory.createCircuitBreakAPIByContext(polarisContext);
}
@Bean @Bean
@ConditionalOnMissingBean(SuccessCircuitBreakerReporter.class) @ConditionalOnMissingBean(SuccessCircuitBreakerReporter.class)
public SuccessCircuitBreakerReporter successCircuitBreakerReporter(RpcEnhancementReporterProperties properties, public SuccessCircuitBreakerReporter successCircuitBreakerReporter(RpcEnhancementReporterProperties properties,
SDKContext polarisContext, CircuitBreakAPI circuitBreakAPI) { PolarisSDKContextManager polarisSDKContextManager) {
return new SuccessCircuitBreakerReporter(properties, polarisContext, circuitBreakAPI); return new SuccessCircuitBreakerReporter(properties, polarisSDKContextManager.getCircuitBreakAPI());
} }
@Bean @Bean
@ConditionalOnMissingBean(ExceptionCircuitBreakerReporter.class) @ConditionalOnMissingBean(ExceptionCircuitBreakerReporter.class)
public ExceptionCircuitBreakerReporter exceptionCircuitBreakerReporter(RpcEnhancementReporterProperties properties, public ExceptionCircuitBreakerReporter exceptionCircuitBreakerReporter(RpcEnhancementReporterProperties properties,
SDKContext polarisContext, CircuitBreakAPI circuitBreakAPI) { PolarisSDKContextManager polarisSDKContextManager) {
return new ExceptionCircuitBreakerReporter(properties, polarisContext, circuitBreakAPI); return new ExceptionCircuitBreakerReporter(properties, polarisSDKContextManager.getCircuitBreakAPI());
} }
@Bean @Bean
@ConditionalOnMissingBean(CircuitBreakerFactory.class) @ConditionalOnMissingBean(CircuitBreakerFactory.class)
public CircuitBreakerFactory polarisCircuitBreakerFactory(CircuitBreakAPI circuitBreakAPI, ConsumerAPI consumerAPI) { public CircuitBreakerFactory polarisCircuitBreakerFactory(PolarisSDKContextManager polarisSDKContextManager) {
PolarisCircuitBreakerFactory factory = new PolarisCircuitBreakerFactory(circuitBreakAPI, consumerAPI); PolarisCircuitBreakerFactory factory = new PolarisCircuitBreakerFactory(
polarisSDKContextManager.getCircuitBreakAPI(), polarisSDKContextManager.getConsumerAPI());
customizers.forEach(customizer -> customizer.customize(factory)); customizers.forEach(customizer -> customizer.customize(factory));
return factory; return factory;
} }
@Bean @Bean
@ConditionalOnBean(RpcEnhancementReporterProperties.class)
@ConditionalOnMissingBean(CircuitBreakerConfigModifier.class) @ConditionalOnMissingBean(CircuitBreakerConfigModifier.class)
public CircuitBreakerConfigModifier circuitBreakerConfigModifier(RpcEnhancementReporterProperties properties) { public CircuitBreakerConfigModifier circuitBreakerConfigModifier(RpcEnhancementReporterProperties properties) {
return new CircuitBreakerConfigModifier(properties); return new CircuitBreakerConfigModifier(properties);

@ -17,10 +17,7 @@
package com.tencent.cloud.polaris.circuitbreaker.config; package com.tencent.cloud.polaris.circuitbreaker.config;
import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementAutoConfiguration;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
@ -30,8 +27,13 @@ import org.springframework.context.annotation.Import;
* @author lepdou 2022-03-29 * @author lepdou 2022-03-29
*/ */
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@ConditionalOnPolarisEnabled @ConditionalOnProperty("spring.cloud.polaris.enabled")
@Import({PolarisContextAutoConfiguration.class, RpcEnhancementAutoConfiguration.class, PolarisCircuitBreakerAutoConfiguration.class}) @Import({
PolarisCircuitBreakerAutoConfiguration.class,
ReactivePolarisCircuitBreakerAutoConfiguration.class,
PolarisCircuitBreakerFeignClientAutoConfiguration.class,
GatewayPolarisCircuitBreakerAutoConfiguration.class
})
public class PolarisCircuitBreakerBootstrapConfiguration { public class PolarisCircuitBreakerBootstrapConfiguration {
} }

@ -24,16 +24,12 @@ import com.tencent.cloud.polaris.circuitbreaker.ReactivePolarisCircuitBreakerFac
import com.tencent.cloud.polaris.circuitbreaker.common.CircuitBreakerConfigModifier; import com.tencent.cloud.polaris.circuitbreaker.common.CircuitBreakerConfigModifier;
import com.tencent.cloud.polaris.circuitbreaker.reporter.ExceptionCircuitBreakerReporter; import com.tencent.cloud.polaris.circuitbreaker.reporter.ExceptionCircuitBreakerReporter;
import com.tencent.cloud.polaris.circuitbreaker.reporter.SuccessCircuitBreakerReporter; import com.tencent.cloud.polaris.circuitbreaker.reporter.SuccessCircuitBreakerReporter;
import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementAutoConfiguration; import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementAutoConfiguration;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties; import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.polaris.api.core.ConsumerAPI;
import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI;
import com.tencent.polaris.circuitbreak.factory.CircuitBreakAPIFactory;
import com.tencent.polaris.client.api.SDKContext;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.client.circuitbreaker.Customizer; import org.springframework.cloud.client.circuitbreaker.Customizer;
@ -47,7 +43,7 @@ import org.springframework.context.annotation.Configuration;
* @author seanyu 2023-02-27 * @author seanyu 2023-02-27
*/ */
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@ConditionalOnClass(name = { "reactor.core.publisher.Mono", "reactor.core.publisher.Flux" }) @ConditionalOnClass(name = {"reactor.core.publisher.Mono", "reactor.core.publisher.Flux"})
@ConditionalOnPolarisCircuitBreakerEnabled @ConditionalOnPolarisCircuitBreakerEnabled
@AutoConfigureAfter(RpcEnhancementAutoConfiguration.class) @AutoConfigureAfter(RpcEnhancementAutoConfiguration.class)
public class ReactivePolarisCircuitBreakerAutoConfiguration { public class ReactivePolarisCircuitBreakerAutoConfiguration {
@ -55,36 +51,30 @@ public class ReactivePolarisCircuitBreakerAutoConfiguration {
@Autowired(required = false) @Autowired(required = false)
private List<Customizer<ReactivePolarisCircuitBreakerFactory>> customizers = new ArrayList<>(); private List<Customizer<ReactivePolarisCircuitBreakerFactory>> customizers = new ArrayList<>();
@Bean
@ConditionalOnMissingBean(CircuitBreakAPI.class)
public CircuitBreakAPI circuitBreakAPI(SDKContext polarisContext) {
return CircuitBreakAPIFactory.createCircuitBreakAPIByContext(polarisContext);
}
@Bean @Bean
@ConditionalOnMissingBean(SuccessCircuitBreakerReporter.class) @ConditionalOnMissingBean(SuccessCircuitBreakerReporter.class)
public SuccessCircuitBreakerReporter successCircuitBreakerReporter(RpcEnhancementReporterProperties properties, public SuccessCircuitBreakerReporter successCircuitBreakerReporter(RpcEnhancementReporterProperties properties,
SDKContext polarisContext, CircuitBreakAPI circuitBreakAPI) { PolarisSDKContextManager polarisSDKContextManager) {
return new SuccessCircuitBreakerReporter(properties, polarisContext, circuitBreakAPI); return new SuccessCircuitBreakerReporter(properties, polarisSDKContextManager.getCircuitBreakAPI());
} }
@Bean @Bean
@ConditionalOnMissingBean(ExceptionCircuitBreakerReporter.class) @ConditionalOnMissingBean(ExceptionCircuitBreakerReporter.class)
public ExceptionCircuitBreakerReporter exceptionCircuitBreakerReporter(RpcEnhancementReporterProperties properties, public ExceptionCircuitBreakerReporter exceptionCircuitBreakerReporter(RpcEnhancementReporterProperties properties,
SDKContext polarisContext, CircuitBreakAPI circuitBreakAPI) { PolarisSDKContextManager polarisSDKContextManager) {
return new ExceptionCircuitBreakerReporter(properties, polarisContext, circuitBreakAPI); return new ExceptionCircuitBreakerReporter(properties, polarisSDKContextManager.getCircuitBreakAPI());
} }
@Bean @Bean
@ConditionalOnMissingBean(ReactiveCircuitBreakerFactory.class) @ConditionalOnMissingBean(ReactiveCircuitBreakerFactory.class)
public ReactiveCircuitBreakerFactory polarisReactiveCircuitBreakerFactory(CircuitBreakAPI circuitBreakAPI, ConsumerAPI consumerAPI) { public ReactiveCircuitBreakerFactory polarisReactiveCircuitBreakerFactory(PolarisSDKContextManager polarisSDKContextManager) {
ReactivePolarisCircuitBreakerFactory factory = new ReactivePolarisCircuitBreakerFactory(circuitBreakAPI, consumerAPI); ReactivePolarisCircuitBreakerFactory factory = new ReactivePolarisCircuitBreakerFactory(
polarisSDKContextManager.getCircuitBreakAPI(), polarisSDKContextManager.getConsumerAPI());
customizers.forEach(customizer -> customizer.customize(factory)); customizers.forEach(customizer -> customizer.customize(factory));
return factory; return factory;
} }
@Bean @Bean
@ConditionalOnBean(RpcEnhancementReporterProperties.class)
@ConditionalOnMissingBean(CircuitBreakerConfigModifier.class) @ConditionalOnMissingBean(CircuitBreakerConfigModifier.class)
public CircuitBreakerConfigModifier reactiveCircuitBreakerConfigModifier(RpcEnhancementReporterProperties properties) { public CircuitBreakerConfigModifier reactiveCircuitBreakerConfigModifier(RpcEnhancementReporterProperties properties) {
return new CircuitBreakerConfigModifier(properties); return new CircuitBreakerConfigModifier(properties);

@ -18,10 +18,15 @@
package com.tencent.cloud.polaris.circuitbreaker.feign; package com.tencent.cloud.polaris.circuitbreaker.feign;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.net.URI;
import java.net.URISyntaxException;
import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.cloud.common.metadata.MetadataContext;
import feign.Target; import feign.Target;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import static org.springframework.core.annotation.AnnotatedElementUtils.findMergedAnnotation; import static org.springframework.core.annotation.AnnotatedElementUtils.findMergedAnnotation;
@ -33,12 +38,30 @@ import static org.springframework.core.annotation.AnnotatedElementUtils.findMerg
*/ */
public class PolarisCircuitBreakerNameResolver { public class PolarisCircuitBreakerNameResolver {
private static final Logger LOG = LoggerFactory.getLogger(PolarisCircuitBreakerNameResolver.class);
public String resolveCircuitBreakerName(String feignClientName, Target<?> target, Method method) { public String resolveCircuitBreakerName(String feignClientName, Target<?> target, Method method) {
String serviceName = target.name(); String serviceName = target.name();
RequestMapping requestMapping = findMergedAnnotation(method, RequestMapping.class);
String path = ""; String path = "";
// Get path in @FeignClient.
if (StringUtils.hasText(target.url())) {
URI uri = null;
try {
uri = new URI(target.url());
}
catch (URISyntaxException e) {
LOG.warn("Generate URI from url({}) in @FeignClient. failed.", target.url());
}
if (uri != null) {
path += uri.getPath();
}
}
// Get path in @RequestMapping.
RequestMapping requestMapping = findMergedAnnotation(method, RequestMapping.class);
if (requestMapping != null) { if (requestMapping != null) {
path = requestMapping.path().length == 0 ? path += requestMapping.path().length == 0 ?
requestMapping.value().length == 0 ? "" : requestMapping.value()[0] : requestMapping.value().length == 0 ? "" : requestMapping.value()[0] :
requestMapping.path()[0]; requestMapping.path()[0];
} }
@ -46,4 +69,5 @@ public class PolarisCircuitBreakerNameResolver {
MetadataContext.LOCAL_NAMESPACE + "#" + serviceName : MetadataContext.LOCAL_NAMESPACE + "#" + serviceName :
MetadataContext.LOCAL_NAMESPACE + "#" + serviceName + "#" + path; MetadataContext.LOCAL_NAMESPACE + "#" + serviceName + "#" + path;
} }
} }

@ -19,32 +19,38 @@ package com.tencent.cloud.polaris.circuitbreaker.reporter;
import java.util.Optional; import java.util.Optional;
import com.tencent.cloud.rpc.enhancement.AbstractPolarisReporterAdapter;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties; import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.PolarisEnhancedPluginUtils;
import com.tencent.polaris.api.plugin.circuitbreaker.ResourceStat; import com.tencent.polaris.api.plugin.circuitbreaker.ResourceStat;
import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI; import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI;
import com.tencent.polaris.client.api.SDKContext;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.ServiceInstance;
import org.springframework.core.Ordered;
public class ExceptionCircuitBreakerReporter extends AbstractPolarisReporterAdapter implements EnhancedPlugin { import static com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant.ClientPluginOrder.CIRCUIT_BREAKER_REPORTER_PLUGIN_ORDER;
/**
* ExceptionCircuitBreakerReporter.
*
* @author sean yu
*/
public class ExceptionCircuitBreakerReporter implements EnhancedPlugin {
private static final Logger LOG = LoggerFactory.getLogger(ExceptionCircuitBreakerReporter.class); private static final Logger LOG = LoggerFactory.getLogger(ExceptionCircuitBreakerReporter.class);
private final CircuitBreakAPI circuitBreakAPI; private final CircuitBreakAPI circuitBreakAPI;
private final RpcEnhancementReporterProperties reportProperties;
public ExceptionCircuitBreakerReporter(RpcEnhancementReporterProperties reportProperties, public ExceptionCircuitBreakerReporter(RpcEnhancementReporterProperties reportProperties,
SDKContext context,
CircuitBreakAPI circuitBreakAPI) { CircuitBreakAPI circuitBreakAPI) {
super(reportProperties, context); this.reportProperties = reportProperties;
this.circuitBreakAPI = circuitBreakAPI; this.circuitBreakAPI = circuitBreakAPI;
} }
@ -55,19 +61,20 @@ public class ExceptionCircuitBreakerReporter extends AbstractPolarisReporterAdap
@Override @Override
public EnhancedPluginType getType() { public EnhancedPluginType getType() {
return EnhancedPluginType.EXCEPTION; return EnhancedPluginType.Client.EXCEPTION;
} }
@Override @Override
public void run(EnhancedPluginContext context) throws Throwable { public void run(EnhancedPluginContext context) throws Throwable {
if (!super.reportProperties.isEnabled()) { if (!this.reportProperties.isEnabled()) {
return; return;
} }
EnhancedRequestContext request = context.getRequest(); EnhancedRequestContext request = context.getRequest();
ServiceInstance serviceInstance = Optional.ofNullable(context.getServiceInstance()).orElse(new DefaultServiceInstance()); ServiceInstance serviceInstance = Optional.ofNullable(context.getTargetServiceInstance())
.orElse(new DefaultServiceInstance());
ResourceStat resourceStat = createInstanceResourceStat( ResourceStat resourceStat = PolarisEnhancedPluginUtils.createInstanceResourceStat(
serviceInstance.getServiceId(), serviceInstance.getServiceId(),
serviceInstance.getHost(), serviceInstance.getHost(),
serviceInstance.getPort(), serviceInstance.getPort(),
@ -78,7 +85,8 @@ public class ExceptionCircuitBreakerReporter extends AbstractPolarisReporterAdap
); );
LOG.debug("Will report CircuitBreaker ResourceStat of {}. Request=[{} {}]. Response=[{}]. Delay=[{}]ms.", LOG.debug("Will report CircuitBreaker ResourceStat of {}. Request=[{} {}]. Response=[{}]. Delay=[{}]ms.",
resourceStat.getRetStatus().name(), request.getHttpMethod().name(), request.getUrl().getPath(), context.getThrowable().getMessage(), context.getDelay()); resourceStat.getRetStatus().name(), request.getHttpMethod().name(), request.getUrl()
.getPath(), context.getThrowable().getMessage(), context.getDelay());
circuitBreakAPI.report(resourceStat); circuitBreakAPI.report(resourceStat);
@ -92,6 +100,6 @@ public class ExceptionCircuitBreakerReporter extends AbstractPolarisReporterAdap
@Override @Override
public int getOrder() { public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE + 2; return CIRCUIT_BREAKER_REPORTER_PLUGIN_ORDER;
} }
} }

@ -19,35 +19,40 @@ package com.tencent.cloud.polaris.circuitbreaker.reporter;
import java.util.Optional; import java.util.Optional;
import com.tencent.cloud.rpc.enhancement.AbstractPolarisReporterAdapter;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties; import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext;
import com.tencent.cloud.rpc.enhancement.plugin.PolarisEnhancedPluginUtils;
import com.tencent.cloud.rpc.enhancement.plugin.reporter.SuccessPolarisReporter; import com.tencent.cloud.rpc.enhancement.plugin.reporter.SuccessPolarisReporter;
import com.tencent.polaris.api.plugin.circuitbreaker.ResourceStat; import com.tencent.polaris.api.plugin.circuitbreaker.ResourceStat;
import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI; import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI;
import com.tencent.polaris.client.api.SDKContext;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.ServiceInstance;
import org.springframework.core.Ordered;
import static com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant.ClientPluginOrder.CIRCUIT_BREAKER_REPORTER_PLUGIN_ORDER;
public class SuccessCircuitBreakerReporter extends AbstractPolarisReporterAdapter implements EnhancedPlugin { /**
* SuccessCircuitBreakerReporter.
*
* @author sean yu
*/
public class SuccessCircuitBreakerReporter implements EnhancedPlugin {
private static final Logger LOG = LoggerFactory.getLogger(SuccessPolarisReporter.class); private static final Logger LOG = LoggerFactory.getLogger(SuccessPolarisReporter.class);
private final CircuitBreakAPI circuitBreakAPI; private final CircuitBreakAPI circuitBreakAPI;
private final RpcEnhancementReporterProperties reportProperties;
public SuccessCircuitBreakerReporter(RpcEnhancementReporterProperties reportProperties, public SuccessCircuitBreakerReporter(RpcEnhancementReporterProperties reportProperties,
SDKContext context,
CircuitBreakAPI circuitBreakAPI) { CircuitBreakAPI circuitBreakAPI) {
super(reportProperties, context); this.reportProperties = reportProperties;
this.circuitBreakAPI = circuitBreakAPI; this.circuitBreakAPI = circuitBreakAPI;
} }
@ -58,19 +63,20 @@ public class SuccessCircuitBreakerReporter extends AbstractPolarisReporterAdapte
@Override @Override
public EnhancedPluginType getType() { public EnhancedPluginType getType() {
return EnhancedPluginType.POST; return EnhancedPluginType.Client.POST;
} }
@Override @Override
public void run(EnhancedPluginContext context) throws Throwable { public void run(EnhancedPluginContext context) throws Throwable {
if (!super.reportProperties.isEnabled()) { if (!this.reportProperties.isEnabled()) {
return; return;
} }
EnhancedRequestContext request = context.getRequest(); EnhancedRequestContext request = context.getRequest();
EnhancedResponseContext response = context.getResponse(); EnhancedResponseContext response = context.getResponse();
ServiceInstance serviceInstance = Optional.ofNullable(context.getServiceInstance()).orElse(new DefaultServiceInstance()); ServiceInstance serviceInstance = Optional.ofNullable(context.getTargetServiceInstance())
.orElse(new DefaultServiceInstance());
ResourceStat resourceStat = createInstanceResourceStat( ResourceStat resourceStat = PolarisEnhancedPluginUtils.createInstanceResourceStat(
serviceInstance.getServiceId(), serviceInstance.getServiceId(),
serviceInstance.getHost(), serviceInstance.getHost(),
serviceInstance.getPort(), serviceInstance.getPort(),
@ -81,7 +87,8 @@ public class SuccessCircuitBreakerReporter extends AbstractPolarisReporterAdapte
); );
LOG.debug("Will report CircuitBreaker ResourceStat of {}. Request=[{} {}]. Response=[{}]. Delay=[{}]ms.", LOG.debug("Will report CircuitBreaker ResourceStat of {}. Request=[{} {}]. Response=[{}]. Delay=[{}]ms.",
resourceStat.getRetStatus().name(), request.getHttpMethod().name(), request.getUrl().getPath(), response.getHttpStatus(), context.getDelay()); resourceStat.getRetStatus().name(), request.getHttpMethod().name(), request.getUrl()
.getPath(), response.getHttpStatus(), context.getDelay());
circuitBreakAPI.report(resourceStat); circuitBreakAPI.report(resourceStat);
} }
@ -94,6 +101,6 @@ public class SuccessCircuitBreakerReporter extends AbstractPolarisReporterAdapte
@Override @Override
public int getOrder() { public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE + 2; return CIRCUIT_BREAKER_REPORTER_PLUGIN_ORDER;
} }
} }

@ -23,6 +23,7 @@ import com.tencent.cloud.polaris.circuitbreaker.feign.PolarisCircuitBreakerNameR
import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory; import org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@ -36,7 +37,7 @@ import org.springframework.context.annotation.Primary;
*/ */
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@ConditionalOnClass({Targeter.class}) @ConditionalOnClass({Targeter.class})
@ConditionalOnProperty(value = "feign.circuitbreaker.enabled", havingValue = "true") @ConditionalOnProperty(value = "feign.hystrix.enabled", havingValue = "true")
@AutoConfigureBefore(FeignAutoConfiguration.class) @AutoConfigureBefore(FeignAutoConfiguration.class)
@ConditionalOnPolarisCircuitBreakerEnabled @ConditionalOnPolarisCircuitBreakerEnabled
public class PolarisFeignCircuitBreakerTargeterAutoConfiguration { public class PolarisFeignCircuitBreakerTargeterAutoConfiguration {
@ -44,6 +45,7 @@ public class PolarisFeignCircuitBreakerTargeterAutoConfiguration {
@Bean @Bean
@Primary @Primary
@ConditionalOnBean(CircuitBreakerFactory.class) @ConditionalOnBean(CircuitBreakerFactory.class)
@ConditionalOnMissingBean(Targeter.class)
public Targeter polarisFeignCircuitBreakerTargeter(CircuitBreakerFactory circuitBreakerFactory, PolarisCircuitBreakerNameResolver circuitBreakerNameResolver) { public Targeter polarisFeignCircuitBreakerTargeter(CircuitBreakerFactory circuitBreakerFactory, PolarisCircuitBreakerNameResolver circuitBreakerNameResolver) {
return new PolarisFeignCircuitBreakerTargeter(circuitBreakerFactory, circuitBreakerNameResolver); return new PolarisFeignCircuitBreakerTargeter(circuitBreakerFactory, circuitBreakerNameResolver);
} }

@ -5,4 +5,5 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.tencent.cloud.polaris.circuitbreaker.config.PolarisCircuitBreakerFeignClientAutoConfiguration,\ com.tencent.cloud.polaris.circuitbreaker.config.PolarisCircuitBreakerFeignClientAutoConfiguration,\
org.springframework.cloud.openfeign.PolarisFeignCircuitBreakerTargeterAutoConfiguration org.springframework.cloud.openfeign.PolarisFeignCircuitBreakerTargeterAutoConfiguration
org.springframework.cloud.bootstrap.BootstrapConfiguration=\ org.springframework.cloud.bootstrap.BootstrapConfiguration=\
com.tencent.cloud.polaris.circuitbreaker.config.PolarisCircuitBreakerBootstrapConfiguration com.tencent.cloud.polaris.circuitbreaker.config.PolarisCircuitBreakerBootstrapConfiguration,\
org.springframework.cloud.openfeign.PolarisFeignCircuitBreakerTargeterAutoConfiguration

@ -30,6 +30,7 @@ import java.util.stream.Collectors;
import com.google.protobuf.util.JsonFormat; import com.google.protobuf.util.JsonFormat;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils; import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
import com.tencent.polaris.api.config.Configuration; import com.tencent.polaris.api.config.Configuration;
import com.tencent.polaris.api.core.ConsumerAPI; import com.tencent.polaris.api.core.ConsumerAPI;
import com.tencent.polaris.api.pojo.ServiceKey; import com.tencent.polaris.api.pojo.ServiceKey;
@ -76,22 +77,21 @@ public class PolarisCircuitBreakerMockServerTest {
.thenReturn(NAMESPACE_TEST); .thenReturn(NAMESPACE_TEST);
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties("spring.cloud.polaris.service")) mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties("spring.cloud.polaris.service"))
.thenReturn(SERVICE_CIRCUIT_BREAKER); .thenReturn(SERVICE_CIRCUIT_BREAKER);
PolarisSDKContextManager.innerDestroy();
namingServer = NamingServer.startNamingServer(-1);
System.setProperty(SERVER_ADDRESS_ENV, String.format("127.0.0.1:%d", namingServer.getPort()));
try {
namingServer = NamingServer.startNamingServer(-1);
System.setProperty(SERVER_ADDRESS_ENV, String.format("127.0.0.1:%d", namingServer.getPort()));
}
catch (IOException e) {
}
ServiceKey serviceKey = new ServiceKey(NAMESPACE_TEST, SERVICE_CIRCUIT_BREAKER); ServiceKey serviceKey = new ServiceKey(NAMESPACE_TEST, SERVICE_CIRCUIT_BREAKER);
CircuitBreakerProto.CircuitBreakerRule.Builder circuitBreakerRuleBuilder = CircuitBreakerProto.CircuitBreakerRule.newBuilder(); CircuitBreakerProto.CircuitBreakerRule.Builder circuitBreakerRuleBuilder = CircuitBreakerProto.CircuitBreakerRule.newBuilder();
InputStream inputStream = PolarisCircuitBreakerMockServerTest.class.getClassLoader().getResourceAsStream("circuitBreakerRule.json"); InputStream inputStream = PolarisCircuitBreakerMockServerTest.class.getClassLoader()
String json = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)).lines().collect(Collectors.joining("")); .getResourceAsStream("circuitBreakerRule.json");
String json = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)).lines()
.collect(Collectors.joining(""));
JsonFormat.parser().ignoringUnknownFields().merge(json, circuitBreakerRuleBuilder); JsonFormat.parser().ignoringUnknownFields().merge(json, circuitBreakerRuleBuilder);
CircuitBreakerProto.CircuitBreakerRule circuitBreakerRule = circuitBreakerRuleBuilder.build(); CircuitBreakerProto.CircuitBreakerRule circuitBreakerRule = circuitBreakerRuleBuilder.build();
CircuitBreakerProto.CircuitBreaker circuitBreaker = CircuitBreakerProto.CircuitBreaker.newBuilder().addRules(circuitBreakerRule).build(); CircuitBreakerProto.CircuitBreaker circuitBreaker = CircuitBreakerProto.CircuitBreaker.newBuilder()
.addRules(circuitBreakerRule).build();
namingServer.getNamingService().setCircuitBreaker(serviceKey, circuitBreaker); namingServer.getNamingService().setCircuitBreaker(serviceKey, circuitBreaker);
} }
@ -100,6 +100,9 @@ public class PolarisCircuitBreakerMockServerTest {
if (null != namingServer) { if (null != namingServer) {
namingServer.terminate(); namingServer.terminate();
} }
if (null != mockedApplicationContextAwareUtils) {
mockedApplicationContextAwareUtils.close();
}
} }
@Test @Test
@ -138,7 +141,8 @@ public class PolarisCircuitBreakerMockServerTest {
assertThat(Mono.error(new RuntimeException("boom")).transform(it -> rcb.run(it, t -> Mono.just("fallback"))) assertThat(Mono.error(new RuntimeException("boom")).transform(it -> rcb.run(it, t -> Mono.just("fallback")))
.block()).isEqualTo("fallback"); .block()).isEqualTo("fallback");
assertThat(Flux.just("foobar", "hello world").transform(it -> rcb.run(it, t -> Flux.just("fallback", "fallback"))) assertThat(Flux.just("foobar", "hello world")
.transform(it -> rcb.run(it, t -> Flux.just("fallback", "fallback")))
.collectList().block()) .collectList().block())
.isEqualTo(Arrays.asList("fallback", "fallback")); .isEqualTo(Arrays.asList("fallback", "fallback"));
@ -146,7 +150,6 @@ public class PolarisCircuitBreakerMockServerTest {
.collectList().block()) .collectList().block())
.isEqualTo(Collections.singletonList("fallback")); .isEqualTo(Collections.singletonList("fallback"));
} }
} }

@ -49,7 +49,7 @@ import static org.assertj.core.api.Assertions.assertThat;
@ExtendWith(MockitoExtension.class) @ExtendWith(MockitoExtension.class)
public class PolarisCircuitBreakerTest { public class PolarisCircuitBreakerTest {
private static final ApplicationContextRunner contextRunner = new ApplicationContextRunner() private static ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of( .withConfiguration(AutoConfigurations.of(
PolarisContextAutoConfiguration.class, PolarisContextAutoConfiguration.class,
RpcEnhancementAutoConfiguration.class, RpcEnhancementAutoConfiguration.class,
@ -76,7 +76,7 @@ public class PolarisCircuitBreakerTest {
@Test @Test
public void run() { public void run() {
contextRunner.run(context -> { this.contextRunner.run(context -> {
PolarisCircuitBreakerFactory polarisCircuitBreakerFactory = context.getBean(PolarisCircuitBreakerFactory.class); PolarisCircuitBreakerFactory polarisCircuitBreakerFactory = context.getBean(PolarisCircuitBreakerFactory.class);
CircuitBreaker cb = polarisCircuitBreakerFactory.create(SERVICE_CIRCUIT_BREAKER); CircuitBreaker cb = polarisCircuitBreakerFactory.create(SERVICE_CIRCUIT_BREAKER);
@ -95,4 +95,7 @@ public class PolarisCircuitBreakerTest {
}); });
} }
} }

@ -15,15 +15,12 @@
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*/ */
package com.tencent.cloud.polaris.circuitbreaker; package com.tencent.cloud.polaris.circuitbreaker.config;
import com.tencent.cloud.polaris.circuitbreaker.common.CircuitBreakerConfigModifier; import com.tencent.cloud.polaris.circuitbreaker.common.CircuitBreakerConfigModifier;
import com.tencent.cloud.polaris.circuitbreaker.config.PolarisCircuitBreakerAutoConfiguration;
import com.tencent.cloud.polaris.circuitbreaker.config.ReactivePolarisCircuitBreakerAutoConfiguration;
import com.tencent.cloud.polaris.circuitbreaker.feign.PolarisCircuitBreakerNameResolver; import com.tencent.cloud.polaris.circuitbreaker.feign.PolarisCircuitBreakerNameResolver;
import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration; import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementAutoConfiguration; import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementAutoConfiguration;
import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
@ -39,12 +36,13 @@ import static org.assertj.core.api.Assertions.assertThat;
* *
* @author Haotian Zhang * @author Haotian Zhang
*/ */
public class CircuitBreakerPolarisAutoConfigurationTest { public class PolarisCircuitBreakerAutoConfigurationTest {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of( .withConfiguration(AutoConfigurations.of(
PolarisContextAutoConfiguration.class, PolarisContextAutoConfiguration.class,
RpcEnhancementAutoConfiguration.class, RpcEnhancementAutoConfiguration.class,
LoadBalancerAutoConfiguration.class, LoadBalancerAutoConfiguration.class,
PolarisCircuitBreakerFeignClientAutoConfiguration.class,
PolarisCircuitBreakerAutoConfiguration.class)) PolarisCircuitBreakerAutoConfiguration.class))
.withPropertyValues("spring.cloud.polaris.circuitbreaker.enabled=true"); .withPropertyValues("spring.cloud.polaris.circuitbreaker.enabled=true");
@ -62,7 +60,6 @@ public class CircuitBreakerPolarisAutoConfigurationTest {
assertThat(context).hasSingleBean(PolarisCircuitBreakerAutoConfiguration.class); assertThat(context).hasSingleBean(PolarisCircuitBreakerAutoConfiguration.class);
assertThat(context).hasSingleBean(CircuitBreakerFactory.class); assertThat(context).hasSingleBean(CircuitBreakerFactory.class);
assertThat(context).hasSingleBean(CircuitBreakerConfigModifier.class); assertThat(context).hasSingleBean(CircuitBreakerConfigModifier.class);
assertThat(context).hasSingleBean(CircuitBreakAPI.class);
assertThat(context).hasSingleBean(PolarisCircuitBreakerNameResolver.class); assertThat(context).hasSingleBean(PolarisCircuitBreakerNameResolver.class);
}); });
} }
@ -73,7 +70,6 @@ public class CircuitBreakerPolarisAutoConfigurationTest {
assertThat(context).hasSingleBean(ReactivePolarisCircuitBreakerAutoConfiguration.class); assertThat(context).hasSingleBean(ReactivePolarisCircuitBreakerAutoConfiguration.class);
assertThat(context).hasSingleBean(ReactiveCircuitBreakerFactory.class); assertThat(context).hasSingleBean(ReactiveCircuitBreakerFactory.class);
assertThat(context).hasSingleBean(CircuitBreakerConfigModifier.class); assertThat(context).hasSingleBean(CircuitBreakerConfigModifier.class);
assertThat(context).hasSingleBean(CircuitBreakAPI.class);
}); });
} }

@ -15,12 +15,8 @@
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*/ */
package com.tencent.cloud.polaris.circuitbreaker; package com.tencent.cloud.polaris.circuitbreaker.config;
import com.tencent.cloud.polaris.circuitbreaker.config.PolarisCircuitBreakerAutoConfiguration;
import com.tencent.cloud.polaris.circuitbreaker.config.PolarisCircuitBreakerBootstrapConfiguration;
import com.tencent.cloud.polaris.circuitbreaker.config.PolarisCircuitBreakerFeignClientAutoConfiguration;
import com.tencent.cloud.polaris.circuitbreaker.config.ReactivePolarisCircuitBreakerAutoConfiguration;
import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration; import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementAutoConfiguration; import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementAutoConfiguration;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;

@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*/ */
package com.tencent.cloud.polaris.circuitbreaker; package com.tencent.cloud.polaris.circuitbreaker.feign;
import java.io.BufferedReader; import java.io.BufferedReader;
@ -24,37 +24,49 @@ import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.util.JsonFormat; import com.google.protobuf.util.JsonFormat;
import com.tencent.cloud.polaris.circuitbreaker.PolarisCircuitBreakerFactory;
import com.tencent.cloud.polaris.circuitbreaker.config.PolarisCircuitBreakerFeignClientAutoConfiguration; import com.tencent.cloud.polaris.circuitbreaker.config.PolarisCircuitBreakerFeignClientAutoConfiguration;
import com.tencent.cloud.polaris.circuitbreaker.reporter.ExceptionCircuitBreakerReporter;
import com.tencent.cloud.polaris.circuitbreaker.reporter.SuccessCircuitBreakerReporter;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.polaris.api.core.ConsumerAPI;
import com.tencent.polaris.api.pojo.ServiceKey; import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI; import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI;
import com.tencent.polaris.circuitbreak.factory.CircuitBreakAPIFactory; import com.tencent.polaris.circuitbreak.factory.CircuitBreakAPIFactory;
import com.tencent.polaris.client.util.Utils; import com.tencent.polaris.client.util.Utils;
import com.tencent.polaris.factory.api.DiscoveryAPIFactory;
import com.tencent.polaris.specification.api.v1.fault.tolerance.CircuitBreakerProto; import com.tencent.polaris.specification.api.v1.fault.tolerance.CircuitBreakerProto;
import com.tencent.polaris.test.common.TestUtils; import com.tencent.polaris.test.common.TestUtils;
import com.tencent.polaris.test.mock.discovery.NamingServer; import com.tencent.polaris.test.mock.discovery.NamingServer;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration; import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory;
import org.springframework.cloud.client.circuitbreaker.Customizer;
import org.springframework.cloud.client.circuitbreaker.NoFallbackAvailableException; import org.springframework.cloud.client.circuitbreaker.NoFallbackAvailableException;
import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.FallbackFactory; import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.cloud.openfeign.FeignClient; import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.cloud.openfeign.PolarisFeignCircuitBreakerTargeter;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.test.annotation.DirtiesContext; import org.springframework.context.annotation.Primary;
import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST;
import static com.tencent.polaris.test.common.TestUtils.SERVER_ADDRESS_ENV; import static com.tencent.polaris.test.common.TestUtils.SERVER_ADDRESS_ENV;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.assertThatThrownBy;
@ -69,33 +81,27 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
properties = { properties = {
"spring.cloud.gateway.enabled=false", "spring.cloud.gateway.enabled=false",
"feign.circuitbreaker.enabled=true", "feign.circuitbreaker.enabled=true",
"spring.cloud.polaris.namespace=default", "spring.cloud.polaris.namespace=" + NAMESPACE_TEST,
"spring.cloud.polaris.service=Test", "spring.cloud.polaris.service=test"
"spring.cloud.polaris.address=grpc://127.0.0.1:10081"
}) })
@DirtiesContext
public class PolarisCircuitBreakerFeignIntegrationTest { public class PolarisCircuitBreakerFeignIntegrationTest {
private static final String TEST_SERVICE_NAME = "test-service-callee"; private static final String TEST_SERVICE_NAME = "test-service-callee";
private static NamingServer namingServer;
@Autowired @Autowired
private EchoService echoService; private EchoService echoService;
@Autowired @Autowired
private FooService fooService; private FooService fooService;
@Autowired @Autowired
private BarService barService; private BarService barService;
@Autowired @Autowired
private BazService bazService; private BazService bazService;
@AfterAll
public static void afterAll() {
if (null != namingServer) {
namingServer.terminate();
}
}
@Test @Test
public void contextLoads() throws Exception { public void contextLoads() {
assertThat(echoService).isNotNull(); assertThat(echoService).isNotNull();
assertThat(fooService).isNotNull(); assertThat(fooService).isNotNull();
} }
@ -120,6 +126,7 @@ public class PolarisCircuitBreakerFeignIntegrationTest {
} }
@FeignClient(value = TEST_SERVICE_NAME, contextId = "1", fallback = EchoServiceFallback.class) @FeignClient(value = TEST_SERVICE_NAME, contextId = "1", fallback = EchoServiceFallback.class)
@Primary
public interface EchoService { public interface EchoService {
@RequestMapping(path = "echo/{str}") @RequestMapping(path = "echo/{str}")
@ -161,6 +168,9 @@ public class PolarisCircuitBreakerFeignIntegrationTest {
@EnableFeignClients @EnableFeignClients
public static class TestConfig { public static class TestConfig {
@Autowired(required = false)
private List<Customizer<PolarisCircuitBreakerFactory>> customizers = new ArrayList<>();
@Bean @Bean
public EchoServiceFallback echoServiceFallback() { public EchoServiceFallback echoServiceFallback() {
return new EchoServiceFallback(); return new EchoServiceFallback();
@ -172,18 +182,18 @@ public class PolarisCircuitBreakerFeignIntegrationTest {
} }
@Bean @Bean
public CircuitBreakAPI circuitBreakAPI() throws InvalidProtocolBufferException { public PreDestroy preDestroy(NamingServer namingServer) {
try { return new PreDestroy(namingServer);
namingServer = NamingServer.startNamingServer(10081); }
System.setProperty(SERVER_ADDRESS_ENV, String.format("127.0.0.1:%d", namingServer.getPort()));
}
catch (IOException e) {
} @Bean
ServiceKey serviceKey = new ServiceKey("default", TEST_SERVICE_NAME); public NamingServer namingServer() throws IOException {
NamingServer namingServer = NamingServer.startNamingServer(-1);
System.setProperty(SERVER_ADDRESS_ENV, String.format("127.0.0.1:%d", namingServer.getPort()));
ServiceKey serviceKey = new ServiceKey(NAMESPACE_TEST, TEST_SERVICE_NAME);
CircuitBreakerProto.CircuitBreakerRule.Builder circuitBreakerRuleBuilder = CircuitBreakerProto.CircuitBreakerRule.newBuilder(); CircuitBreakerProto.CircuitBreakerRule.Builder circuitBreakerRuleBuilder = CircuitBreakerProto.CircuitBreakerRule.newBuilder();
InputStream inputStream = PolarisCircuitBreakerMockServerTest.class.getClassLoader() InputStream inputStream = PolarisCircuitBreakerFeignIntegrationTest.class.getClassLoader()
.getResourceAsStream("circuitBreakerRule.json"); .getResourceAsStream("circuitBreakerRule.json");
String json = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)).lines() String json = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)).lines()
.collect(Collectors.joining("")); .collect(Collectors.joining(""));
@ -192,10 +202,51 @@ public class PolarisCircuitBreakerFeignIntegrationTest {
CircuitBreakerProto.CircuitBreaker circuitBreaker = CircuitBreakerProto.CircuitBreaker.newBuilder() CircuitBreakerProto.CircuitBreaker circuitBreaker = CircuitBreakerProto.CircuitBreaker.newBuilder()
.addRules(circuitBreakerRule).build(); .addRules(circuitBreakerRule).build();
namingServer.getNamingService().setCircuitBreaker(serviceKey, circuitBreaker); namingServer.getNamingService().setCircuitBreaker(serviceKey, circuitBreaker);
return namingServer;
}
@Bean
public CircuitBreakAPI circuitBreakAPI(NamingServer namingServer) {
com.tencent.polaris.api.config.Configuration configuration = TestUtils.configWithEnvAddress(); com.tencent.polaris.api.config.Configuration configuration = TestUtils.configWithEnvAddress();
return CircuitBreakAPIFactory.createCircuitBreakAPIByConfig(configuration); return CircuitBreakAPIFactory.createCircuitBreakAPIByConfig(configuration);
} }
@Bean
public ConsumerAPI consumerAPI(NamingServer namingServer) {
com.tencent.polaris.api.config.Configuration configuration = TestUtils.configWithEnvAddress();
return DiscoveryAPIFactory.createConsumerAPIByConfig(configuration);
}
@Bean
public SuccessCircuitBreakerReporter successCircuitBreakerReporter(RpcEnhancementReporterProperties properties,
CircuitBreakAPI circuitBreakAPI) {
return new SuccessCircuitBreakerReporter(properties, circuitBreakAPI);
}
@Bean
public ExceptionCircuitBreakerReporter exceptionCircuitBreakerReporter(RpcEnhancementReporterProperties properties,
CircuitBreakAPI circuitBreakAPI) {
return new ExceptionCircuitBreakerReporter(properties, circuitBreakAPI);
}
@Bean
public CircuitBreakerFactory polarisCircuitBreakerFactory(CircuitBreakAPI circuitBreakAPI, ConsumerAPI consumerAPI) {
PolarisCircuitBreakerFactory factory = new PolarisCircuitBreakerFactory(circuitBreakAPI, consumerAPI);
customizers.forEach(customizer -> customizer.customize(factory));
return factory;
}
@Bean
public PolarisCircuitBreakerNameResolver polarisCircuitBreakerNameResolver() {
return new PolarisCircuitBreakerNameResolver();
}
@Bean
@Primary
@ConditionalOnBean(CircuitBreakerFactory.class)
public PolarisFeignCircuitBreakerTargeter polarisFeignCircuitBreakerTargeter(CircuitBreakerFactory circuitBreakerFactory, PolarisCircuitBreakerNameResolver circuitBreakerNameResolver) {
return new PolarisFeignCircuitBreakerTargeter(circuitBreakerFactory, circuitBreakerNameResolver);
}
} }
public static class EchoServiceFallback implements EchoService { public static class EchoServiceFallback implements EchoService {
@ -231,4 +282,18 @@ public class PolarisCircuitBreakerFeignIntegrationTest {
} }
public static class PreDestroy implements DisposableBean {
private final NamingServer namingServer;
public PreDestroy(NamingServer namingServer) {
this.namingServer = namingServer;
}
@Override
public void destroy() throws Exception {
namingServer.terminate();
}
}
} }

@ -0,0 +1,125 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.polaris.circuitbreaker.feign;
import java.lang.reflect.Method;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.common.util.ReflectionUtils;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import feign.Target;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.RequestMapping;
import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST;
import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
/**
* @author sean yu
*/
@ExtendWith(MockitoExtension.class)
public class PolarisCircuitBreakerNameResolverTest {
private static MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils;
@BeforeAll
static void beforeAll() {
mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class);
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn("unit-test");
ApplicationContext applicationContext = mock(ApplicationContext.class);
RpcEnhancementReporterProperties reporterProperties = mock(RpcEnhancementReporterProperties.class);
doReturn(reporterProperties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
}
@AfterAll
static void afterAll() {
mockedApplicationContextAwareUtils.close();
}
@BeforeEach
void setUp() {
MetadataContext.LOCAL_NAMESPACE = NAMESPACE_TEST;
MetadataContext.LOCAL_SERVICE = SERVICE_PROVIDER;
}
@Test
public void test() {
Target target = mock(Target.class);
doReturn("test-svc").when(target).name();
Method method = ReflectionUtils.findMethod(PolarisCircuitBreakerNameResolverTest.class, "mockRequestMapping");
PolarisCircuitBreakerNameResolver resolver = new PolarisCircuitBreakerNameResolver();
String polarisCircuitBreakerName = resolver.resolveCircuitBreakerName("test", target, method);
assertThat(polarisCircuitBreakerName).isEqualTo("Test#test-svc");
}
@Test
public void test2() {
Target target = mock(Target.class);
doReturn("test-svc").when(target).name();
Method method = ReflectionUtils.findMethod(PolarisCircuitBreakerNameResolverTest.class, "mockRequestMapping2");
PolarisCircuitBreakerNameResolver resolver = new PolarisCircuitBreakerNameResolver();
String polarisCircuitBreakerName = resolver.resolveCircuitBreakerName("test", target, method);
assertThat(polarisCircuitBreakerName).isEqualTo("Test#test-svc#/");
}
@Test
public void test3() {
Target target = mock(Target.class);
doReturn("test-svc").when(target).name();
Method method = ReflectionUtils.findMethod(PolarisCircuitBreakerNameResolverTest.class, "mockRequestMapping3");
PolarisCircuitBreakerNameResolver resolver = new PolarisCircuitBreakerNameResolver();
String polarisCircuitBreakerName = resolver.resolveCircuitBreakerName("test", target, method);
assertThat(polarisCircuitBreakerName).isEqualTo("Test#test-svc#/");
}
@RequestMapping
public void mockRequestMapping() {
}
@RequestMapping(path = "/")
public void mockRequestMapping2() {
}
@RequestMapping("/")
public void mockRequestMapping3() {
}
}

@ -0,0 +1,89 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.polaris.circuitbreaker.feign;
import feign.Feign;
import feign.RequestLine;
import feign.Target;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory;
import org.springframework.cloud.openfeign.FeignClientFactoryBean;
import org.springframework.cloud.openfeign.FeignContext;
import org.springframework.cloud.openfeign.PolarisFeignCircuitBreakerTargeter;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
/**
* PolarisFeignCircuitBreakerTargeterTest.
*
* @author sean yu
*/
@ExtendWith(MockitoExtension.class)
public class PolarisFeignCircuitBreakerTargeterTest {
@Mock
CircuitBreakerFactory circuitBreakerFactory;
@Mock
PolarisCircuitBreakerNameResolver circuitBreakerNameResolver;
@Test
public void testTarget() {
PolarisFeignCircuitBreakerTargeter targeter = new PolarisFeignCircuitBreakerTargeter(circuitBreakerFactory, circuitBreakerNameResolver);
targeter.target(new FeignClientFactoryBean(), new Feign.Builder(), new FeignContext(), new Target.HardCodedTarget<>(TestApi.class, "/test"));
}
@Test
public void testTarget2() {
PolarisFeignCircuitBreakerTargeter targeter = new PolarisFeignCircuitBreakerTargeter(circuitBreakerFactory, circuitBreakerNameResolver);
FeignClientFactoryBean feignClientFactoryBean = mock(FeignClientFactoryBean.class);
doReturn(TestApi.class).when(feignClientFactoryBean).getFallback();
doReturn("test").when(feignClientFactoryBean).getName();
FeignContext feignClientFactory = mock(FeignContext.class);
doReturn(null).when(feignClientFactory).getInstance("test", TestApi.class);
assertThatThrownBy(() -> {
targeter.target(feignClientFactoryBean, new PolarisFeignCircuitBreaker.Builder(), feignClientFactory, new Target.HardCodedTarget<>(TestApi.class, "/test"));
}).isInstanceOf(IllegalStateException.class);
}
@Test
public void testTarget3() {
PolarisFeignCircuitBreakerTargeter targeter = new PolarisFeignCircuitBreakerTargeter(circuitBreakerFactory, circuitBreakerNameResolver);
FeignClientFactoryBean feignClientFactoryBean = mock(FeignClientFactoryBean.class);
doReturn(void.class).when(feignClientFactoryBean).getFallback();
doReturn(TestApi.class).when(feignClientFactoryBean).getFallbackFactory();
doReturn("test").when(feignClientFactoryBean).getName();
FeignContext feignClientFactory = mock(FeignContext.class);
doReturn(Object.class).when(feignClientFactory).getInstance("test", TestApi.class);
assertThatThrownBy(() -> {
targeter.target(feignClientFactoryBean, new PolarisFeignCircuitBreaker.Builder(), feignClientFactory, new Target.HardCodedTarget<>(TestApi.class, "/test"));
}).isInstanceOf(IllegalStateException.class);
}
interface TestApi {
@RequestLine("GET /test")
void test();
}
}

@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*/ */
package com.tencent.cloud.polaris.circuitbreaker; package com.tencent.cloud.polaris.circuitbreaker.gateway;
import java.io.BufferedReader; import java.io.BufferedReader;
@ -23,31 +23,39 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.util.JsonFormat; import com.google.protobuf.util.JsonFormat;
import com.tencent.cloud.polaris.circuitbreaker.gateway.PolarisCircuitBreakerFilterFactory; import com.tencent.cloud.polaris.circuitbreaker.PolarisCircuitBreakerFactory;
import com.tencent.cloud.polaris.circuitbreaker.reporter.ExceptionCircuitBreakerReporter;
import com.tencent.cloud.polaris.circuitbreaker.reporter.SuccessCircuitBreakerReporter;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.polaris.api.core.ConsumerAPI;
import com.tencent.polaris.api.pojo.ServiceKey; import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI; import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI;
import com.tencent.polaris.circuitbreak.factory.CircuitBreakAPIFactory; import com.tencent.polaris.circuitbreak.factory.CircuitBreakAPIFactory;
import com.tencent.polaris.client.util.Utils; import com.tencent.polaris.client.util.Utils;
import com.tencent.polaris.factory.api.DiscoveryAPIFactory;
import com.tencent.polaris.specification.api.v1.fault.tolerance.CircuitBreakerProto; import com.tencent.polaris.specification.api.v1.fault.tolerance.CircuitBreakerProto;
import com.tencent.polaris.test.common.TestUtils; import com.tencent.polaris.test.common.TestUtils;
import com.tencent.polaris.test.mock.discovery.NamingServer; import com.tencent.polaris.test.mock.discovery.NamingServer;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock; import org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory;
import org.springframework.cloud.client.circuitbreaker.Customizer;
import org.springframework.cloud.gateway.filter.factory.SpringCloudCircuitBreakerFilterFactory; import org.springframework.cloud.gateway.filter.factory.SpringCloudCircuitBreakerFilterFactory;
import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
@ -60,6 +68,8 @@ import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST;
import static com.tencent.polaris.test.common.Consts.SERVICE_CIRCUIT_BREAKER;
import static com.tencent.polaris.test.common.TestUtils.SERVER_ADDRESS_ENV; import static com.tencent.polaris.test.common.TestUtils.SERVER_ADDRESS_ENV;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -72,33 +82,24 @@ import static org.assertj.core.api.Assertions.assertThat;
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
properties = { properties = {
"spring.cloud.gateway.enabled=true", "spring.cloud.gateway.enabled=true",
"spring.cloud.polaris.namespace=default", "spring.cloud.polaris.namespace=" + NAMESPACE_TEST,
"spring.cloud.polaris.service=Test", "spring.cloud.polaris.service=" + SERVICE_CIRCUIT_BREAKER,
"spring.main.web-application-type=reactive", "spring.main.web-application-type=reactive"
"httpbin=http://localhost:${wiremock.server.port}",
"spring.cloud.polaris.address=grpc://127.0.0.1:10081"
}, },
classes = PolarisCircuitBreakerGatewayIntegrationTest.TestApplication.class classes = PolarisCircuitBreakerGatewayIntegrationTest.TestApplication.class
) )
@AutoConfigureWireMock(port = 0)
@ActiveProfiles("test-gateway") @ActiveProfiles("test-gateway")
@AutoConfigureWebTestClient(timeout = "1000000") @AutoConfigureWebTestClient(timeout = "1000000")
public class PolarisCircuitBreakerGatewayIntegrationTest { public class PolarisCircuitBreakerGatewayIntegrationTest {
private static final String TEST_SERVICE_NAME = "test-service-callee"; private static final String TEST_SERVICE_NAME = "test-service-callee";
private static NamingServer namingServer;
@Autowired @Autowired
private WebTestClient webClient; private WebTestClient webClient;
@Autowired @Autowired
private ApplicationContext applicationContext; private ApplicationContext applicationContext;
@AfterAll
public static void afterAll() {
if (null != namingServer) {
namingServer.terminate();
}
}
@Test @Test
public void fallback() throws Exception { public void fallback() throws Exception {
SpringCloudCircuitBreakerFilterFactory.Config config = new SpringCloudCircuitBreakerFilterFactory.Config(); SpringCloudCircuitBreakerFilterFactory.Config config = new SpringCloudCircuitBreakerFilterFactory.Config();
@ -160,19 +161,22 @@ public class PolarisCircuitBreakerGatewayIntegrationTest {
@EnableAutoConfiguration @EnableAutoConfiguration
public static class TestApplication { public static class TestApplication {
@Autowired(required = false)
private List<Customizer<PolarisCircuitBreakerFactory>> customizers = new ArrayList<>();
@Bean @Bean
public CircuitBreakAPI circuitBreakAPI() throws InvalidProtocolBufferException { public PreDestroy preDestroy(NamingServer namingServer) {
try { return new PreDestroy(namingServer);
namingServer = NamingServer.startNamingServer(10081); }
System.setProperty(SERVER_ADDRESS_ENV, String.format("127.0.0.1:%d", namingServer.getPort()));
}
catch (IOException e) {
} @Bean
ServiceKey serviceKey = new ServiceKey("default", TEST_SERVICE_NAME); public NamingServer namingServer() throws IOException {
NamingServer namingServer = NamingServer.startNamingServer(-1);
System.setProperty(SERVER_ADDRESS_ENV, String.format("127.0.0.1:%d", namingServer.getPort()));
ServiceKey serviceKey = new ServiceKey(NAMESPACE_TEST, TEST_SERVICE_NAME);
CircuitBreakerProto.CircuitBreakerRule.Builder circuitBreakerRuleBuilder = CircuitBreakerProto.CircuitBreakerRule.newBuilder(); CircuitBreakerProto.CircuitBreakerRule.Builder circuitBreakerRuleBuilder = CircuitBreakerProto.CircuitBreakerRule.newBuilder();
InputStream inputStream = PolarisCircuitBreakerMockServerTest.class.getClassLoader() InputStream inputStream = PolarisCircuitBreakerGatewayIntegrationTest.class.getClassLoader()
.getResourceAsStream("circuitBreakerRule.json"); .getResourceAsStream("circuitBreakerRule.json");
String json = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)).lines() String json = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)).lines()
.collect(Collectors.joining("")); .collect(Collectors.joining(""));
@ -181,10 +185,43 @@ public class PolarisCircuitBreakerGatewayIntegrationTest {
CircuitBreakerProto.CircuitBreaker circuitBreaker = CircuitBreakerProto.CircuitBreaker.newBuilder() CircuitBreakerProto.CircuitBreaker circuitBreaker = CircuitBreakerProto.CircuitBreaker.newBuilder()
.addRules(circuitBreakerRule).build(); .addRules(circuitBreakerRule).build();
namingServer.getNamingService().setCircuitBreaker(serviceKey, circuitBreaker); namingServer.getNamingService().setCircuitBreaker(serviceKey, circuitBreaker);
return namingServer;
}
@Bean
public CircuitBreakAPI circuitBreakAPI(NamingServer namingServer) throws IOException {
com.tencent.polaris.api.config.Configuration configuration = TestUtils.configWithEnvAddress(); com.tencent.polaris.api.config.Configuration configuration = TestUtils.configWithEnvAddress();
return CircuitBreakAPIFactory.createCircuitBreakAPIByConfig(configuration); return CircuitBreakAPIFactory.createCircuitBreakAPIByConfig(configuration);
} }
@Bean
public ConsumerAPI consumerAPI(NamingServer namingServer) {
com.tencent.polaris.api.config.Configuration configuration = TestUtils.configWithEnvAddress();
return DiscoveryAPIFactory.createConsumerAPIByConfig(configuration);
}
@Bean
@ConditionalOnMissingBean(SuccessCircuitBreakerReporter.class)
public SuccessCircuitBreakerReporter successCircuitBreakerReporter(RpcEnhancementReporterProperties properties,
CircuitBreakAPI circuitBreakAPI) {
return new SuccessCircuitBreakerReporter(properties, circuitBreakAPI);
}
@Bean
@ConditionalOnMissingBean(ExceptionCircuitBreakerReporter.class)
public ExceptionCircuitBreakerReporter exceptionCircuitBreakerReporter(RpcEnhancementReporterProperties properties,
CircuitBreakAPI circuitBreakAPI) {
return new ExceptionCircuitBreakerReporter(properties, circuitBreakAPI);
}
@Bean
@ConditionalOnMissingBean(CircuitBreakerFactory.class)
public CircuitBreakerFactory polarisCircuitBreakerFactory(CircuitBreakAPI circuitBreakAPI, ConsumerAPI consumerAPI) {
PolarisCircuitBreakerFactory factory = new PolarisCircuitBreakerFactory(circuitBreakAPI, consumerAPI);
customizers.forEach(customizer -> customizer.customize(factory));
return factory;
}
@Bean @Bean
public RouteLocator myRoutes(RouteLocatorBuilder builder) { public RouteLocator myRoutes(RouteLocatorBuilder builder) {
Set<String> codeSets = new HashSet<>(); Set<String> codeSets = new HashSet<>();
@ -228,4 +265,18 @@ public class PolarisCircuitBreakerGatewayIntegrationTest {
} }
public static class PreDestroy implements DisposableBean {
private final NamingServer namingServer;
public PreDestroy(NamingServer namingServer) {
this.namingServer = namingServer;
}
@Override
public void destroy() throws Exception {
namingServer.terminate();
}
}
} }

@ -95,7 +95,7 @@ public class ExceptionCircuitBreakerReporterTest {
@Test @Test
public void testType() { public void testType() {
assertThat(exceptionCircuitBreakerReporter.getType()).isEqualTo(EnhancedPluginType.EXCEPTION); assertThat(exceptionCircuitBreakerReporter.getType()).isEqualTo(EnhancedPluginType.Client.EXCEPTION);
} }
@Test @Test
@ -121,7 +121,7 @@ public class ExceptionCircuitBreakerReporterTest {
pluginContext.setRequest(request); pluginContext.setRequest(request);
pluginContext.setResponse(response); pluginContext.setResponse(response);
pluginContext.setServiceInstance(serviceInstance); pluginContext.setTargetServiceInstance(serviceInstance, null);
pluginContext.setThrowable(new RuntimeException()); pluginContext.setThrowable(new RuntimeException());
exceptionCircuitBreakerReporter.run(pluginContext); exceptionCircuitBreakerReporter.run(pluginContext);

@ -40,6 +40,7 @@ import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST; import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST;
@ -74,6 +75,12 @@ public class SuccessCircuitBreakerReporterTest {
mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class); mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class);
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString())) mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn("unit-test"); .thenReturn("unit-test");
ApplicationContext applicationContext = mock(ApplicationContext.class);
RpcEnhancementReporterProperties reporterProperties = mock(RpcEnhancementReporterProperties.class);
doReturn(reporterProperties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
} }
@AfterAll @AfterAll
@ -94,7 +101,7 @@ public class SuccessCircuitBreakerReporterTest {
@Test @Test
public void testType() { public void testType() {
assertThat(successCircuitBreakerReporter.getType()).isEqualTo(EnhancedPluginType.POST); assertThat(successCircuitBreakerReporter.getType()).isEqualTo(EnhancedPluginType.Client.POST);
} }
@Test @Test
@ -120,7 +127,7 @@ public class SuccessCircuitBreakerReporterTest {
pluginContext.setRequest(request); pluginContext.setRequest(request);
pluginContext.setResponse(response); pluginContext.setResponse(response);
pluginContext.setServiceInstance(serviceInstance); pluginContext.setTargetServiceInstance(serviceInstance, null);
successCircuitBreakerReporter.run(pluginContext); successCircuitBreakerReporter.run(pluginContext);
successCircuitBreakerReporter.getOrder(); successCircuitBreakerReporter.getOrder();

@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*/ */
package com.tencent.cloud.polaris.circuitbreaker; package com.tencent.cloud.polaris.circuitbreaker.resttemplate;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
@ -24,15 +24,18 @@ import java.io.InputStreamReader;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.util.JsonFormat; import com.google.protobuf.util.JsonFormat;
import com.tencent.cloud.polaris.circuitbreaker.PolarisCircuitBreakerFactory;
import com.tencent.cloud.polaris.circuitbreaker.config.PolarisCircuitBreakerFeignClientAutoConfiguration; import com.tencent.cloud.polaris.circuitbreaker.config.PolarisCircuitBreakerFeignClientAutoConfiguration;
import com.tencent.cloud.polaris.circuitbreaker.resttemplate.PolarisCircuitBreaker; import com.tencent.cloud.polaris.circuitbreaker.reporter.ExceptionCircuitBreakerReporter;
import com.tencent.cloud.polaris.circuitbreaker.resttemplate.PolarisCircuitBreakerFallback; import com.tencent.cloud.polaris.circuitbreaker.reporter.SuccessCircuitBreakerReporter;
import com.tencent.cloud.polaris.circuitbreaker.resttemplate.PolarisCircuitBreakerHttpResponse; import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.polaris.api.pojo.ServiceKey; import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI; import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI;
import com.tencent.polaris.circuitbreak.factory.CircuitBreakAPIFactory; import com.tencent.polaris.circuitbreak.factory.CircuitBreakAPIFactory;
@ -40,15 +43,17 @@ import com.tencent.polaris.client.util.Utils;
import com.tencent.polaris.specification.api.v1.fault.tolerance.CircuitBreakerProto; import com.tencent.polaris.specification.api.v1.fault.tolerance.CircuitBreakerProto;
import com.tencent.polaris.test.common.TestUtils; import com.tencent.polaris.test.common.TestUtils;
import com.tencent.polaris.test.mock.discovery.NamingServer; import com.tencent.polaris.test.mock.discovery.NamingServer;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration; import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory;
import org.springframework.cloud.client.circuitbreaker.Customizer;
import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
@ -57,7 +62,6 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.client.ExpectedCount; import org.springframework.test.web.client.ExpectedCount;
import org.springframework.test.web.client.MockRestServiceServer; import org.springframework.test.web.client.MockRestServiceServer;
@ -67,6 +71,7 @@ import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.DefaultUriBuilderFactory; import org.springframework.web.util.DefaultUriBuilderFactory;
import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST;
import static com.tencent.polaris.test.common.TestUtils.SERVER_ADDRESS_ENV; import static com.tencent.polaris.test.common.TestUtils.SERVER_ADDRESS_ENV;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.assertThatThrownBy;
@ -80,47 +85,44 @@ import static org.springframework.test.web.client.response.MockRestResponseCreat
*/ */
@ExtendWith(SpringExtension.class) @ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = RANDOM_PORT, @SpringBootTest(webEnvironment = RANDOM_PORT,
classes = PolarisCircuitBreakerIntegrationTest.TestConfig.class, classes = PolarisCircuitBreakerRestTemplateIntegrationTest.TestConfig.class,
properties = { properties = {
"spring.cloud.gateway.enabled=false", "spring.cloud.gateway.enabled=false",
"feign.circuitbreaker.enabled=true", "feign.circuitbreaker.enabled=true",
"spring.cloud.polaris.namespace=default", "spring.cloud.polaris.namespace=" + NAMESPACE_TEST,
"spring.cloud.polaris.service=test", "spring.cloud.polaris.service=test"
"spring.cloud.polaris.address=grpc://127.0.0.1:10081"
}) })
@DirtiesContext public class PolarisCircuitBreakerRestTemplateIntegrationTest {
public class PolarisCircuitBreakerIntegrationTest {
private static final String TEST_SERVICE_NAME = "test-service-callee"; private static final String TEST_SERVICE_NAME = "test-service-callee";
private static NamingServer namingServer;
@Autowired @Autowired
@Qualifier("defaultRestTemplate") @Qualifier("defaultRestTemplate")
private RestTemplate defaultRestTemplate; private RestTemplate defaultRestTemplate;
@Autowired @Autowired
@Qualifier("restTemplateFallbackFromPolaris") @Qualifier("restTemplateFallbackFromPolaris")
private RestTemplate restTemplateFallbackFromPolaris; private RestTemplate restTemplateFallbackFromPolaris;
@Autowired @Autowired
@Qualifier("restTemplateFallbackFromCode") @Qualifier("restTemplateFallbackFromCode")
private RestTemplate restTemplateFallbackFromCode; private RestTemplate restTemplateFallbackFromCode;
@Autowired @Autowired
@Qualifier("restTemplateFallbackFromCode2") @Qualifier("restTemplateFallbackFromCode2")
private RestTemplate restTemplateFallbackFromCode2; private RestTemplate restTemplateFallbackFromCode2;
@Autowired @Autowired
@Qualifier("restTemplateFallbackFromCode3") @Qualifier("restTemplateFallbackFromCode3")
private RestTemplate restTemplateFallbackFromCode3; private RestTemplate restTemplateFallbackFromCode3;
@Autowired @Autowired
@Qualifier("restTemplateFallbackFromCode4") @Qualifier("restTemplateFallbackFromCode4")
private RestTemplate restTemplateFallbackFromCode4; private RestTemplate restTemplateFallbackFromCode4;
@Autowired @Autowired
private ApplicationContext applicationContext; private ApplicationContext applicationContext;
@AfterAll
public static void afterAll() {
if (null != namingServer) {
namingServer.terminate();
}
}
@Test @Test
public void testRestTemplate() throws URISyntaxException { public void testRestTemplate() throws URISyntaxException {
@ -164,15 +166,22 @@ public class PolarisCircuitBreakerIntegrationTest {
@EnableFeignClients @EnableFeignClients
public static class TestConfig { public static class TestConfig {
@Autowired(required = false)
private List<Customizer<PolarisCircuitBreakerFactory>> customizers = new ArrayList<>();
{
PolarisSDKContextManager.innerDestroy();
}
@Bean @Bean
@PolarisCircuitBreaker(fallback = "fallback") @com.tencent.cloud.polaris.circuitbreaker.resttemplate.PolarisCircuitBreaker(fallback = "fallback")
public RestTemplate defaultRestTemplate() { public RestTemplate defaultRestTemplate() {
return new RestTemplate(); return new RestTemplate();
} }
@Bean @Bean
@LoadBalanced @LoadBalanced
@PolarisCircuitBreaker @com.tencent.cloud.polaris.circuitbreaker.resttemplate.PolarisCircuitBreaker
public RestTemplate restTemplateFallbackFromPolaris() { public RestTemplate restTemplateFallbackFromPolaris() {
DefaultUriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory("http://" + TEST_SERVICE_NAME); DefaultUriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory("http://" + TEST_SERVICE_NAME);
RestTemplate restTemplate = new RestTemplate(); RestTemplate restTemplate = new RestTemplate();
@ -182,7 +191,7 @@ public class PolarisCircuitBreakerIntegrationTest {
@Bean @Bean
@LoadBalanced @LoadBalanced
@PolarisCircuitBreaker(fallbackClass = CustomPolarisCircuitBreakerFallback.class) @com.tencent.cloud.polaris.circuitbreaker.resttemplate.PolarisCircuitBreaker(fallbackClass = CustomPolarisCircuitBreakerFallback.class)
public RestTemplate restTemplateFallbackFromCode() { public RestTemplate restTemplateFallbackFromCode() {
DefaultUriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory("http://" + TEST_SERVICE_NAME); DefaultUriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory("http://" + TEST_SERVICE_NAME);
RestTemplate restTemplate = new RestTemplate(); RestTemplate restTemplate = new RestTemplate();
@ -192,7 +201,7 @@ public class PolarisCircuitBreakerIntegrationTest {
@Bean @Bean
@LoadBalanced @LoadBalanced
@PolarisCircuitBreaker(fallbackClass = CustomPolarisCircuitBreakerFallback2.class) @com.tencent.cloud.polaris.circuitbreaker.resttemplate.PolarisCircuitBreaker(fallbackClass = CustomPolarisCircuitBreakerFallback2.class)
public RestTemplate restTemplateFallbackFromCode2() { public RestTemplate restTemplateFallbackFromCode2() {
DefaultUriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory("http://" + TEST_SERVICE_NAME); DefaultUriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory("http://" + TEST_SERVICE_NAME);
RestTemplate restTemplate = new RestTemplate(); RestTemplate restTemplate = new RestTemplate();
@ -202,7 +211,7 @@ public class PolarisCircuitBreakerIntegrationTest {
@Bean @Bean
@LoadBalanced @LoadBalanced
@PolarisCircuitBreaker(fallbackClass = CustomPolarisCircuitBreakerFallback3.class) @com.tencent.cloud.polaris.circuitbreaker.resttemplate.PolarisCircuitBreaker(fallbackClass = CustomPolarisCircuitBreakerFallback3.class)
public RestTemplate restTemplateFallbackFromCode3() { public RestTemplate restTemplateFallbackFromCode3() {
DefaultUriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory("http://" + TEST_SERVICE_NAME); DefaultUriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory("http://" + TEST_SERVICE_NAME);
RestTemplate restTemplate = new RestTemplate(); RestTemplate restTemplate = new RestTemplate();
@ -236,18 +245,12 @@ public class PolarisCircuitBreakerIntegrationTest {
} }
@Bean @Bean
public CircuitBreakAPI circuitBreakAPI() throws InvalidProtocolBufferException { public NamingServer namingServer() throws IOException {
try { NamingServer namingServer = NamingServer.startNamingServer(-1);
namingServer = NamingServer.startNamingServer(10081); System.setProperty(SERVER_ADDRESS_ENV, String.format("127.0.0.1:%d", namingServer.getPort()));
System.setProperty(SERVER_ADDRESS_ENV, String.format("127.0.0.1:%d", namingServer.getPort())); ServiceKey serviceKey = new ServiceKey(NAMESPACE_TEST, TEST_SERVICE_NAME);
}
catch (IOException e) {
}
ServiceKey serviceKey = new ServiceKey("default", TEST_SERVICE_NAME);
CircuitBreakerProto.CircuitBreakerRule.Builder circuitBreakerRuleBuilder = CircuitBreakerProto.CircuitBreakerRule.newBuilder(); CircuitBreakerProto.CircuitBreakerRule.Builder circuitBreakerRuleBuilder = CircuitBreakerProto.CircuitBreakerRule.newBuilder();
InputStream inputStream = PolarisCircuitBreakerMockServerTest.class.getClassLoader() InputStream inputStream = PolarisCircuitBreakerRestTemplateIntegrationTest.class.getClassLoader()
.getResourceAsStream("circuitBreakerRule.json"); .getResourceAsStream("circuitBreakerRule.json");
String json = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)).lines() String json = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)).lines()
.collect(Collectors.joining("")); .collect(Collectors.joining(""));
@ -256,10 +259,41 @@ public class PolarisCircuitBreakerIntegrationTest {
CircuitBreakerProto.CircuitBreaker circuitBreaker = CircuitBreakerProto.CircuitBreaker.newBuilder() CircuitBreakerProto.CircuitBreaker circuitBreaker = CircuitBreakerProto.CircuitBreaker.newBuilder()
.addRules(circuitBreakerRule).build(); .addRules(circuitBreakerRule).build();
namingServer.getNamingService().setCircuitBreaker(serviceKey, circuitBreaker); namingServer.getNamingService().setCircuitBreaker(serviceKey, circuitBreaker);
return namingServer;
}
@Bean
public PreDestroy preDestroy(NamingServer namingServer) {
return new PreDestroy(namingServer);
}
@Bean
public CircuitBreakAPI circuitBreakAPI(NamingServer namingServer) {
com.tencent.polaris.api.config.Configuration configuration = TestUtils.configWithEnvAddress(); com.tencent.polaris.api.config.Configuration configuration = TestUtils.configWithEnvAddress();
return CircuitBreakAPIFactory.createCircuitBreakAPIByConfig(configuration); return CircuitBreakAPIFactory.createCircuitBreakAPIByConfig(configuration);
} }
@Bean
public SuccessCircuitBreakerReporter successCircuitBreakerReporter(RpcEnhancementReporterProperties properties,
CircuitBreakAPI circuitBreakAPI) {
return new SuccessCircuitBreakerReporter(properties, circuitBreakAPI);
}
@Bean
public ExceptionCircuitBreakerReporter exceptionCircuitBreakerReporter(RpcEnhancementReporterProperties properties,
CircuitBreakAPI circuitBreakAPI) {
return new ExceptionCircuitBreakerReporter(properties, circuitBreakAPI);
}
@Bean
public CircuitBreakerFactory polarisCircuitBreakerFactory(CircuitBreakAPI circuitBreakAPI,
PolarisSDKContextManager polarisSDKContextManager) {
PolarisCircuitBreakerFactory factory = new PolarisCircuitBreakerFactory(
circuitBreakAPI, polarisSDKContextManager.getConsumerAPI());
customizers.forEach(customizer -> customizer.customize(factory));
return factory;
}
@RestController @RestController
@RequestMapping("/example/service/b") @RequestMapping("/example/service/b")
public class ServiceBController { public class ServiceBController {
@ -309,4 +343,18 @@ public class PolarisCircuitBreakerIntegrationTest {
} }
} }
public static class PreDestroy implements DisposableBean {
private final NamingServer namingServer;
public PreDestroy(NamingServer namingServer) {
this.namingServer = namingServer;
}
@Override
public void destroy() throws Exception {
namingServer.terminate();
}
}
} }

@ -35,6 +35,7 @@ import org.mockito.Mockito;
import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST; import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST;
import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER; import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.anyString;
public class PolarisCircuitBreakerUtilsTests { public class PolarisCircuitBreakerUtilsTests {
@ -68,4 +69,11 @@ public class PolarisCircuitBreakerUtilsTests {
PolarisCircuitBreakerUtils.reportStatus(consumerAPI, conf, new CallAbortedException("mock", new CircuitBreakerStatus.FallbackInfo(0, new HashMap<>(), ""))); PolarisCircuitBreakerUtils.reportStatus(consumerAPI, conf, new CallAbortedException("mock", new CircuitBreakerStatus.FallbackInfo(0, new HashMap<>(), "")));
} }
@Test
public void testResolveCircuitBreakerId() {
assertThat(PolarisCircuitBreakerUtils.resolveCircuitBreakerId("test_svc")).isEqualTo(new String[]{NAMESPACE_TEST, "test_svc", ""});
assertThat(PolarisCircuitBreakerUtils.resolveCircuitBreakerId("test_svc#test_path")).isEqualTo(new String[]{NAMESPACE_TEST, "test_svc", "test_path"});
assertThat(PolarisCircuitBreakerUtils.resolveCircuitBreakerId("test_ns#test_svc#test_path")).isEqualTo(new String[]{"test_ns", "test_svc", "test_path"});
}
} }

@ -13,7 +13,7 @@ spring:
feature-env: feature-env:
enabled: true enabled: true
polaris: polaris:
address: grpc://127.0.0.1:8091 address: grpc://127.0.0.1:10081
namespace: default namespace: default
enabled: true enabled: true
gateway: gateway:

@ -20,6 +20,7 @@ package com.tencent.cloud.polaris.config;
import com.tencent.cloud.polaris.config.adapter.AffectedConfigurationPropertiesRebinder; import com.tencent.cloud.polaris.config.adapter.AffectedConfigurationPropertiesRebinder;
import com.tencent.cloud.polaris.config.adapter.PolarisConfigPropertyRefresher; import com.tencent.cloud.polaris.config.adapter.PolarisConfigPropertyRefresher;
import com.tencent.cloud.polaris.config.adapter.PolarisConfigRefreshScopeAnnotationDetector;
import com.tencent.cloud.polaris.config.adapter.PolarisPropertySourceManager; import com.tencent.cloud.polaris.config.adapter.PolarisPropertySourceManager;
import com.tencent.cloud.polaris.config.adapter.PolarisRefreshAffectedContextRefresher; import com.tencent.cloud.polaris.config.adapter.PolarisRefreshAffectedContextRefresher;
import com.tencent.cloud.polaris.config.adapter.PolarisRefreshEntireContextRefresher; import com.tencent.cloud.polaris.config.adapter.PolarisRefreshEntireContextRefresher;
@ -27,6 +28,8 @@ import com.tencent.cloud.polaris.config.annotation.PolarisConfigAnnotationProces
import com.tencent.cloud.polaris.config.condition.ConditionalOnReflectRefreshType; import com.tencent.cloud.polaris.config.condition.ConditionalOnReflectRefreshType;
import com.tencent.cloud.polaris.config.config.PolarisConfigProperties; import com.tencent.cloud.polaris.config.config.PolarisConfigProperties;
import com.tencent.cloud.polaris.config.listener.PolarisConfigChangeEventListener; import com.tencent.cloud.polaris.config.listener.PolarisConfigChangeEventListener;
import com.tencent.cloud.polaris.config.listener.PolarisConfigRefreshOptimizationListener;
import com.tencent.cloud.polaris.config.logger.PolarisConfigLoggerApplicationListener;
import com.tencent.cloud.polaris.config.spring.annotation.SpringValueProcessor; import com.tencent.cloud.polaris.config.spring.annotation.SpringValueProcessor;
import com.tencent.cloud.polaris.config.spring.property.PlaceholderHelper; import com.tencent.cloud.polaris.config.spring.property.PlaceholderHelper;
import com.tencent.cloud.polaris.config.spring.property.SpringValueRegistry; import com.tencent.cloud.polaris.config.spring.property.SpringValueRegistry;
@ -60,6 +63,12 @@ public class PolarisConfigAutoConfiguration {
return new PolarisConfigChangeEventListener(); return new PolarisConfigChangeEventListener();
} }
@Bean
public PolarisConfigLoggerApplicationListener polarisConfigLoggerApplicationListener() {
return new PolarisConfigLoggerApplicationListener();
}
@Bean @Bean
@Primary @Primary
@ConditionalOnReflectRefreshType @ConditionalOnReflectRefreshType
@ -102,5 +111,15 @@ public class PolarisConfigAutoConfiguration {
return new PolarisRefreshAffectedContextRefresher(polarisConfigProperties, polarisPropertySourceManager, return new PolarisRefreshAffectedContextRefresher(polarisConfigProperties, polarisPropertySourceManager,
springValueRegistry, placeholderHelper); springValueRegistry, placeholderHelper);
} }
@Bean
public PolarisConfigRefreshScopeAnnotationDetector polarisConfigRefreshScopeAnnotationDetector() {
return new PolarisConfigRefreshScopeAnnotationDetector();
}
@Bean
public PolarisConfigRefreshOptimizationListener polarisConfigRefreshOptimizationListener() {
return new PolarisConfigRefreshOptimizationListener();
}
} }
} }

@ -23,9 +23,9 @@ import com.tencent.cloud.polaris.config.adapter.PolarisConfigFileLocator;
import com.tencent.cloud.polaris.config.adapter.PolarisPropertySourceManager; import com.tencent.cloud.polaris.config.adapter.PolarisPropertySourceManager;
import com.tencent.cloud.polaris.config.condition.ConditionalOnReflectRefreshType; import com.tencent.cloud.polaris.config.condition.ConditionalOnReflectRefreshType;
import com.tencent.cloud.polaris.config.config.PolarisConfigProperties; import com.tencent.cloud.polaris.config.config.PolarisConfigProperties;
import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration; import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration;
import com.tencent.cloud.polaris.context.config.PolarisContextProperties; import com.tencent.cloud.polaris.context.config.PolarisContextProperties;
import com.tencent.polaris.client.api.SDKContext;
import com.tencent.polaris.configuration.api.core.ConfigFileService; import com.tencent.polaris.configuration.api.core.ConfigFileService;
import com.tencent.polaris.configuration.factory.ConfigFileServiceFactory; import com.tencent.polaris.configuration.factory.ConfigFileServiceFactory;
@ -60,8 +60,8 @@ public class PolarisConfigBootstrapAutoConfiguration {
@Bean @Bean
@ConditionalOnConnectRemoteServerEnabled @ConditionalOnConnectRemoteServerEnabled
public ConfigFileService configFileService(SDKContext sdkContext) { public ConfigFileService configFileService(PolarisSDKContextManager polarisSDKContextManager) {
return ConfigFileServiceFactory.createConfigFileService(sdkContext); return ConfigFileServiceFactory.createConfigFileService(polarisSDKContextManager.getSDKContext());
} }
@Bean @Bean

@ -0,0 +1,26 @@
/*
* Copyright (c) 2023 www.tencent.com.
* All Rights Reserved.
* This program is the confidential and proprietary information of
* www.tencent.com ("Confidential Information"). You shall not disclose such
* Confidential Information and shall use it only in accordance with
* the terms of the license agreement you entered into with www.tencent.com.
*
*/
package com.tencent.cloud.polaris.config.adapter;
import com.tencent.polaris.configuration.api.core.ConfigFileService;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.Environment;
/**
* @Date Jul 23, 2023 2:57:49 PM
* @author juanyinyang
*/
public interface PolarisConfigCustomExtensionLayer {
void execute(String namespace, Environment environment, CompositePropertySource compositePropertySource, PolarisPropertySourceManager polarisPropertySourceManager, ConfigFileService configFileService);
}

@ -20,9 +20,11 @@ package com.tencent.cloud.polaris.config.adapter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.ServiceLoader;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import com.tencent.cloud.polaris.config.config.ConfigFileGroup; import com.tencent.cloud.polaris.config.config.ConfigFileGroup;
@ -68,12 +70,20 @@ public class PolarisConfigFileLocator implements PropertySourceLocator {
private final PolarisPropertySourceManager polarisPropertySourceManager; private final PolarisPropertySourceManager polarisPropertySourceManager;
private final Environment environment; private final Environment environment;
// 此类给一些客户定制化逻辑做一些特殊业务分组文件的配置处理
private PolarisConfigCustomExtensionLayer polarisConfigCustomExtensionLayer;
{
ServiceLoader<PolarisConfigCustomExtensionLayer> polarisConfigCustomExtensionLayerLoader = ServiceLoader.load(PolarisConfigCustomExtensionLayer.class);
Iterator<PolarisConfigCustomExtensionLayer> polarisConfigCustomExtensionLayerIterator = polarisConfigCustomExtensionLayerLoader.iterator();
// 一般就一个实现类,如果有多个,那么加载的是最后一个
while (polarisConfigCustomExtensionLayerIterator.hasNext()) {
polarisConfigCustomExtensionLayer = polarisConfigCustomExtensionLayerIterator.next();
LOGGER.info("[SCT Config] PolarisConfigFileLocator init polarisConfigCustomExtensionLayer:{}", polarisConfigCustomExtensionLayer);
}
}
public PolarisConfigFileLocator(PolarisConfigProperties polarisConfigProperties, public PolarisConfigFileLocator(PolarisConfigProperties polarisConfigProperties, PolarisContextProperties polarisContextProperties, ConfigFileService configFileService, PolarisPropertySourceManager polarisPropertySourceManager, Environment environment) {
PolarisContextProperties polarisContextProperties,
ConfigFileService configFileService,
PolarisPropertySourceManager polarisPropertySourceManager,
Environment environment) {
this.polarisConfigProperties = polarisConfigProperties; this.polarisConfigProperties = polarisConfigProperties;
this.polarisContextProperties = polarisContextProperties; this.polarisContextProperties = polarisContextProperties;
this.configFileService = configFileService; this.configFileService = configFileService;
@ -83,9 +93,10 @@ public class PolarisConfigFileLocator implements PropertySourceLocator {
@Override @Override
public PropertySource<?> locate(Environment environment) { public PropertySource<?> locate(Environment environment) {
CompositePropertySource compositePropertySource = new CompositePropertySource( CompositePropertySource compositePropertySource = new CompositePropertySource(POLARIS_CONFIG_PROPERTY_SOURCE_NAME);
POLARIS_CONFIG_PROPERTY_SOURCE_NAME);
// load custom config extension files
initCustomPolarisConfigExtensionFiles(compositePropertySource);
// load spring boot default config files // load spring boot default config files
initInternalConfigFiles(compositePropertySource); initInternalConfigFiles(compositePropertySource);
@ -99,12 +110,21 @@ public class PolarisConfigFileLocator implements PropertySourceLocator {
return compositePropertySource; return compositePropertySource;
} }
private void initCustomPolarisConfigExtensionFiles(CompositePropertySource compositePropertySource) {
if (polarisConfigCustomExtensionLayer == null) {
LOGGER.info("[SCT Config] PolarisAdaptorTsfConfigExtensionLayer is not init, ignore the following execution steps");
return;
}
String namespace = polarisContextProperties.getNamespace();
polarisConfigCustomExtensionLayer.execute(namespace, environment, compositePropertySource, polarisPropertySourceManager, configFileService);
LOGGER.info("[SCT Config] InitCustomPolarisConfigExtensionFiles finished, namespace:{}", namespace);
}
private void initInternalConfigFiles(CompositePropertySource compositePropertySource) { private void initInternalConfigFiles(CompositePropertySource compositePropertySource) {
List<ConfigFileMetadata> internalConfigFiles = getInternalConfigFiles(); List<ConfigFileMetadata> internalConfigFiles = getInternalConfigFiles();
for (ConfigFileMetadata configFile : internalConfigFiles) { for (ConfigFileMetadata configFile : internalConfigFiles) {
PolarisPropertySource polarisPropertySource = loadPolarisPropertySource( PolarisPropertySource polarisPropertySource = loadPolarisPropertySource(configFile.getNamespace(), configFile.getFileGroup(), configFile.getFileName());
configFile.getNamespace(), configFile.getFileGroup(), configFile.getFileName());
compositePropertySource.addPropertySource(polarisPropertySource); compositePropertySource.addPropertySource(polarisPropertySource);
@ -141,36 +161,37 @@ public class PolarisConfigFileLocator implements PropertySourceLocator {
return internalConfigFiles; return internalConfigFiles;
} }
private void buildInternalApplicationConfigFiles( private void buildInternalApplicationConfigFiles(List<ConfigFileMetadata> internalConfigFiles, String namespace, String serviceName, List<String> profileList) {
List<ConfigFileMetadata> internalConfigFiles, String namespace, String serviceName, List<String> profileList) {
for (String profile : profileList) { for (String profile : profileList) {
if (!StringUtils.hasText(profile)) { if (!StringUtils.hasText(profile)) {
continue; continue;
} }
internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "application-" + profile + ".properties")); internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "application-" + profile + ".properties"));
internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "application-" + profile + ".yml")); internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "application-" + profile + ".yml"));
internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "application-" + profile + ".yaml"));
} }
// build default config properties files. // build default config properties files.
internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "application.properties")); internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "application.properties"));
internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "application.yml")); internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "application.yml"));
internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "application.yaml"));
} }
private void buildInternalBootstrapConfigFiles( private void buildInternalBootstrapConfigFiles(List<ConfigFileMetadata> internalConfigFiles, String namespace, String serviceName, List<String> profileList) {
List<ConfigFileMetadata> internalConfigFiles, String namespace, String serviceName, List<String> profileList) {
for (String profile : profileList) { for (String profile : profileList) {
if (!StringUtils.hasText(profile)) { if (!StringUtils.hasText(profile)) {
continue; continue;
} }
internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "bootstrap-" + profile + ".properties")); internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "bootstrap-" + profile + ".properties"));
internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "bootstrap-" + profile + ".yml")); internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "bootstrap-" + profile + ".yml"));
internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "bootstrap-" + profile + ".yaml"));
} }
// build default config properties files. // build default config properties files.
internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "bootstrap.properties")); internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "bootstrap.properties"));
internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "bootstrap.yml")); internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "bootstrap.yml"));
internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "bootstrap.yaml"));
} }
private void initCustomPolarisConfigFiles(CompositePropertySource compositePropertySource, private void initCustomPolarisConfigFiles(CompositePropertySource compositePropertySource, List<ConfigFileGroup> configFileGroups) {
List<ConfigFileGroup> configFileGroups) {
String namespace = polarisContextProperties.getNamespace(); String namespace = polarisContextProperties.getNamespace();
for (ConfigFileGroup configFileGroup : configFileGroups) { for (ConfigFileGroup configFileGroup : configFileGroups) {
@ -192,14 +213,12 @@ public class PolarisConfigFileLocator implements PropertySourceLocator {
polarisPropertySourceManager.addPropertySource(polarisPropertySource); polarisPropertySourceManager.addPropertySource(polarisPropertySource);
LOGGER.info("[SCT Config] Load and inject polaris config file success." LOGGER.info("[SCT Config] Load and inject polaris config file success. namespace = {}, group = {}, fileName = {}", namespace, group, fileName);
+ " namespace = {}, group = {}, fileName = {}", namespace, group, fileName);
} }
} }
} }
private PolarisPropertySource loadPolarisPropertySource(String namespace, private PolarisPropertySource loadPolarisPropertySource(String namespace, String group, String fileName) {
String group, String fileName) {
ConfigKVFile configKVFile; ConfigKVFile configKVFile;
// unknown extension is resolved as properties file // unknown extension is resolved as properties file
if (ConfigFileFormat.isPropertyFile(fileName) || ConfigFileFormat.isUnknownFile(fileName)) { if (ConfigFileFormat.isPropertyFile(fileName) || ConfigFileFormat.isUnknownFile(fileName)) {
@ -209,11 +228,9 @@ public class PolarisConfigFileLocator implements PropertySourceLocator {
configKVFile = configFileService.getConfigYamlFile(namespace, group, fileName); configKVFile = configFileService.getConfigYamlFile(namespace, group, fileName);
} }
else { else {
LOGGER.warn("[SCT Config] Unsupported config file. namespace = {}, group = {}, fileName = {}", LOGGER.warn("[SCT Config] Unsupported config file. namespace = {}, group = {}, fileName = {}", namespace, group, fileName);
namespace, group, fileName);
throw new IllegalStateException("Only configuration files in the format of properties / yaml / yaml" throw new IllegalStateException("Only configuration files in the format of properties / yaml / yaml" + " can be injected into the spring context");
+ " can be injected into the spring context");
} }
Map<String, Object> map = new ConcurrentHashMap<>(); Map<String, Object> map = new ConcurrentHashMap<>();

@ -23,6 +23,7 @@ import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import com.tencent.cloud.polaris.config.config.PolarisConfigProperties; import com.tencent.cloud.polaris.config.config.PolarisConfigProperties;
import com.tencent.cloud.polaris.config.logger.PolarisConfigLoggerContext;
import com.tencent.polaris.configuration.api.core.ConfigKVFileChangeListener; import com.tencent.polaris.configuration.api.core.ConfigKVFileChangeListener;
import com.tencent.polaris.configuration.api.core.ConfigPropertyChangeInfo; import com.tencent.polaris.configuration.api.core.ConfigPropertyChangeInfo;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -33,6 +34,8 @@ import org.springframework.context.ApplicationListener;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
/** /**
* 1. Listen to the Polaris server configuration publishing event 2. Write the changed * 1. Listen to the Polaris server configuration publishing event 2. Write the changed
* configuration content to propertySource 3. Refresh the context through contextRefresher * configuration content to propertySource 3. Refresh the context through contextRefresher
@ -96,6 +99,18 @@ public abstract class PolarisConfigPropertyAutoRefresher
LOGGER.info("[SCT Config] changed property = {}", configPropertyChangeInfo); LOGGER.info("[SCT Config] changed property = {}", configPropertyChangeInfo);
// 新增动态改变日志级别的能力
try {
if (changedKey.startsWith("logging.level") && changedKey.length() >= 14) {
String loggerName = changedKey.substring(14);
String newValue = configPropertyChangeInfo.getNewValue();
LOGGER.info("[SCT Config] set logging.level loggerName:{}, newValue:{}", loggerName, newValue);
PolarisConfigLoggerContext.setLevel(loggerName, newValue);
}
}
catch (Exception e) {
LOGGER.error("[SCT Config] set logging.level exception,", e);
}
switch (configPropertyChangeInfo.getChangeType()) { switch (configPropertyChangeInfo.getChangeType()) {
case MODIFIED: case MODIFIED:
case ADDED: case ADDED:

@ -0,0 +1,94 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.polaris.config.adapter;
import java.lang.annotation.Annotation;
import java.util.concurrent.atomic.AtomicBoolean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;
import org.springframework.core.PriorityOrdered;
import org.springframework.lang.NonNull;
/**
* Mainly used to detect whether the annotation class {@link org.springframework.cloud.context.config.annotation.RefreshScope}
* exists, and whether the user has configured beans using this annotation in their business system.
* If the annotation {@code @RefreshScope} exists and is used, the auto-optimization will be triggered
* in listener {@link com.tencent.cloud.polaris.config.listener.PolarisConfigRefreshOptimizationListener}.
*
* <p>This bean will only be created and initialized when the config refresh type is {@code RefreshType.REFLECT}.
*
* @author jarvisxiong
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public class PolarisConfigRefreshScopeAnnotationDetector implements BeanPostProcessor, InitializingBean, PriorityOrdered {
private final AtomicBoolean isRefreshScopeAnnotationUsed = new AtomicBoolean(false);
private Class refreshScopeAnnotationClass;
private String annotatedRefreshScopeBeanName;
@Override
public Object postProcessBeforeInitialization(@NonNull Object bean, @NonNull String beanName)
throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(@NonNull Object bean, @NonNull String beanName)
throws BeansException {
if (isRefreshScopeAnnotationUsed() || refreshScopeAnnotationClass == null) {
return bean;
}
Annotation[] refreshScopeAnnotations = bean.getClass().getAnnotationsByType(refreshScopeAnnotationClass);
if (refreshScopeAnnotations.length > 0) {
if (isRefreshScopeAnnotationUsed.compareAndSet(false, true)) {
annotatedRefreshScopeBeanName = beanName;
}
}
return bean;
}
@Override
public void afterPropertiesSet() {
try {
refreshScopeAnnotationClass = Class.forName(
"org.springframework.cloud.context.config.annotation.RefreshScope",
false,
getClass().getClassLoader());
}
catch (ClassNotFoundException ignored) {
}
}
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE;
}
public boolean isRefreshScopeAnnotationUsed() {
return isRefreshScopeAnnotationUsed.get();
}
public String getAnnotatedRefreshScopeBeanName() {
return annotatedRefreshScopeBeanName;
}
}

@ -15,15 +15,16 @@
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
* *
*/ */
package com.tencent.cloud.polaris.config.config; package com.tencent.cloud.polaris.config.config;
import java.util.List; import java.util.List;
import com.tencent.cloud.polaris.config.enums.RefreshType; import com.tencent.cloud.polaris.config.enums.RefreshType;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
/** /**
* polaris config module bootstrap configs. * polaris config module bootstrap configs.
* *
@ -31,26 +32,29 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
*/ */
@ConfigurationProperties("spring.cloud.polaris.config") @ConfigurationProperties("spring.cloud.polaris.config")
public class PolarisConfigProperties { public class PolarisConfigProperties {
/** /**
* Whether to open the configuration center. * Whether to open the configuration center.
*/ */
@Value("${spring.cloud.polaris.config.enabled:#{'true'}}")
private boolean enabled = true; private boolean enabled = true;
/** /**
* Configuration center service address list. * Configuration center service address list.
*/ */
@Value("${spring.cloud.polaris.config.address:}")
private String address; private String address;
/** /**
* Polaris config grpc port. * Polaris config grpc port.
*/ */
@Value("${spring.cloud.polaris.config.port:#{'8093'}}")
private int port = 8093; private int port = 8093;
/** /**
* Whether to automatically update to the spring context when the configuration file. * Whether to automatically update to the spring context when the configuration file.
* is updated * is updated
*/ */
@Value("${spring.cloud.polaris.config.autoRefresh:#{'true'}}")
private boolean autoRefresh = true; private boolean autoRefresh = true;
private boolean shutdownIfConnectToConfigServerFailed = true; private boolean shutdownIfConnectToConfigServerFailed = true;

@ -0,0 +1,132 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
*/
package com.tencent.cloud.polaris.config.listener;
import java.util.Collections;
import com.tencent.cloud.polaris.config.adapter.PolarisConfigRefreshScopeAnnotationDetector;
import com.tencent.cloud.polaris.config.adapter.PolarisPropertySourceManager;
import com.tencent.cloud.polaris.config.adapter.PolarisRefreshEntireContextRefresher;
import com.tencent.cloud.polaris.config.config.PolarisConfigProperties;
import com.tencent.cloud.polaris.config.enums.RefreshType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.cloud.context.refresh.ContextRefresher;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.lang.NonNull;
import static com.tencent.cloud.polaris.config.condition.ReflectRefreshTypeCondition.POLARIS_CONFIG_REFRESH_TYPE;
/**
* When {@link com.tencent.cloud.polaris.config.adapter.PolarisConfigRefreshScopeAnnotationDetector} detects that
* the annotation {@code @RefreshScope} exists and is used, but the config refresh type
* {@code spring.cloud.polaris.config.refresh-type} is still {@code RefreshType.REFLECT}, then the framework will
* automatically switch the config refresh type to {@code RefreshType.REFRESH_CONTEXT}.
*
* <p>The purpose of this optimization is to omit additional configuration, and facilitate for users to use the
* dynamic configuration refresh strategy of Spring Cloud Context.</p>
*
* @author jarvisxiong
*/
public class PolarisConfigRefreshOptimizationListener implements ApplicationListener<ContextRefreshedEvent> {
private static final Logger LOGGER = LoggerFactory.getLogger(PolarisConfigRefreshOptimizationListener.class);
private static final String CONFIG_REFRESH_TYPE_PROPERTY = "configRefreshTypeProperty";
private static final String REFLECT_REBINDER_BEAN_NAME = "affectedConfigurationPropertiesRebinder";
private static final String REFLECT_REFRESHER_BEAN_NAME = "polarisReflectPropertySourceAutoRefresher";
private static final String REFRESH_CONTEXT_REFRESHER_BEAN_NAME = "polarisRefreshContextPropertySourceAutoRefresher";
@Override
public void onApplicationEvent(@NonNull ContextRefreshedEvent event) {
ConfigurableApplicationContext applicationContext = (ConfigurableApplicationContext) event.getApplicationContext();
PolarisConfigRefreshScopeAnnotationDetector detector = applicationContext.getBean(PolarisConfigRefreshScopeAnnotationDetector.class);
boolean isRefreshScopeAnnotationUsed = detector.isRefreshScopeAnnotationUsed();
String annotatedRefreshScopeBeanName = detector.getAnnotatedRefreshScopeBeanName();
// using System.setProperty to set spring.cloud.polaris.config.refresh-type
String value = System.getProperty("spring.cloud.polaris.config.refresh-type");
boolean isSystemSetRefreshType = RefreshType.REFRESH_CONTEXT.toString().equalsIgnoreCase(value);
// a bean is using @RefreshScope, but the config refresh type is still [reflect], switch automatically
if (isRefreshScopeAnnotationUsed || isSystemSetRefreshType) {
if (isRefreshScopeAnnotationUsed) {
LOGGER.warn("Detected that the bean [{}] is using @RefreshScope annotation, but the config refresh type is still [reflect]. " + "[SCT] will automatically switch to [refresh_context].", annotatedRefreshScopeBeanName);
}
if (isSystemSetRefreshType) {
LOGGER.warn("Detected that using System.setProperty to set spring.cloud.polaris.config.refresh-type = refresh_context, but the config refresh type is still [reflect]. " + "[SCT] will automatically switch to [refresh_context].");
}
switchConfigRefreshTypeProperty(applicationContext);
modifyPolarisConfigPropertiesBean(applicationContext);
// remove related bean of type [reflect]
removeRelatedBeansOfReflect(applicationContext);
// register a new refresher bean of type [refresh_context]
registerRefresherBeanOfRefreshContext(applicationContext);
// add the new refresher to context as a listener
addRefresherBeanAsListener(applicationContext);
}
}
private void switchConfigRefreshTypeProperty(ConfigurableApplicationContext applicationContext) {
MutablePropertySources propertySources = applicationContext.getEnvironment().getPropertySources();
propertySources.addFirst(new MapPropertySource(CONFIG_REFRESH_TYPE_PROPERTY, Collections.singletonMap(POLARIS_CONFIG_REFRESH_TYPE, RefreshType.REFRESH_CONTEXT)));
}
private void modifyPolarisConfigPropertiesBean(ConfigurableApplicationContext applicationContext) {
PolarisConfigProperties polarisConfigProperties = applicationContext.getBean(PolarisConfigProperties.class);
polarisConfigProperties.setRefreshType(RefreshType.REFRESH_CONTEXT);
}
private void removeRelatedBeansOfReflect(ConfigurableApplicationContext applicationContext) {
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getBeanFactory();
beanFactory.removeBeanDefinition(REFLECT_REFRESHER_BEAN_NAME);
beanFactory.removeBeanDefinition(REFLECT_REBINDER_BEAN_NAME);
}
private void registerRefresherBeanOfRefreshContext(ConfigurableApplicationContext applicationContext) {
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getBeanFactory();
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setBeanClass(PolarisRefreshEntireContextRefresher.class);
PolarisConfigProperties polarisConfigProperties = beanFactory.getBean(PolarisConfigProperties.class);
PolarisPropertySourceManager polarisPropertySourceManager = beanFactory.getBean(PolarisPropertySourceManager.class);
ContextRefresher contextRefresher = beanFactory.getBean(ContextRefresher.class);
ConstructorArgumentValues constructorArgumentValues = beanDefinition.getConstructorArgumentValues();
constructorArgumentValues.addIndexedArgumentValue(0, polarisConfigProperties);
constructorArgumentValues.addIndexedArgumentValue(1, polarisPropertySourceManager);
constructorArgumentValues.addIndexedArgumentValue(2, contextRefresher);
beanFactory.registerBeanDefinition(REFRESH_CONTEXT_REFRESHER_BEAN_NAME, beanDefinition);
}
private void addRefresherBeanAsListener(ConfigurableApplicationContext applicationContext) {
PolarisRefreshEntireContextRefresher refresher = (PolarisRefreshEntireContextRefresher) applicationContext.getBean(REFRESH_CONTEXT_REFRESHER_BEAN_NAME);
applicationContext.addApplicationListener(refresher);
}
}

@ -0,0 +1,28 @@
package com.tencent.cloud.polaris.config.logger;
/**
* @author juanyinyang
*/
public enum Level {
/** 日志级别. */
TRACE("TRACE"), DEBUG("DEBUG"), INFO("INFO"), WARN("WARN"), ERROR("ERROR"), FATAL("FATAL"), OFF("OFF");
private String level;
Level(String level) {
this.level = level;
}
public String getLevel() {
return level;
}
public static Level levelOf(String level) {
for (Level l : Level.values()) {
if (l.level.equalsIgnoreCase(level)) {
return l;
}
}
return null;
}
}

@ -0,0 +1,35 @@
package com.tencent.cloud.polaris.config.logger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.boot.logging.LoggingSystem;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
/**
* @author juanyinyang
*/
public class PolarisConfigLoggerApplicationListener implements ApplicationListener<ApplicationEvent> {
private static final Logger LOGGER = LoggerFactory.getLogger(PolarisConfigLoggerApplicationListener.class);
/**
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
*/
@Override
public void onApplicationEvent(ApplicationEvent event) {
try {
// Initialize application loggingSystem.
if (event instanceof ApplicationStartedEvent) {
ApplicationStartedEvent startedEvent = (ApplicationStartedEvent) event;
ClassLoader classLoader = startedEvent.getSpringApplication().getClassLoader();
LoggingSystem loggingSystem = LoggingSystem.get(classLoader);
LOGGER.info("PolarisConfigLoggerApplicationListener onApplicationEvent init loggingSystem:{}", loggingSystem);
PolarisConfigLoggerContext.setLogSystem(loggingSystem);
}
}
catch (Exception e) {
LOGGER.error("PolarisConfigLoggerApplicationListener onApplicationEvent exception:", e);
}
}
}

@ -0,0 +1,97 @@
/*
* Copyright (c) 2018 www.tencent.com.
* All Rights Reserved.
* This program is the confidential and proprietary information of
* www.tencent.com ("Confidential Information"). You shall not disclose such
* Confidential Information and shall use it only in accordance with
* the terms of the license agreement you entered into with www.tencent.com.
*/
package com.tencent.cloud.polaris.config.logger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.logging.LogLevel;
import org.springframework.boot.logging.LoggingSystem;
import org.springframework.util.Assert;
import static org.springframework.boot.logging.LoggingSystem.ROOT_LOGGER_NAME;
/**
* @author juanyinyang
*/
public final class PolarisConfigLoggerContext {
private static LoggingSystem loggingSystem;
private PolarisConfigLoggerContext() {
}
protected static void setLogSystem(LoggingSystem logSystem) {
Assert.notNull(logSystem, "Logging System should not be null");
PolarisConfigLoggerContext.loggingSystem = logSystem;
}
public static void setLevel(String loggerName, String level) {
if (loggingSystem == null) {
printLog("[SCT Config] PolarisConfigLoggerContext logger: [" + loggerName + "] change to target level fail. caused by internal exception:" + level, Level.WARN);
return;
}
Level loggerLevel = Level.levelOf(level);
if (loggerLevel == null) {
printLog("[SCT Config] PolarisConfigLoggerContext logger: [" + loggerName + "] change to target level fail. caused by level is not support, level:" + level, Level.WARN);
return;
}
LogLevel logLevel = null;
switch (loggerLevel) {
case TRACE:
logLevel = LogLevel.TRACE;
break;
case DEBUG:
logLevel = LogLevel.DEBUG;
break;
case OFF:
logLevel = LogLevel.OFF;
break;
case INFO:
logLevel = LogLevel.INFO;
break;
case WARN:
logLevel = LogLevel.WARN;
break;
case ERROR:
logLevel = LogLevel.ERROR;
break;
case FATAL:
logLevel = LogLevel.FATAL;
break;
default:
printLog("[SCT Config] PolarisConfigLoggerContext logger: [" + loggerName + "] setLevel fail. caused by level is not support, level: " + level, Level.WARN);
}
loggingSystem.setLogLevel(loggerName, logLevel);
printLog("[SCT Config] PolarisConfigLoggerContext logger: [" + loggerName + "] changed to level:" + level, Level.INFO);
}
/**
* .
*/
private static void printLog(String message, Level level) {
Logger logger = LoggerFactory.getLogger(ROOT_LOGGER_NAME);
if (level.ordinal() <= Level.INFO.ordinal()) {
if (logger != null) {
logger.info(message);
}
else {
StdLog.info(message);
}
}
else {
if (logger != null) {
logger.warn(message);
}
else {
StdLog.warn(message);
}
}
}
}

@ -0,0 +1,79 @@
package com.tencent.cloud.polaris.config.logger;
import java.io.PrintStream;
import java.util.Calendar;
/**
* internal output logger.
* @author juanyinyang
*/
public final class StdLog {
private static final String CLASS_INFO = StdLog.class.getName();
protected static boolean debugEnabled = false;
/**
* *enable info level log.
*/
protected static boolean infoEnabled = true;
/**
* quite mode will out put nothing.
*/
protected static boolean quietMode = false;
private static final String DEBUG_FIX = "StdLog:DEBUG: ";
private static final String INFO_FIX = "StdLog:INFO: ";
private static final String WARN_FIX = "StdLog:WARN: ";
private StdLog() {
}
public static void setQuietMode(boolean quietMode) {
StdLog.quietMode = quietMode;
}
public static void setInfoEnabled(boolean infoEnabled) {
StdLog.infoEnabled = infoEnabled;
}
public static void setDebugEnabled(boolean debugEnabled) {
StdLog.debugEnabled = debugEnabled;
}
public static void debug(String msg) {
if (debugEnabled && !quietMode) {
println(System.out, DEBUG_FIX + msg);
}
}
public static void info(String msg) {
if (infoEnabled && !quietMode) {
println(System.out, INFO_FIX + msg);
}
}
public static void warn(String msg) {
if (infoEnabled && !quietMode) {
println(System.err, WARN_FIX + msg);
}
}
public static void warn(String msg, Throwable t) {
if (quietMode) {
return;
}
println(System.err, WARN_FIX + msg);
if (t != null) {
t.printStackTrace();
}
}
private static void println(PrintStream out, String msg) {
out.println(Calendar.getInstance().getTime().toString() + " " + CLASS_INFO + " " + msg);
}
}

@ -81,8 +81,10 @@ public class PolarisConfigFileLocatorTest {
Map<String, Object> emptyMap = new HashMap<>(); Map<String, Object> emptyMap = new HashMap<>();
ConfigKVFile emptyConfigFile = new MockedConfigKVFile(emptyMap); ConfigKVFile emptyConfigFile = new MockedConfigKVFile(emptyMap);
when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "application.yml")).thenReturn(emptyConfigFile); when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "application.yml")).thenReturn(emptyConfigFile);
when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "application.yaml")).thenReturn(emptyConfigFile);
when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "bootstrap.properties")).thenReturn(emptyConfigFile); when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "bootstrap.properties")).thenReturn(emptyConfigFile);
when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "bootstrap.yml")).thenReturn(emptyConfigFile); when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "bootstrap.yml")).thenReturn(emptyConfigFile);
when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "bootstrap.yaml")).thenReturn(emptyConfigFile);
when(polarisConfigProperties.getGroups()).thenReturn(null); when(polarisConfigProperties.getGroups()).thenReturn(null);
when(environment.getActiveProfiles()).thenReturn(new String[] {}); when(environment.getActiveProfiles()).thenReturn(new String[] {});
@ -121,11 +123,15 @@ public class PolarisConfigFileLocatorTest {
Map<String, Object> emptyMap = new HashMap<>(); Map<String, Object> emptyMap = new HashMap<>();
ConfigKVFile emptyConfigFile = new MockedConfigKVFile(emptyMap); ConfigKVFile emptyConfigFile = new MockedConfigKVFile(emptyMap);
when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "application.yml")).thenReturn(emptyConfigFile); when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "application.yml")).thenReturn(emptyConfigFile);
when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "application.yaml")).thenReturn(emptyConfigFile);
when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "application-dev.yml")).thenReturn(emptyConfigFile); when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "application-dev.yml")).thenReturn(emptyConfigFile);
when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "application-dev.yaml")).thenReturn(emptyConfigFile);
when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "bootstrap.properties")).thenReturn(emptyConfigFile); when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "bootstrap.properties")).thenReturn(emptyConfigFile);
when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "bootstrap-dev.properties")).thenReturn(emptyConfigFile); when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "bootstrap-dev.properties")).thenReturn(emptyConfigFile);
when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "bootstrap.yml")).thenReturn(emptyConfigFile); when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "bootstrap.yml")).thenReturn(emptyConfigFile);
when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "bootstrap.yaml")).thenReturn(emptyConfigFile);
when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "bootstrap-dev.yml")).thenReturn(emptyConfigFile); when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "bootstrap-dev.yml")).thenReturn(emptyConfigFile);
when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "bootstrap-dev.yaml")).thenReturn(emptyConfigFile);
when(polarisConfigProperties.getGroups()).thenReturn(null); when(polarisConfigProperties.getGroups()).thenReturn(null);
when(environment.getActiveProfiles()).thenReturn(new String[] {"dev"}); when(environment.getActiveProfiles()).thenReturn(new String[] {"dev"});
@ -150,8 +156,10 @@ public class PolarisConfigFileLocatorTest {
when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "application.properties")).thenReturn(emptyConfigFile); when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "application.properties")).thenReturn(emptyConfigFile);
when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "application.yml")).thenReturn(emptyConfigFile); when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "application.yml")).thenReturn(emptyConfigFile);
when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "application.yaml")).thenReturn(emptyConfigFile);
when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "bootstrap.properties")).thenReturn(emptyConfigFile); when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "bootstrap.properties")).thenReturn(emptyConfigFile);
when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "bootstrap.yml")).thenReturn(emptyConfigFile); when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "bootstrap.yml")).thenReturn(emptyConfigFile);
when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "bootstrap.yaml")).thenReturn(emptyConfigFile);
List<ConfigFileGroup> customFiles = new LinkedList<>(); List<ConfigFileGroup> customFiles = new LinkedList<>();
ConfigFileGroup configFileGroup = new ConfigFileGroup(); ConfigFileGroup configFileGroup = new ConfigFileGroup();

@ -0,0 +1,101 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
*/
package com.tencent.cloud.polaris.config.adapter;
import com.tencent.cloud.polaris.config.PolarisConfigAutoConfiguration;
import com.tencent.cloud.polaris.config.PolarisConfigBootstrapAutoConfiguration;
import org.assertj.core.api.InstanceOfAssertFactories;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration;
import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import static org.assertj.core.api.Assertions.as;
import static org.assertj.core.api.Assertions.assertThat;
/**
* test for {@link PolarisConfigRefreshScopeAnnotationDetector}.
*/
@SuppressWarnings("rawtypes")
public class PolarisConfigRefreshScopeAnnotationDetectorTest {
private static Class refreshScopeAnnotationClass = null;
static {
try {
refreshScopeAnnotationClass = Class.forName(
"org.springframework.cloud.context.config.annotation.RefreshScope",
false,
PolarisConfigRefreshScopeAnnotationDetectorTest.class.getClassLoader());
}
catch (ClassNotFoundException ignored) {
}
}
@Test
public void testUseRefreshScope() {
ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(PolarisConfigBootstrapAutoConfiguration.class))
.withConfiguration(AutoConfigurations.of(PolarisConfigAutoConfiguration.class))
.withConfiguration(AutoConfigurations.of(RefreshAutoConfiguration.class))
.withConfiguration(AutoConfigurations.of(ConfigurationPropertiesRebinderAutoConfiguration.class))
.withBean("testBeanWithRefreshScope", TestBeanWithRefreshScope.class)
.withPropertyValues("spring.application.name=" + "polarisConfigRefreshScopeAnnotationDetectorTest")
.withPropertyValues("server.port=" + 8080)
.withPropertyValues("spring.cloud.polaris.address=grpc://127.0.0.1:10081")
.withPropertyValues("spring.cloud.polaris.config.connect-remote-server=false");
contextRunner.run(context -> {
assertThat(context).hasSingleBean(PolarisConfigRefreshScopeAnnotationDetector.class);
PolarisConfigRefreshScopeAnnotationDetector detector = context.getBean(PolarisConfigRefreshScopeAnnotationDetector.class);
assertThat(detector.isRefreshScopeAnnotationUsed()).isTrue();
assertThat(detector.getAnnotatedRefreshScopeBeanName()).isEqualTo("scopedTarget.testBeanWithRefreshScope");
assertThat(detector).extracting("refreshScopeAnnotationClass", as(InstanceOfAssertFactories.type(Class.class)))
.isEqualTo(refreshScopeAnnotationClass);
});
}
@Test
public void testNotUseRefreshScope() {
ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(PolarisConfigBootstrapAutoConfiguration.class))
.withConfiguration(AutoConfigurations.of(PolarisConfigAutoConfiguration.class))
.withConfiguration(AutoConfigurations.of(RefreshAutoConfiguration.class))
.withConfiguration(AutoConfigurations.of(ConfigurationPropertiesRebinderAutoConfiguration.class))
.withPropertyValues("spring.application.name=" + "polarisConfigRefreshScopeAnnotationDetectorTest")
.withPropertyValues("server.port=" + 8080)
.withPropertyValues("spring.cloud.polaris.address=grpc://127.0.0.1:10081")
.withPropertyValues("spring.cloud.polaris.config.connect-remote-server=false");
contextRunner.run(context -> {
assertThat(context).hasSingleBean(PolarisConfigRefreshScopeAnnotationDetector.class);
PolarisConfigRefreshScopeAnnotationDetector detector = context.getBean(PolarisConfigRefreshScopeAnnotationDetector.class);
assertThat(detector.isRefreshScopeAnnotationUsed()).isFalse();
assertThat(detector.getAnnotatedRefreshScopeBeanName()).isNull();
assertThat(detector).extracting("refreshScopeAnnotationClass", as(InstanceOfAssertFactories.type(Class.class)))
.isEqualTo(refreshScopeAnnotationClass);
});
}
@RefreshScope
protected static class TestBeanWithRefreshScope {
}
}

@ -0,0 +1,154 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
*/
package com.tencent.cloud.polaris.config.listener;
import java.util.HashMap;
import java.util.Map;
import com.google.common.collect.Lists;
import com.tencent.cloud.polaris.config.adapter.MockedConfigKVFile;
import com.tencent.cloud.polaris.config.adapter.PolarisPropertySource;
import com.tencent.cloud.polaris.config.adapter.PolarisPropertySourceManager;
import com.tencent.cloud.polaris.config.adapter.PolarisRefreshAffectedContextRefresher;
import com.tencent.cloud.polaris.config.config.PolarisConfigProperties;
import com.tencent.cloud.polaris.config.enums.RefreshType;
import com.tencent.polaris.configuration.api.core.ChangeType;
import com.tencent.polaris.configuration.api.core.ConfigKVFileChangeEvent;
import com.tencent.polaris.configuration.api.core.ConfigPropertyChangeInfo;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.context.refresh.ContextRefresher;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import static com.tencent.cloud.polaris.config.condition.ReflectRefreshTypeCondition.POLARIS_CONFIG_REFRESH_TYPE;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.DEFINED_PORT;
/**
* test for {@link PolarisConfigRefreshOptimizationListener}.
*/
@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = DEFINED_PORT, classes = PolarisConfigRefreshOptimizationListenerNotTriggeredTest.TestApplication.class,
properties = {
"server.port=8081",
"spring.cloud.polaris.address=grpc://127.0.0.1:10081",
"spring.cloud.polaris.config.connect-remote-server=false",
"spring.cloud.polaris.config.refresh-type=reflect",
"spring.config.location = classpath:application-test.yml"
})
public class PolarisConfigRefreshOptimizationListenerNotTriggeredTest {
private static final String REFLECT_REFRESHER_BEAN_NAME = "polarisReflectPropertySourceAutoRefresher";
private static final String TEST_NAMESPACE = "testNamespace";
private static final String TEST_SERVICE_NAME = "testServiceName";
private static final String TEST_FILE_NAME = "application.properties";
@Autowired
private ConfigurableApplicationContext context;
@Test
public void testNotSwitchConfigRefreshType() {
RefreshType actualRefreshType = context.getEnvironment()
.getProperty(POLARIS_CONFIG_REFRESH_TYPE, RefreshType.class);
assertThat(actualRefreshType).isEqualTo(RefreshType.REFLECT);
PolarisConfigProperties polarisConfigProperties = context.getBean(PolarisConfigProperties.class);
assertThat(polarisConfigProperties.getRefreshType()).isEqualTo(RefreshType.REFLECT);
assertThat(context.containsBean(REFLECT_REFRESHER_BEAN_NAME)).isTrue();
PolarisRefreshAffectedContextRefresher refresher = context
.getBean(REFLECT_REFRESHER_BEAN_NAME, PolarisRefreshAffectedContextRefresher.class);
assertThat(((AbstractApplicationContext) context).getApplicationListeners().contains(refresher)).isTrue();
}
@Test
public void testConfigFileChanged() {
Map<String, Object> content = new HashMap<>();
content.put("k1", "v1");
content.put("k2", "v2");
content.put("k3", "v3");
MockedConfigKVFile file = new MockedConfigKVFile(content);
PolarisPropertySource polarisPropertySource = new PolarisPropertySource(TEST_NAMESPACE, TEST_SERVICE_NAME, TEST_FILE_NAME,
file, content);
PolarisPropertySourceManager manager = context.getBean(PolarisPropertySourceManager.class);
when(manager.getAllPropertySources()).thenReturn(Lists.newArrayList(polarisPropertySource));
PolarisRefreshAffectedContextRefresher refresher = context.getBean(PolarisRefreshAffectedContextRefresher.class);
PolarisRefreshAffectedContextRefresher spyRefresher = Mockito.spy(refresher);
spyRefresher.onApplicationEvent(null);
ConfigPropertyChangeInfo changeInfo = new ConfigPropertyChangeInfo("k1", "v1", "v11", ChangeType.MODIFIED);
ConfigPropertyChangeInfo changeInfo2 = new ConfigPropertyChangeInfo("k4", null, "v4", ChangeType.ADDED);
ConfigPropertyChangeInfo changeInfo3 = new ConfigPropertyChangeInfo("k2", "v2", null, ChangeType.DELETED);
Map<String, ConfigPropertyChangeInfo> changeInfos = new HashMap<>();
changeInfos.put("k1", changeInfo);
changeInfos.put("k2", changeInfo3);
changeInfos.put("k4", changeInfo2);
ConfigKVFileChangeEvent event = new ConfigKVFileChangeEvent(changeInfos);
file.fireChangeListener(event);
ContextRefresher mockContextRefresher = context.getBean(ContextRefresher.class);
when(mockContextRefresher.refresh()).thenReturn(event.changedKeys());
Mockito.verify(spyRefresher, Mockito.times(1))
.refreshSpringValue("k1");
Mockito.verify(spyRefresher, Mockito.times(1))
.refreshSpringValue("k2");
Mockito.verify(spyRefresher, Mockito.times(1))
.refreshSpringValue("k4");
Mockito.verify(spyRefresher, Mockito.times(1))
.refreshConfigurationProperties(event.changedKeys());
}
@SpringBootApplication
protected static class TestApplication {
@Primary
@Bean
public PolarisPropertySourceManager polarisPropertySourceManager() {
return mock(PolarisPropertySourceManager.class);
}
@Primary
@Bean
public ContextRefresher contextRefresher() {
return mock(ContextRefresher.class);
}
@Component
protected static class TestBeanWithoutRefreshScope {
}
}
}

@ -0,0 +1,156 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
*/
package com.tencent.cloud.polaris.config.listener;
import java.util.HashMap;
import java.util.Map;
import com.google.common.collect.Lists;
import com.tencent.cloud.polaris.config.adapter.MockedConfigKVFile;
import com.tencent.cloud.polaris.config.adapter.PolarisPropertySource;
import com.tencent.cloud.polaris.config.adapter.PolarisPropertySourceManager;
import com.tencent.cloud.polaris.config.adapter.PolarisRefreshEntireContextRefresher;
import com.tencent.cloud.polaris.config.config.PolarisConfigProperties;
import com.tencent.cloud.polaris.config.enums.RefreshType;
import com.tencent.polaris.configuration.api.core.ChangeType;
import com.tencent.polaris.configuration.api.core.ConfigKVFileChangeEvent;
import com.tencent.polaris.configuration.api.core.ConfigPropertyChangeInfo;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.context.refresh.ContextRefresher;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import static com.tencent.cloud.polaris.config.condition.ReflectRefreshTypeCondition.POLARIS_CONFIG_REFRESH_TYPE;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.DEFINED_PORT;
/**
* test for {@link PolarisConfigRefreshOptimizationListener}.
*/
@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = DEFINED_PORT, classes = PolarisConfigRefreshOptimizationListenerTriggeredTest.TestApplication.class,
properties = {
"server.port=8081",
"spring.cloud.polaris.address=grpc://127.0.0.1:10081",
"spring.cloud.polaris.config.connect-remote-server=false",
"spring.cloud.polaris.config.refresh-type=reflect",
"spring.config.location = classpath:application-test.yml"
})
public class PolarisConfigRefreshOptimizationListenerTriggeredTest {
private static final String REFRESH_CONTEXT_REFRESHER_BEAN_NAME = "polarisRefreshContextPropertySourceAutoRefresher";
private static final String TEST_NAMESPACE = "testNamespace";
private static final String TEST_SERVICE_NAME = "testServiceName";
private static final String TEST_FILE_NAME = "application.properties";
@Autowired
private ConfigurableApplicationContext context;
@Test
public void testSwitchConfigRefreshType() {
RefreshType actualRefreshType = context.getEnvironment()
.getProperty(POLARIS_CONFIG_REFRESH_TYPE, RefreshType.class);
assertThat(actualRefreshType).isEqualTo(RefreshType.REFRESH_CONTEXT);
PolarisConfigProperties polarisConfigProperties = context.getBean(PolarisConfigProperties.class);
assertThat(polarisConfigProperties.getRefreshType()).isEqualTo(RefreshType.REFRESH_CONTEXT);
assertThat(context.containsBean(REFRESH_CONTEXT_REFRESHER_BEAN_NAME)).isTrue();
PolarisRefreshEntireContextRefresher refresher = context
.getBean(REFRESH_CONTEXT_REFRESHER_BEAN_NAME, PolarisRefreshEntireContextRefresher.class);
assertThat(((AbstractApplicationContext) context).getApplicationListeners().contains(refresher)).isTrue();
}
@Test
public void testConfigFileChanged() {
Map<String, Object> content = new HashMap<>();
content.put("k1", "v1");
content.put("k2", "v2");
content.put("k3", "v3");
MockedConfigKVFile file = new MockedConfigKVFile(content);
PolarisPropertySource polarisPropertySource = new PolarisPropertySource(TEST_NAMESPACE, TEST_SERVICE_NAME, TEST_FILE_NAME,
file, content);
PolarisPropertySourceManager manager = context.getBean(PolarisPropertySourceManager.class);
when(manager.getAllPropertySources()).thenReturn(Lists.newArrayList(polarisPropertySource));
PolarisRefreshEntireContextRefresher refresher = context.getBean(PolarisRefreshEntireContextRefresher.class);
PolarisRefreshEntireContextRefresher spyRefresher = Mockito.spy(refresher);
spyRefresher.onApplicationEvent(null);
ConfigPropertyChangeInfo changeInfo = new ConfigPropertyChangeInfo("k1", "v1", "v11", ChangeType.MODIFIED);
ConfigPropertyChangeInfo changeInfo2 = new ConfigPropertyChangeInfo("k4", null, "v4", ChangeType.ADDED);
ConfigPropertyChangeInfo changeInfo3 = new ConfigPropertyChangeInfo("k2", "v2", null, ChangeType.DELETED);
Map<String, ConfigPropertyChangeInfo> changeInfos = new HashMap<>();
changeInfos.put("k1", changeInfo);
changeInfos.put("k2", changeInfo3);
changeInfos.put("k4", changeInfo2);
ConfigKVFileChangeEvent event = new ConfigKVFileChangeEvent(changeInfos);
file.fireChangeListener(event);
ContextRefresher mockContextRefresher = context.getBean(ContextRefresher.class);
when(mockContextRefresher.refresh()).thenReturn(event.changedKeys());
Mockito.verify(spyRefresher, Mockito.times(1))
.refreshSpringValue("k1");
Mockito.verify(spyRefresher, Mockito.times(1))
.refreshSpringValue("k2");
Mockito.verify(spyRefresher, Mockito.times(1))
.refreshSpringValue("k4");
Mockito.verify(spyRefresher, Mockito.times(1))
.refreshConfigurationProperties(event.changedKeys());
}
@SpringBootApplication
protected static class TestApplication {
@Primary
@Bean
public PolarisPropertySourceManager polarisPropertySourceManager() {
return mock(PolarisPropertySourceManager.class);
}
@Primary
@Bean
public ContextRefresher contextRefresher() {
return mock(ContextRefresher.class);
}
@Component
@RefreshScope
protected static class TestBeanWithRefreshScope {
}
}
}

@ -18,14 +18,12 @@
package com.tencent.cloud.polaris; package com.tencent.cloud.polaris;
import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled; import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled;
import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryHandler; import com.tencent.cloud.polaris.discovery.PolarisDiscoveryHandler;
import com.tencent.cloud.polaris.extend.consul.ConsulConfigModifier; import com.tencent.cloud.polaris.extend.consul.ConsulConfigModifier;
import com.tencent.cloud.polaris.extend.consul.ConsulContextProperties; import com.tencent.cloud.polaris.extend.consul.ConsulContextProperties;
import com.tencent.cloud.polaris.extend.nacos.NacosConfigModifier; import com.tencent.cloud.polaris.extend.nacos.NacosConfigModifier;
import com.tencent.cloud.polaris.extend.nacos.NacosContextProperties; import com.tencent.cloud.polaris.extend.nacos.NacosContextProperties;
import com.tencent.polaris.api.core.ConsumerAPI;
import com.tencent.polaris.api.core.ProviderAPI;
import com.tencent.polaris.client.api.SDKContext;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@ -46,9 +44,8 @@ public class DiscoveryPropertiesAutoConfiguration {
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public PolarisDiscoveryHandler polarisDiscoveryHandler(PolarisDiscoveryProperties polarisDiscoveryProperties, public PolarisDiscoveryHandler polarisDiscoveryHandler(PolarisDiscoveryProperties polarisDiscoveryProperties,
ProviderAPI providerAPI, SDKContext sdkContext, PolarisSDKContextManager polarisSDKContextManager) {
ConsumerAPI polarisConsumer) { return new PolarisDiscoveryHandler(polarisDiscoveryProperties, polarisSDKContextManager);
return new PolarisDiscoveryHandler(polarisDiscoveryProperties, providerAPI, sdkContext, polarisConsumer);
} }
@Bean @Bean
@ -65,13 +62,13 @@ public class DiscoveryPropertiesAutoConfiguration {
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public NacosConfigModifier nacosConfigModifier(@Autowired(required = false) NacosContextProperties nacosContextProperties) { public PolarisDiscoveryConfigModifier polarisDiscoveryConfigModifier(PolarisDiscoveryProperties polarisDiscoveryProperties) {
return new NacosConfigModifier(nacosContextProperties); return new PolarisDiscoveryConfigModifier(polarisDiscoveryProperties);
} }
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public PolarisDiscoveryConfigModifier polarisDiscoveryConfigModifier(PolarisDiscoveryProperties polarisDiscoveryProperties) { public NacosConfigModifier nacosConfigModifier(@Autowired(required = false) NacosContextProperties nacosContextProperties) {
return new PolarisDiscoveryConfigModifier(polarisDiscoveryProperties); return new NacosConfigModifier(nacosContextProperties);
} }
} }

@ -45,6 +45,11 @@ public class PolarisDiscoveryProperties {
@Value("${spring.cloud.polaris.discovery.service:${spring.cloud.polaris.service:${spring.application.name:}}}") @Value("${spring.cloud.polaris.discovery.service:${spring.cloud.polaris.service:${spring.application.name:}}}")
private String service; private String service;
/**
* Service instance id.
*/
private String instanceId;
/** /**
* The polaris authentication token. * The polaris authentication token.
*/ */
@ -96,6 +101,14 @@ public class PolarisDiscoveryProperties {
*/ */
private Long serviceListRefreshInterval = 60000L; private Long serviceListRefreshInterval = 60000L;
public String getInstanceId() {
return instanceId;
}
public void setInstanceId(String instanceId) {
this.instanceId = instanceId;
}
public String getNamespace() { public String getNamespace() {
return namespace; return namespace;
} }
@ -204,6 +217,7 @@ public class PolarisDiscoveryProperties {
return "PolarisDiscoveryProperties{" + return "PolarisDiscoveryProperties{" +
"namespace='" + namespace + '\'' + "namespace='" + namespace + '\'' +
", service='" + service + '\'' + ", service='" + service + '\'' +
", instanceId='" + instanceId + '\'' +
", token='" + token + '\'' + ", token='" + token + '\'' +
", weight=" + weight + ", weight=" + weight +
", version='" + version + '\'' + ", version='" + version + '\'' +

@ -19,14 +19,13 @@
package com.tencent.cloud.polaris.discovery; package com.tencent.cloud.polaris.discovery;
import com.tencent.cloud.polaris.PolarisDiscoveryProperties; import com.tencent.cloud.polaris.PolarisDiscoveryProperties;
import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
import com.tencent.polaris.api.core.ConsumerAPI; import com.tencent.polaris.api.core.ConsumerAPI;
import com.tencent.polaris.api.core.ProviderAPI;
import com.tencent.polaris.api.rpc.GetAllInstancesRequest; import com.tencent.polaris.api.rpc.GetAllInstancesRequest;
import com.tencent.polaris.api.rpc.GetHealthyInstancesRequest; import com.tencent.polaris.api.rpc.GetHealthyInstancesRequest;
import com.tencent.polaris.api.rpc.GetServicesRequest; import com.tencent.polaris.api.rpc.GetServicesRequest;
import com.tencent.polaris.api.rpc.InstancesResponse; import com.tencent.polaris.api.rpc.InstancesResponse;
import com.tencent.polaris.api.rpc.ServicesResponse; import com.tencent.polaris.api.rpc.ServicesResponse;
import com.tencent.polaris.client.api.SDKContext;
/** /**
* Discovery Handler for Polaris. * Discovery Handler for Polaris.
@ -37,18 +36,12 @@ public class PolarisDiscoveryHandler {
private final PolarisDiscoveryProperties polarisDiscoveryProperties; private final PolarisDiscoveryProperties polarisDiscoveryProperties;
private final ProviderAPI providerAPI;
private final SDKContext sdkContext;
private final ConsumerAPI polarisConsumer; private final ConsumerAPI polarisConsumer;
public PolarisDiscoveryHandler(PolarisDiscoveryProperties polarisDiscoveryProperties, public PolarisDiscoveryHandler(PolarisDiscoveryProperties polarisDiscoveryProperties,
ProviderAPI providerAPI, SDKContext sdkContext, ConsumerAPI polarisConsumer) { PolarisSDKContextManager polarisSDKContextManager) {
this.polarisDiscoveryProperties = polarisDiscoveryProperties; this.polarisDiscoveryProperties = polarisDiscoveryProperties;
this.providerAPI = providerAPI; this.polarisConsumer = polarisSDKContextManager.getConsumerAPI();
this.sdkContext = sdkContext;
this.polarisConsumer = polarisConsumer;
} }
/** /**
@ -75,15 +68,7 @@ public class PolarisDiscoveryHandler {
GetAllInstancesRequest request = new GetAllInstancesRequest(); GetAllInstancesRequest request = new GetAllInstancesRequest();
request.setNamespace(namespace); request.setNamespace(namespace);
request.setService(service); request.setService(service);
return polarisConsumer.getAllInstance(request); return polarisConsumer.getAllInstances(request);
}
public ProviderAPI getProviderAPI() {
return providerAPI;
}
public SDKContext getSdkContext() {
return sdkContext;
} }
/** /**

@ -48,7 +48,7 @@ public class PolarisReactiveDiscoveryClient implements ReactiveDiscoveryClient {
@Override @Override
public String description() { public String description() {
return "Spring Cloud Tencent Polaris Reactive Discovery Client."; return "Spring Cloud Tencent Polaris Reactive Discovery Client";
} }
@Override @Override

@ -22,23 +22,28 @@ import com.tencent.cloud.polaris.discovery.PolarisServiceDiscovery;
import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.ConditionalOnDiscoveryHealthIndicatorEnabled;
import org.springframework.cloud.client.ConditionalOnReactiveDiscoveryEnabled; import org.springframework.cloud.client.ConditionalOnReactiveDiscoveryEnabled;
import org.springframework.cloud.client.ReactiveCommonsClientAutoConfiguration; import org.springframework.cloud.client.ReactiveCommonsClientAutoConfiguration;
import org.springframework.cloud.client.discovery.composite.reactive.ReactiveCompositeDiscoveryClientAutoConfiguration; import org.springframework.cloud.client.discovery.composite.reactive.ReactiveCompositeDiscoveryClientAutoConfiguration;
import org.springframework.cloud.client.discovery.health.DiscoveryClientHealthIndicatorProperties;
import org.springframework.cloud.client.discovery.health.reactive.ReactiveDiscoveryClientHealthIndicator;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
/** /**
* Reactive Discovery Client Configuration for Polaris. * Reactive Discovery Client Configuration for Polaris.
* *
* @author Haotian Zhang, Andrew Shan, Jie Cheng * @author Haotian Zhang, Andrew Shan, Jie Cheng, youta
*/ */
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@ConditionalOnReactiveDiscoveryEnabled @ConditionalOnReactiveDiscoveryEnabled
@AutoConfigureAfter({ PolarisDiscoveryAutoConfiguration.class, @EnableConfigurationProperties(DiscoveryClientHealthIndicatorProperties.class)
ReactiveCompositeDiscoveryClientAutoConfiguration.class }) @AutoConfigureAfter({PolarisDiscoveryAutoConfiguration.class, ReactiveCompositeDiscoveryClientAutoConfiguration.class})
@AutoConfigureBefore({ ReactiveCommonsClientAutoConfiguration.class }) @AutoConfigureBefore({ReactiveCommonsClientAutoConfiguration.class})
public class PolarisReactiveDiscoveryClientConfiguration { public class PolarisReactiveDiscoveryClientConfiguration {
@Bean @Bean
@ -47,4 +52,12 @@ public class PolarisReactiveDiscoveryClientConfiguration {
PolarisServiceDiscovery polarisServiceDiscovery) { PolarisServiceDiscovery polarisServiceDiscovery) {
return new PolarisReactiveDiscoveryClient(polarisServiceDiscovery); return new PolarisReactiveDiscoveryClient(polarisServiceDiscovery);
} }
@Bean
@ConditionalOnClass(name = "org.springframework.boot.actuate.health.ReactiveHealthIndicator")
@ConditionalOnDiscoveryHealthIndicatorEnabled
public ReactiveDiscoveryClientHealthIndicator polarisReactiveDiscoveryClientHealthIndicator(
PolarisReactiveDiscoveryClient client, DiscoveryClientHealthIndicatorProperties properties) {
return new ReactiveDiscoveryClientHealthIndicator(client, properties);
}
} }

@ -21,7 +21,7 @@ import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryHandler; import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
import com.tencent.polaris.client.util.NamedThreadFactory; import com.tencent.polaris.client.util.NamedThreadFactory;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -45,14 +45,14 @@ public class PolarisRefreshApplicationReadyEventListener
private static final Logger LOG = LoggerFactory.getLogger(PolarisRefreshApplicationReadyEventListener.class); private static final Logger LOG = LoggerFactory.getLogger(PolarisRefreshApplicationReadyEventListener.class);
private static final int DELAY = 60; private static final int DELAY = 60;
private final PolarisDiscoveryHandler polarisDiscoveryHandler; private final PolarisSDKContextManager polarisSDKContextManager;
private final PolarisServiceStatusChangeListener polarisServiceStatusChangeListener; private final PolarisServiceStatusChangeListener polarisServiceStatusChangeListener;
private final ScheduledExecutorService refreshExecutor; private final ScheduledExecutorService refreshExecutor;
private ApplicationEventPublisher publisher; private ApplicationEventPublisher publisher;
public PolarisRefreshApplicationReadyEventListener(PolarisDiscoveryHandler polarisDiscoveryHandler, public PolarisRefreshApplicationReadyEventListener(PolarisSDKContextManager polarisSDKContextManager,
PolarisServiceStatusChangeListener polarisServiceStatusChangeListener) { PolarisServiceStatusChangeListener polarisServiceStatusChangeListener) {
this.polarisDiscoveryHandler = polarisDiscoveryHandler; this.polarisSDKContextManager = polarisSDKContextManager;
this.polarisServiceStatusChangeListener = polarisServiceStatusChangeListener; this.polarisServiceStatusChangeListener = polarisServiceStatusChangeListener;
this.refreshExecutor = Executors.newSingleThreadScheduledExecutor( this.refreshExecutor = Executors.newSingleThreadScheduledExecutor(
new NamedThreadFactory("polaris-service-refresh")); new NamedThreadFactory("polaris-service-refresh"));
@ -61,7 +61,7 @@ public class PolarisRefreshApplicationReadyEventListener
@Override @Override
public void onApplicationEvent(ApplicationReadyEvent event) { public void onApplicationEvent(ApplicationReadyEvent event) {
// Register service change listener. // Register service change listener.
polarisDiscoveryHandler.getSdkContext().getExtensions().getLocalRegistry() polarisSDKContextManager.getSDKContext().getExtensions().getLocalRegistry()
.registerResourceListener(polarisServiceStatusChangeListener); .registerResourceListener(polarisServiceStatusChangeListener);
// Begin scheduled refresh thread. // Begin scheduled refresh thread.

@ -18,7 +18,7 @@
package com.tencent.cloud.polaris.discovery.refresh; package com.tencent.cloud.polaris.discovery.refresh;
import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled; import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryHandler; import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@ -42,8 +42,8 @@ public class PolarisRefreshConfiguration {
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public PolarisRefreshApplicationReadyEventListener polarisServiceStatusApplicationReadyEventListener( public PolarisRefreshApplicationReadyEventListener polarisServiceStatusApplicationReadyEventListener(
PolarisDiscoveryHandler polarisDiscoveryHandler, PolarisSDKContextManager polarisSDKContextManager,
PolarisServiceStatusChangeListener polarisServiceStatusChangeListener) { PolarisServiceStatusChangeListener polarisServiceStatusChangeListener) {
return new PolarisRefreshApplicationReadyEventListener(polarisDiscoveryHandler, polarisServiceStatusChangeListener); return new PolarisRefreshApplicationReadyEventListener(polarisSDKContextManager, polarisServiceStatusChangeListener);
} }
} }

@ -17,6 +17,10 @@
package com.tencent.cloud.polaris.registry; package com.tencent.cloud.polaris.registry;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.polaris.PolarisDiscoveryProperties;
import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.assembly.api.AssemblyAPI;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -32,15 +36,25 @@ import org.springframework.util.StringUtils;
*/ */
public class PolarisAutoServiceRegistration extends AbstractAutoServiceRegistration<PolarisRegistration> { public class PolarisAutoServiceRegistration extends AbstractAutoServiceRegistration<PolarisRegistration> {
private static final Logger LOG = LoggerFactory.getLogger(PolarisAutoServiceRegistration.class); private static final Logger log = LoggerFactory.getLogger(PolarisAutoServiceRegistration.class);
private final PolarisRegistration registration; private final PolarisRegistration registration;
public PolarisAutoServiceRegistration(ServiceRegistry<PolarisRegistration> serviceRegistry, private final PolarisDiscoveryProperties polarisDiscoveryProperties;
private final AssemblyAPI assemblyAPI;
public PolarisAutoServiceRegistration(
ServiceRegistry<PolarisRegistration> serviceRegistry,
AutoServiceRegistrationProperties autoServiceRegistrationProperties, AutoServiceRegistrationProperties autoServiceRegistrationProperties,
PolarisRegistration registration) { PolarisRegistration registration,
PolarisDiscoveryProperties polarisDiscoveryProperties,
AssemblyAPI assemblyAPI
) {
super(serviceRegistry, autoServiceRegistrationProperties); super(serviceRegistry, autoServiceRegistrationProperties);
this.registration = registration; this.registration = registration;
this.polarisDiscoveryProperties = polarisDiscoveryProperties;
this.assemblyAPI = assemblyAPI;
} }
@Override @Override
@ -56,9 +70,12 @@ public class PolarisAutoServiceRegistration extends AbstractAutoServiceRegistrat
@Override @Override
protected void register() { protected void register() {
if (!this.registration.isRegisterEnabled()) { if (!this.registration.isRegisterEnabled()) {
LOG.debug("Registration disabled."); log.debug("Registration disabled.");
return; return;
} }
if (assemblyAPI != null) {
assemblyAPI.initService(new ServiceKey(MetadataContext.LOCAL_NAMESPACE, MetadataContext.LOCAL_SERVICE));
}
super.register(); super.register();
} }
@ -73,7 +90,7 @@ public class PolarisAutoServiceRegistration extends AbstractAutoServiceRegistrat
@Override @Override
protected Object getConfiguration() { protected Object getConfiguration() {
return this.registration.getPolarisProperties(); return this.polarisDiscoveryProperties;
} }
@Override @Override
@ -84,7 +101,7 @@ public class PolarisAutoServiceRegistration extends AbstractAutoServiceRegistrat
@Override @Override
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
protected String getAppName() { protected String getAppName() {
String appName = registration.getPolarisProperties().getService(); String appName = registration.getServiceId();
return StringUtils.isEmpty(appName) ? super.getAppName() : appName; return StringUtils.isEmpty(appName) ? super.getAppName() : appName;
} }
} }

@ -13,13 +13,13 @@
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * 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 * CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*
*/ */
package com.tencent.cloud.polaris.registry; package com.tencent.cloud.polaris.registry;
import java.net.URI; import java.net.URI;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
@ -55,24 +55,18 @@ public class PolarisRegistration implements Registration {
private final PolarisDiscoveryProperties polarisDiscoveryProperties; private final PolarisDiscoveryProperties polarisDiscoveryProperties;
private final ConsulContextProperties consulContextProperties;
private final SDKContext polarisContext; private final SDKContext polarisContext;
private final StaticMetadataManager staticMetadataManager; private final StaticMetadataManager staticMetadataManager;
private final NacosContextProperties nacosContextProperties; private final String serviceId;
private final String host;
private final boolean isSecure;
private final ServletWebServerApplicationContext servletWebServerApplicationContext; private final ServletWebServerApplicationContext servletWebServerApplicationContext;
private final ReactiveWebServerApplicationContext reactiveWebServerApplicationContext; private final ReactiveWebServerApplicationContext reactiveWebServerApplicationContext;
private boolean registerEnabled = false;
private Map<String, String> metadata; private Map<String, String> metadata;
private String host;
private int port; private int port;
private String instanceId; private String instanceId;
public PolarisRegistration( public PolarisRegistration(
@ -84,32 +78,95 @@ public class PolarisRegistration implements Registration {
@Nullable ServletWebServerApplicationContext servletWebServerApplicationContext, @Nullable ServletWebServerApplicationContext servletWebServerApplicationContext,
@Nullable ReactiveWebServerApplicationContext reactiveWebServerApplicationContext) { @Nullable ReactiveWebServerApplicationContext reactiveWebServerApplicationContext) {
this.polarisDiscoveryProperties = polarisDiscoveryProperties; this.polarisDiscoveryProperties = polarisDiscoveryProperties;
this.consulContextProperties = consulContextProperties;
this.polarisContext = context; this.polarisContext = context;
this.staticMetadataManager = staticMetadataManager; this.staticMetadataManager = staticMetadataManager;
this.nacosContextProperties = nacosContextProperties;
this.servletWebServerApplicationContext = servletWebServerApplicationContext; this.servletWebServerApplicationContext = servletWebServerApplicationContext;
this.reactiveWebServerApplicationContext = reactiveWebServerApplicationContext; this.reactiveWebServerApplicationContext = reactiveWebServerApplicationContext;
host = polarisContext.getConfig().getGlobal().getAPI().getBindIP();
if (polarisContextProperties != null) {
port = polarisContextProperties.getLocalPort();
}
}
@Override // generate serviceId
public String getServiceId() {
if (Objects.isNull(nacosContextProperties)) { if (Objects.isNull(nacosContextProperties)) {
return polarisDiscoveryProperties.getService(); serviceId = polarisDiscoveryProperties.getService();
} }
else { else {
String group = nacosContextProperties.getGroup(); String group = nacosContextProperties.getGroup();
if (StringUtils.isNotBlank(group) && !DEFAULT_GROUP.equals(group)) { if (StringUtils.isNotBlank(group) && !DEFAULT_GROUP.equals(group)) {
return String.format(GROUP_SERVER_ID_FORMAT, group, polarisDiscoveryProperties.getService()); serviceId = String.format(GROUP_SERVER_ID_FORMAT, group, polarisDiscoveryProperties.getService());
} }
else { else {
return polarisDiscoveryProperties.getService(); serviceId = polarisDiscoveryProperties.getService();
} }
} }
// generate host
host = polarisContext.getConfig().getGlobal().getAPI().getBindIP();
// generate port
if (polarisContextProperties != null) {
port = polarisContextProperties.getLocalPort();
}
// generate isSecure
isSecure = StringUtils.equalsIgnoreCase(polarisDiscoveryProperties.getProtocol(), "https");
// generate metadata
if (CollectionUtils.isEmpty(metadata)) {
Map<String, String> instanceMetadata = new HashMap<>();
// put internal metadata
instanceMetadata.put(METADATA_KEY_IP, host);
instanceMetadata.put(METADATA_KEY_ADDRESS, host + ":" + port);
// put internal-nacos-cluster if necessary
if (Objects.nonNull(nacosContextProperties)) {
String clusterName = nacosContextProperties.getClusterName();
if (StringUtils.isNotBlank(clusterName) && !DEFAULT_CLUSTER.equals(clusterName)) {
instanceMetadata.put(NACOS_CLUSTER, clusterName);
}
}
instanceMetadata.putAll(staticMetadataManager.getMergedStaticMetadata());
this.metadata = instanceMetadata;
}
// generate registerEnabled
if (null != polarisDiscoveryProperties) {
registerEnabled = polarisDiscoveryProperties.isRegisterEnabled();
}
if (null != consulContextProperties && consulContextProperties.isEnabled()) {
registerEnabled |= consulContextProperties.isRegister();
}
if (null != nacosContextProperties && nacosContextProperties.isEnabled()) {
registerEnabled |= nacosContextProperties.isRegisterEnabled();
}
}
public static PolarisRegistration registration(PolarisDiscoveryProperties polarisDiscoveryProperties,
@Nullable PolarisContextProperties polarisContextProperties,
@Nullable ConsulContextProperties consulContextProperties,
SDKContext context, StaticMetadataManager staticMetadataManager,
@Nullable NacosContextProperties nacosContextProperties,
@Nullable ServletWebServerApplicationContext servletWebServerApplicationContext,
@Nullable ReactiveWebServerApplicationContext reactiveWebServerApplicationContext,
@Nullable List<PolarisRegistrationCustomizer> registrationCustomizers) {
PolarisRegistration polarisRegistration = new PolarisRegistration(polarisDiscoveryProperties,
polarisContextProperties, consulContextProperties, context, staticMetadataManager,
nacosContextProperties, servletWebServerApplicationContext, reactiveWebServerApplicationContext);
customize(registrationCustomizers, polarisRegistration);
return polarisRegistration;
}
public static void customize(List<PolarisRegistrationCustomizer> registrationCustomizers, PolarisRegistration registration) {
if (registrationCustomizers != null) {
for (PolarisRegistrationCustomizer customizer : registrationCustomizers) {
customizer.customize(registration);
}
}
}
@Override
public String getServiceId() {
return serviceId;
} }
@Override @Override
@ -139,7 +196,7 @@ public class PolarisRegistration implements Registration {
@Override @Override
public boolean isSecure() { public boolean isSecure() {
return StringUtils.equalsIgnoreCase(polarisDiscoveryProperties.getProtocol(), "https"); return isSecure;
} }
@Override @Override
@ -149,30 +206,9 @@ public class PolarisRegistration implements Registration {
@Override @Override
public Map<String, String> getMetadata() { public Map<String, String> getMetadata() {
if (CollectionUtils.isEmpty(metadata)) {
Map<String, String> instanceMetadata = new HashMap<>();
// put internal metadata
instanceMetadata.put(METADATA_KEY_IP, host);
instanceMetadata.put(METADATA_KEY_ADDRESS, host + ":" + port);
// put internal-nacos-cluster if necessary
String clusterName = nacosContextProperties.getClusterName();
if (StringUtils.isNotBlank(clusterName) && !DEFAULT_CLUSTER.equals(clusterName)) {
instanceMetadata.put(NACOS_CLUSTER, clusterName);
}
instanceMetadata.putAll(staticMetadataManager.getMergedStaticMetadata());
this.metadata = instanceMetadata;
}
return metadata; return metadata;
} }
public PolarisDiscoveryProperties getPolarisProperties() {
return polarisDiscoveryProperties;
}
@Override @Override
public String getInstanceId() { public String getInstanceId() {
return instanceId; return instanceId;
@ -183,18 +219,6 @@ public class PolarisRegistration implements Registration {
} }
public boolean isRegisterEnabled() { public boolean isRegisterEnabled() {
boolean registerEnabled = false;
if (null != polarisDiscoveryProperties) {
registerEnabled = polarisDiscoveryProperties.isRegisterEnabled();
}
if (null != consulContextProperties && consulContextProperties.isEnabled()) {
registerEnabled |= consulContextProperties.isRegister();
}
if (null != nacosContextProperties && nacosContextProperties.isEnabled()) {
registerEnabled |= nacosContextProperties.isRegisterEnabled();
}
return registerEnabled; return registerEnabled;
} }

@ -0,0 +1,27 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.polaris.registry;
/**
* Customizer for {@link PolarisRegistration}.
*
* @author Haotian Zhang
*/
public interface PolarisRegistrationCustomizer {
void customize(PolarisRegistration registration);
}

@ -26,6 +26,7 @@ import java.util.concurrent.ScheduledExecutorService;
import com.tencent.cloud.common.metadata.StaticMetadataManager; import com.tencent.cloud.common.metadata.StaticMetadataManager;
import com.tencent.cloud.polaris.PolarisDiscoveryProperties; import com.tencent.cloud.polaris.PolarisDiscoveryProperties;
import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryHandler; import com.tencent.cloud.polaris.discovery.PolarisDiscoveryHandler;
import com.tencent.cloud.polaris.util.OkHttpUtil; import com.tencent.cloud.polaris.util.OkHttpUtil;
import com.tencent.cloud.rpc.enhancement.stat.config.PolarisStatProperties; import com.tencent.cloud.rpc.enhancement.stat.config.PolarisStatProperties;
@ -33,6 +34,7 @@ import com.tencent.polaris.api.config.global.StatReporterConfig;
import com.tencent.polaris.api.core.ProviderAPI; import com.tencent.polaris.api.core.ProviderAPI;
import com.tencent.polaris.api.exception.PolarisException; import com.tencent.polaris.api.exception.PolarisException;
import com.tencent.polaris.api.plugin.common.PluginTypes; import com.tencent.polaris.api.plugin.common.PluginTypes;
import com.tencent.polaris.api.plugin.stat.ReporterMetaInfo;
import com.tencent.polaris.api.plugin.stat.StatReporter; import com.tencent.polaris.api.plugin.stat.StatReporter;
import com.tencent.polaris.api.pojo.Instance; import com.tencent.polaris.api.pojo.Instance;
import com.tencent.polaris.api.rpc.InstanceDeregisterRequest; import com.tencent.polaris.api.rpc.InstanceDeregisterRequest;
@ -47,6 +49,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.cloud.client.serviceregistry.ServiceRegistry; import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
@ -58,24 +61,25 @@ import static org.springframework.util.ReflectionUtils.rethrowRuntimeException;
* *
* @author Haotian Zhang, Andrew Shan, Jie Cheng, changjin wei() * @author Haotian Zhang, Andrew Shan, Jie Cheng, changjin wei()
*/ */
public class PolarisServiceRegistry implements ServiceRegistry<PolarisRegistration> { public class PolarisServiceRegistry implements ServiceRegistry<PolarisRegistration>, DisposableBean {
private static final Logger LOGGER = LoggerFactory.getLogger(PolarisServiceRegistry.class); private static final Logger LOGGER = LoggerFactory.getLogger(PolarisServiceRegistry.class);
private final PolarisDiscoveryProperties polarisDiscoveryProperties; private final PolarisDiscoveryProperties polarisDiscoveryProperties;
private final PolarisSDKContextManager polarisSDKContextManager;
private final PolarisDiscoveryHandler polarisDiscoveryHandler; private final PolarisDiscoveryHandler polarisDiscoveryHandler;
private final StaticMetadataManager staticMetadataManager; private final StaticMetadataManager staticMetadataManager;
private final ScheduledExecutorService heartbeatExecutor;
private final PolarisStatProperties polarisStatProperties; private final PolarisStatProperties polarisStatProperties;
private final ScheduledExecutorService heartbeatExecutor;
public PolarisServiceRegistry(PolarisDiscoveryProperties polarisDiscoveryProperties, public PolarisServiceRegistry(PolarisDiscoveryProperties polarisDiscoveryProperties,
PolarisDiscoveryHandler polarisDiscoveryHandler, PolarisSDKContextManager polarisSDKContextManager, PolarisDiscoveryHandler polarisDiscoveryHandler,
StaticMetadataManager staticMetadataManager, PolarisStatProperties polarisStatProperties) { StaticMetadataManager staticMetadataManager, PolarisStatProperties polarisStatProperties) {
this.polarisDiscoveryProperties = polarisDiscoveryProperties; this.polarisDiscoveryProperties = polarisDiscoveryProperties;
this.polarisSDKContextManager = polarisSDKContextManager;
this.polarisDiscoveryHandler = polarisDiscoveryHandler; this.polarisDiscoveryHandler = polarisDiscoveryHandler;
this.staticMetadataManager = staticMetadataManager; this.staticMetadataManager = staticMetadataManager;
@ -113,8 +117,9 @@ public class PolarisServiceRegistry implements ServiceRegistry<PolarisRegistrati
instanceRegisterRequest.setMetadata(registration.getMetadata()); instanceRegisterRequest.setMetadata(registration.getMetadata());
instanceRegisterRequest.setProtocol(polarisDiscoveryProperties.getProtocol()); instanceRegisterRequest.setProtocol(polarisDiscoveryProperties.getProtocol());
instanceRegisterRequest.setVersion(polarisDiscoveryProperties.getVersion()); instanceRegisterRequest.setVersion(polarisDiscoveryProperties.getVersion());
instanceRegisterRequest.setInstanceId(polarisDiscoveryProperties.getInstanceId());
try { try {
ProviderAPI providerClient = polarisDiscoveryHandler.getProviderAPI(); ProviderAPI providerClient = polarisSDKContextManager.getProviderAPI();
InstanceRegisterResponse instanceRegisterResponse; InstanceRegisterResponse instanceRegisterResponse;
if (StringUtils.isBlank(polarisDiscoveryProperties.getHealthCheckUrl())) { if (StringUtils.isBlank(polarisDiscoveryProperties.getHealthCheckUrl())) {
instanceRegisterResponse = providerClient.registerInstance(instanceRegisterRequest); instanceRegisterResponse = providerClient.registerInstance(instanceRegisterRequest);
@ -132,10 +137,16 @@ public class PolarisServiceRegistry implements ServiceRegistry<PolarisRegistrati
staticMetadataManager.getMergedStaticMetadata()); staticMetadataManager.getMergedStaticMetadata());
if (Objects.nonNull(polarisStatProperties) && polarisStatProperties.isEnabled()) { if (Objects.nonNull(polarisStatProperties) && polarisStatProperties.isEnabled()) {
try { try {
StatReporter statReporter = (StatReporter) polarisDiscoveryHandler.getSdkContext().getPlugins() StatReporter statReporter = (StatReporter) polarisSDKContextManager.getSDKContext().getPlugins()
.getPlugin(PluginTypes.STAT_REPORTER.getBaseType(), StatReporterConfig.DEFAULT_REPORTER_PROMETHEUS); .getPlugin(PluginTypes.STAT_REPORTER.getBaseType(), StatReporterConfig.DEFAULT_REPORTER_PROMETHEUS);
if (Objects.nonNull(statReporter)) { if (Objects.nonNull(statReporter)) {
LOGGER.info("Stat server started on port: " + statReporter.metaInfo().getPort() + " (http)"); ReporterMetaInfo reporterMetaInfo = statReporter.metaInfo();
if (reporterMetaInfo.getPort() != null) {
LOGGER.info("Stat server started on port: " + reporterMetaInfo.getPort() + " (http)");
}
else {
LOGGER.info("Stat server is set to type of Push gateway");
}
} }
else { else {
LOGGER.warn("Plugin StatReporter not found"); LOGGER.warn("Plugin StatReporter not found");
@ -146,10 +157,12 @@ public class PolarisServiceRegistry implements ServiceRegistry<PolarisRegistrati
} }
} }
ServiceConfigImpl serviceConfig = (ServiceConfigImpl) polarisDiscoveryHandler.getSdkContext().getConfig() ServiceConfigImpl serviceConfig = (ServiceConfigImpl) polarisSDKContextManager.getSDKContext().getConfig()
.getProvider().getService(); .getProvider().getService();
serviceConfig.setNamespace(polarisDiscoveryProperties.getNamespace()); serviceConfig.setNamespace(polarisDiscoveryProperties.getNamespace());
serviceConfig.setName(serviceId); serviceConfig.setName(serviceId);
PolarisSDKContextManager.isRegistered = true;
} }
catch (Exception e) { catch (Exception e) {
LOGGER.error("polaris registry, {} register failed...{},", registration.getServiceId(), registration, e); LOGGER.error("polaris registry, {} register failed...{},", registration.getServiceId(), registration, e);
@ -174,7 +187,7 @@ public class PolarisServiceRegistry implements ServiceRegistry<PolarisRegistrati
deRegisterRequest.setPort(registration.getPort()); deRegisterRequest.setPort(registration.getPort());
try { try {
ProviderAPI providerClient = polarisDiscoveryHandler.getProviderAPI(); ProviderAPI providerClient = polarisSDKContextManager.getProviderAPI();
providerClient.deRegister(deRegisterRequest); providerClient.deRegister(deRegisterRequest);
} }
catch (Exception e) { catch (Exception e) {
@ -184,8 +197,9 @@ public class PolarisServiceRegistry implements ServiceRegistry<PolarisRegistrati
if (null != heartbeatExecutor) { if (null != heartbeatExecutor) {
heartbeatExecutor.shutdown(); heartbeatExecutor.shutdown();
} }
LOGGER.info("De-registration finished.");
PolarisSDKContextManager.isRegistered = false;
} }
LOGGER.info("De-registration finished.");
} }
@Override @Override
@ -240,7 +254,7 @@ public class PolarisServiceRegistry implements ServiceRegistry<PolarisRegistrati
return; return;
} }
polarisDiscoveryHandler.getProviderAPI().heartbeat(heartbeatRequest); polarisSDKContextManager.getProviderAPI().heartbeat(heartbeatRequest);
LOGGER.trace("Polaris heartbeat is sent"); LOGGER.trace("Polaris heartbeat is sent");
} }
catch (PolarisException e) { catch (PolarisException e) {
@ -251,4 +265,11 @@ public class PolarisServiceRegistry implements ServiceRegistry<PolarisRegistrati
} }
}, polarisDiscoveryProperties.getHeartbeatInterval(), polarisDiscoveryProperties.getHeartbeatInterval(), SECONDS); }, polarisDiscoveryProperties.getHeartbeatInterval(), polarisDiscoveryProperties.getHeartbeatInterval(), SECONDS);
} }
@Override
public void destroy() {
if (heartbeatExecutor != null) {
heartbeatExecutor.shutdown();
}
}
} }

@ -13,20 +13,21 @@
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * 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 * CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*
*/ */
package com.tencent.cloud.polaris.registry; package com.tencent.cloud.polaris.registry;
import java.util.List;
import com.tencent.cloud.common.metadata.StaticMetadataManager; import com.tencent.cloud.common.metadata.StaticMetadataManager;
import com.tencent.cloud.polaris.PolarisDiscoveryProperties; import com.tencent.cloud.polaris.PolarisDiscoveryProperties;
import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
import com.tencent.cloud.polaris.context.config.PolarisContextProperties; import com.tencent.cloud.polaris.context.config.PolarisContextProperties;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryAutoConfiguration; import com.tencent.cloud.polaris.discovery.PolarisDiscoveryAutoConfiguration;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryHandler; import com.tencent.cloud.polaris.discovery.PolarisDiscoveryHandler;
import com.tencent.cloud.polaris.extend.consul.ConsulContextProperties; import com.tencent.cloud.polaris.extend.consul.ConsulContextProperties;
import com.tencent.cloud.polaris.extend.nacos.NacosContextProperties; import com.tencent.cloud.polaris.extend.nacos.NacosContextProperties;
import com.tencent.cloud.rpc.enhancement.stat.config.PolarisStatProperties; import com.tencent.cloud.rpc.enhancement.stat.config.PolarisStatProperties;
import com.tencent.polaris.client.api.SDKContext;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureAfter;
@ -50,16 +51,16 @@ import org.springframework.context.annotation.Configuration;
@EnableConfigurationProperties @EnableConfigurationProperties
@ConditionalOnPolarisRegisterEnabled @ConditionalOnPolarisRegisterEnabled
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true) @ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
@AutoConfigureAfter({AutoServiceRegistrationConfiguration.class, @AutoConfigureAfter({AutoServiceRegistrationConfiguration.class, AutoServiceRegistrationAutoConfiguration.class,
AutoServiceRegistrationAutoConfiguration.class,
PolarisDiscoveryAutoConfiguration.class}) PolarisDiscoveryAutoConfiguration.class})
public class PolarisServiceRegistryAutoConfiguration { public class PolarisServiceRegistryAutoConfiguration {
@Bean @Bean
public PolarisServiceRegistry polarisServiceRegistry( public PolarisServiceRegistry polarisServiceRegistry(
PolarisDiscoveryProperties polarisDiscoveryProperties, PolarisDiscoveryHandler polarisDiscoveryHandler, PolarisDiscoveryProperties polarisDiscoveryProperties, PolarisSDKContextManager polarisSDKContextManager,
PolarisDiscoveryHandler polarisDiscoveryHandler,
StaticMetadataManager staticMetadataManager, PolarisStatProperties polarisStatProperties) { StaticMetadataManager staticMetadataManager, PolarisStatProperties polarisStatProperties) {
return new PolarisServiceRegistry(polarisDiscoveryProperties, polarisDiscoveryHandler, return new PolarisServiceRegistry(polarisDiscoveryProperties, polarisSDKContextManager, polarisDiscoveryHandler,
staticMetadataManager, polarisStatProperties); staticMetadataManager, polarisStatProperties);
} }
@ -69,12 +70,14 @@ public class PolarisServiceRegistryAutoConfiguration {
PolarisDiscoveryProperties polarisDiscoveryProperties, PolarisDiscoveryProperties polarisDiscoveryProperties,
PolarisContextProperties polarisContextProperties, PolarisContextProperties polarisContextProperties,
@Autowired(required = false) ConsulContextProperties consulContextProperties, @Autowired(required = false) ConsulContextProperties consulContextProperties,
SDKContext context, StaticMetadataManager staticMetadataManager, NacosContextProperties nacosContextProperties, PolarisSDKContextManager polarisSDKContextManager, StaticMetadataManager staticMetadataManager,
NacosContextProperties nacosContextProperties,
@Autowired(required = false) ServletWebServerApplicationContext servletWebServerApplicationContext, @Autowired(required = false) ServletWebServerApplicationContext servletWebServerApplicationContext,
@Autowired(required = false) ReactiveWebServerApplicationContext reactiveWebServerApplicationContext) { @Autowired(required = false) ReactiveWebServerApplicationContext reactiveWebServerApplicationContext,
return new PolarisRegistration(polarisDiscoveryProperties, polarisContextProperties, consulContextProperties, context, @Autowired(required = false) List<PolarisRegistrationCustomizer> registrationCustomizers) {
staticMetadataManager, nacosContextProperties, return PolarisRegistration.registration(polarisDiscoveryProperties, polarisContextProperties, consulContextProperties,
servletWebServerApplicationContext, reactiveWebServerApplicationContext); polarisSDKContextManager.getSDKContext(), staticMetadataManager, nacosContextProperties,
servletWebServerApplicationContext, reactiveWebServerApplicationContext, registrationCustomizers);
} }
@Bean @Bean
@ -82,8 +85,12 @@ public class PolarisServiceRegistryAutoConfiguration {
public PolarisAutoServiceRegistration polarisAutoServiceRegistration( public PolarisAutoServiceRegistration polarisAutoServiceRegistration(
PolarisServiceRegistry registry, PolarisServiceRegistry registry,
AutoServiceRegistrationProperties autoServiceRegistrationProperties, AutoServiceRegistrationProperties autoServiceRegistrationProperties,
PolarisRegistration registration) { PolarisRegistration registration,
return new PolarisAutoServiceRegistration(registry, autoServiceRegistrationProperties, registration); PolarisDiscoveryProperties polarisDiscoveryProperties,
PolarisSDKContextManager polarisSDKContextManager
) {
return new PolarisAutoServiceRegistration(registry, autoServiceRegistrationProperties, registration,
polarisDiscoveryProperties, polarisSDKContextManager.getAssemblyAPI());
} }
@Bean @Bean

@ -20,8 +20,6 @@ package com.tencent.cloud.polaris;
import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration; import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryHandler; import com.tencent.cloud.polaris.discovery.PolarisDiscoveryHandler;
import com.tencent.cloud.polaris.extend.consul.ConsulContextProperties; import com.tencent.cloud.polaris.extend.consul.ConsulContextProperties;
import com.tencent.polaris.api.core.ConsumerAPI;
import com.tencent.polaris.api.core.ProviderAPI;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
@ -48,8 +46,6 @@ public class DiscoveryPropertiesAutoConfigurationTest {
assertThat(context).hasSingleBean(DiscoveryPropertiesAutoConfiguration.class); assertThat(context).hasSingleBean(DiscoveryPropertiesAutoConfiguration.class);
assertThat(context).hasSingleBean(PolarisDiscoveryProperties.class); assertThat(context).hasSingleBean(PolarisDiscoveryProperties.class);
assertThat(context).hasSingleBean(ConsulContextProperties.class); assertThat(context).hasSingleBean(ConsulContextProperties.class);
assertThat(context).hasSingleBean(ProviderAPI.class);
assertThat(context).hasSingleBean(ConsumerAPI.class);
assertThat(context).hasSingleBean(PolarisDiscoveryHandler.class); assertThat(context).hasSingleBean(PolarisDiscoveryHandler.class);
assertThat(context).hasSingleBean(DiscoveryConfigModifier.class); assertThat(context).hasSingleBean(DiscoveryConfigModifier.class);
}); });

@ -85,10 +85,15 @@ public class PolarisDiscoveryPropertiesTest {
polarisDiscoveryProperties.setServiceListRefreshInterval(1000L); polarisDiscoveryProperties.setServiceListRefreshInterval(1000L);
assertThat(polarisDiscoveryProperties.getServiceListRefreshInterval()).isEqualTo(1000L); assertThat(polarisDiscoveryProperties.getServiceListRefreshInterval()).isEqualTo(1000L);
// InstanceId
polarisDiscoveryProperties.setInstanceId("test-ins-id");
assertThat(polarisDiscoveryProperties.getInstanceId()).isEqualTo("test-ins-id");
assertThat(polarisDiscoveryProperties.toString()) assertThat(polarisDiscoveryProperties.toString())
.isEqualTo("PolarisDiscoveryProperties{" .isEqualTo("PolarisDiscoveryProperties{"
+ "namespace='Test'" + "namespace='Test'"
+ ", service='java_provider_test'" + ", service='java_provider_test'"
+ ", instanceId='test-ins-id'"
+ ", token='19485a7674294e3c88dba293373c1534'" + ", token='19485a7674294e3c88dba293373c1534'"
+ ", weight=10, version='1.0.0'" + ", weight=10, version='1.0.0'"
+ ", protocol='HTTP'" + ", protocol='HTTP'"

@ -19,12 +19,12 @@
package com.tencent.cloud.polaris.discovery; package com.tencent.cloud.polaris.discovery;
import com.tencent.cloud.polaris.PolarisDiscoveryProperties; import com.tencent.cloud.polaris.PolarisDiscoveryProperties;
import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration; import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration;
import com.tencent.polaris.api.core.ConsumerAPI;
import com.tencent.polaris.api.core.ProviderAPI;
import com.tencent.polaris.test.mock.discovery.NamingServer; import com.tencent.polaris.test.mock.discovery.NamingServer;
import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
@ -49,8 +49,7 @@ public class PolarisDiscoveryAutoConfigurationTest {
.withConfiguration(AutoConfigurations.of( .withConfiguration(AutoConfigurations.of(
PolarisContextAutoConfiguration.class, PolarisContextAutoConfiguration.class,
PolarisDiscoveryAutoConfiguration.class, PolarisDiscoveryAutoConfiguration.class,
PolarisDiscoveryClientConfiguration.class, PolarisDiscoveryClientConfiguration.class))
PolarisContextAutoConfiguration.class))
.withPropertyValues("spring.application.name=" + SERVICE_PROVIDER) .withPropertyValues("spring.application.name=" + SERVICE_PROVIDER)
.withPropertyValues("server.port=" + PORT) .withPropertyValues("server.port=" + PORT)
.withPropertyValues("spring.cloud.polaris.address=grpc://127.0.0.1:10081"); .withPropertyValues("spring.cloud.polaris.address=grpc://127.0.0.1:10081");
@ -67,11 +66,14 @@ public class PolarisDiscoveryAutoConfigurationTest {
} }
} }
@BeforeEach
void setUp() {
PolarisSDKContextManager.innerDestroy();
}
@Test @Test
public void testDefaultInitialization() { public void testDefaultInitialization() {
this.contextRunner.run(context -> { this.contextRunner.run(context -> {
assertThat(context).hasSingleBean(ProviderAPI.class);
assertThat(context).hasSingleBean(ConsumerAPI.class);
assertThat(context).hasSingleBean(PolarisDiscoveryProperties.class); assertThat(context).hasSingleBean(PolarisDiscoveryProperties.class);
assertThat(context).hasSingleBean(PolarisServiceDiscovery.class); assertThat(context).hasSingleBean(PolarisServiceDiscovery.class);
}); });

@ -17,10 +17,12 @@
package com.tencent.cloud.polaris.discovery; package com.tencent.cloud.polaris.discovery;
import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration; import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration;
import com.tencent.polaris.test.mock.discovery.NamingServer; import com.tencent.polaris.test.mock.discovery.NamingServer;
import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
@ -62,6 +64,11 @@ public class PolarisDiscoveryClientConfigurationTest {
} }
} }
@BeforeEach
void setUp() {
PolarisSDKContextManager.innerDestroy();
}
@Test @Test
public void testDefaultInitialization() { public void testDefaultInitialization() {
this.contextRunner.run(context -> assertThat(context).hasSingleBean(PolarisDiscoveryClient.class)); this.contextRunner.run(context -> assertThat(context).hasSingleBean(PolarisDiscoveryClient.class));

@ -0,0 +1,65 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.polaris.discovery;
import com.tencent.cloud.polaris.PolarisDiscoveryProperties;
import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
import com.tencent.polaris.api.core.ConsumerAPI;
import com.tencent.polaris.api.exception.PolarisException;
import com.tencent.polaris.api.rpc.ServicesResponse;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
/**
* Test for {@link PolarisDiscoveryHandler}.
*
* @author Haotian Zhang
*/
@ExtendWith(MockitoExtension.class)
public class PolarisDiscoveryHandlerTest {
private PolarisDiscoveryHandler polarisDiscoveryHandler;
@BeforeEach
void setUp() {
PolarisDiscoveryProperties polarisDiscoveryProperties = mock(PolarisDiscoveryProperties.class);
doReturn(NAMESPACE_TEST).when(polarisDiscoveryProperties).getNamespace();
ConsumerAPI consumerAPI = mock(ConsumerAPI.class);
ServicesResponse servicesResponse = mock(ServicesResponse.class);
doReturn(servicesResponse).when(consumerAPI).getServices(any());
PolarisSDKContextManager polarisSDKContextManager = mock(PolarisSDKContextManager.class);
doReturn(consumerAPI).when(polarisSDKContextManager).getConsumerAPI();
polarisDiscoveryHandler = new PolarisDiscoveryHandler(polarisDiscoveryProperties, polarisSDKContextManager);
}
@Test
public void testGetServices() throws PolarisException {
ServicesResponse servicesResponse = polarisDiscoveryHandler.getServices();
assertThat(servicesResponse).isNotNull();
}
}

@ -17,11 +17,13 @@
package com.tencent.cloud.polaris.discovery.reactive; package com.tencent.cloud.polaris.discovery.reactive;
import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration; import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryClientConfiguration; import com.tencent.cloud.polaris.discovery.PolarisDiscoveryClientConfiguration;
import com.tencent.polaris.test.mock.discovery.NamingServer; import com.tencent.polaris.test.mock.discovery.NamingServer;
import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
@ -36,7 +38,7 @@ import static org.assertj.core.api.Assertions.assertThat;
/** /**
* Test for {@link PolarisReactiveDiscoveryClientConfiguration}. * Test for {@link PolarisReactiveDiscoveryClientConfiguration}.
* *
* @author Haotian Zhang * @author Haotian Zhang, youta
*/ */
public class PolarisReactiveDiscoveryClientConfigurationTest { public class PolarisReactiveDiscoveryClientConfigurationTest {
@ -65,12 +67,23 @@ public class PolarisReactiveDiscoveryClientConfigurationTest {
} }
} }
@BeforeEach
void setUp() {
PolarisSDKContextManager.innerDestroy();
}
@Test @Test
public void testDefaultInitialization() { public void testDefaultInitialization() {
this.contextRunner.run(context -> assertThat(context) this.contextRunner.run(context -> assertThat(context)
.hasSingleBean(PolarisReactiveDiscoveryClient.class)); .hasSingleBean(PolarisReactiveDiscoveryClient.class));
} }
@Test
public void shouldWorkWithDefaults() {
contextRunner.run(context -> assertThat(context).hasBean("polarisReactiveDiscoveryClientHealthIndicator"));
}
@Configuration @Configuration
@EnableAutoConfiguration @EnableAutoConfiguration
static class PolarisReactiveDiscoveryClientConfiguration { static class PolarisReactiveDiscoveryClientConfiguration {

@ -99,6 +99,6 @@ public class PolarisReactiveDiscoveryClientTest {
@Test @Test
public void testDescription() { public void testDescription() {
assertThat(client.description()).isEqualTo("Spring Cloud Tencent Polaris Reactive Discovery Client."); assertThat(client.description()).isEqualTo("Spring Cloud Tencent Polaris Reactive Discovery Client");
} }
} }

@ -16,9 +16,11 @@
*/ */
package com.tencent.cloud.polaris.endpoint; package com.tencent.cloud.polaris.endpoint;
import java.util.Collections;
import java.util.Map; import java.util.Map;
import com.tencent.cloud.polaris.PolarisDiscoveryProperties; import com.tencent.cloud.polaris.PolarisDiscoveryProperties;
import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryAutoConfiguration; import com.tencent.cloud.polaris.discovery.PolarisDiscoveryAutoConfiguration;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryClient; import com.tencent.cloud.polaris.discovery.PolarisDiscoveryClient;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryClientConfiguration; import com.tencent.cloud.polaris.discovery.PolarisDiscoveryClientConfiguration;
@ -26,6 +28,7 @@ import com.tencent.cloud.polaris.discovery.PolarisDiscoveryHandler;
import com.tencent.polaris.test.mock.discovery.NamingServer; import com.tencent.polaris.test.mock.discovery.NamingServer;
import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
@ -38,6 +41,8 @@ import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST;
import static com.tencent.polaris.test.common.Consts.PORT; import static com.tencent.polaris.test.common.Consts.PORT;
import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER; import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
/** /**
* Test for polaris discovery endpoint. * Test for polaris discovery endpoint.
@ -48,7 +53,7 @@ public class PolarisDiscoveryEndpointTest {
private static NamingServer namingServer; private static NamingServer namingServer;
private WebApplicationContextRunner contextRunner = new WebApplicationContextRunner() private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of( .withConfiguration(AutoConfigurations.of(
PolarisPropertiesConfiguration.class, PolarisPropertiesConfiguration.class,
PolarisDiscoveryClientConfiguration.class, PolarisDiscoveryClientConfiguration.class,
@ -72,6 +77,11 @@ public class PolarisDiscoveryEndpointTest {
} }
} }
@BeforeEach
void setUp() {
PolarisSDKContextManager.innerDestroy();
}
@Test @Test
public void testPolarisDiscoveryEndpoint() { public void testPolarisDiscoveryEndpoint() {
this.contextRunner.run(context -> { this.contextRunner.run(context -> {
@ -79,12 +89,17 @@ public class PolarisDiscoveryEndpointTest {
.getBean(PolarisDiscoveryProperties.class); .getBean(PolarisDiscoveryProperties.class);
DiscoveryClient discoveryClient = context DiscoveryClient discoveryClient = context
.getBean(PolarisDiscoveryClient.class); .getBean(PolarisDiscoveryClient.class);
PolarisDiscoveryHandler polarisDiscoveryHandler = context.getBean(PolarisDiscoveryHandler.class); PolarisDiscoveryHandler polarisDiscoveryHandler = context.getBean(PolarisDiscoveryHandler.class);
PolarisDiscoveryEndpoint polarisDiscoveryEndpoint = new PolarisDiscoveryEndpoint(polarisDiscoveryProperties, discoveryClient, polarisDiscoveryHandler); PolarisDiscoveryEndpoint polarisDiscoveryEndpoint = new PolarisDiscoveryEndpoint(polarisDiscoveryProperties, discoveryClient, polarisDiscoveryHandler);
Map<String, Object> mapInfo = polarisDiscoveryEndpoint.polarisDiscovery("java_provider_test"); Map<String, Object> mapInfo = polarisDiscoveryEndpoint.polarisDiscovery("java_provider_test");
assertThat(polarisDiscoveryProperties).isEqualTo(mapInfo.get("PolarisDiscoveryProperties")); assertThat(polarisDiscoveryProperties).isEqualTo(mapInfo.get("PolarisDiscoveryProperties"));
DiscoveryClient discoveryClient1 = mock(DiscoveryClient.class);
doReturn(Collections.singletonList("xx")).when(discoveryClient1).getServices();
PolarisDiscoveryEndpoint polarisDiscoveryEndpoint1 = new PolarisDiscoveryEndpoint(polarisDiscoveryProperties, discoveryClient1, polarisDiscoveryHandler);
Map<String, Object> mapInfo2 = polarisDiscoveryEndpoint1.polarisDiscovery(null);
assertThat(polarisDiscoveryProperties).isEqualTo(mapInfo2.get("PolarisDiscoveryProperties"));
}); });
} }

@ -20,8 +20,9 @@ package com.tencent.cloud.polaris.extend.consul;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import com.tencent.polaris.client.api.SDKContext; import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
import com.tencent.polaris.factory.config.global.ServerConnectorConfigImpl; import com.tencent.polaris.factory.config.global.ServerConnectorConfigImpl;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
@ -53,7 +54,12 @@ public class ConsulContextPropertiesTest {
private ConsulContextProperties consulContextProperties; private ConsulContextProperties consulContextProperties;
@Autowired @Autowired
private SDKContext sdkContext; private PolarisSDKContextManager polarisSDKContextManager;
@BeforeEach
void setUp() {
PolarisSDKContextManager.innerDestroy();
}
@Test @Test
public void testDefaultInitialization() { public void testDefaultInitialization() {
@ -67,8 +73,9 @@ public class ConsulContextPropertiesTest {
@Test @Test
public void testModify() { public void testModify() {
assertThat(sdkContext).isNotNull(); assertThat(polarisSDKContextManager).isNotNull();
com.tencent.polaris.api.config.Configuration configuration = sdkContext.getConfig(); com.tencent.polaris.api.config.Configuration configuration = polarisSDKContextManager.getSDKContext()
.getConfig();
List<ServerConnectorConfigImpl> serverConnectorConfigs = configuration.getGlobal().getServerConnectors(); List<ServerConnectorConfigImpl> serverConnectorConfigs = configuration.getGlobal().getServerConnectors();
Map<String, String> metadata = null; Map<String, String> metadata = null;
for (ServerConnectorConfigImpl serverConnectorConfig : serverConnectorConfigs) { for (ServerConnectorConfigImpl serverConnectorConfig : serverConnectorConfigs) {
@ -86,5 +93,8 @@ public class ConsulContextPropertiesTest {
@SpringBootApplication @SpringBootApplication
protected static class TestApplication { protected static class TestApplication {
static {
PolarisSDKContextManager.innerDestroy();
}
} }
} }

@ -21,8 +21,8 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
import com.tencent.polaris.api.config.plugin.DefaultPlugins; import com.tencent.polaris.api.config.plugin.DefaultPlugins;
import com.tencent.polaris.client.api.SDKContext;
import com.tencent.polaris.factory.config.global.ServerConnectorConfigImpl; import com.tencent.polaris.factory.config.global.ServerConnectorConfigImpl;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
@ -50,7 +50,7 @@ public class NacosContextPropertiesTest {
private NacosContextProperties nacosContextProperties; private NacosContextProperties nacosContextProperties;
@Autowired @Autowired
private SDKContext sdkContext; private PolarisSDKContextManager polarisSDKContextManager;
@Test @Test
public void testDefaultInitialization() { public void testDefaultInitialization() {
@ -65,8 +65,9 @@ public class NacosContextPropertiesTest {
@Test @Test
public void testModify() { public void testModify() {
assertThat(sdkContext).isNotNull(); assertThat(polarisSDKContextManager).isNotNull();
com.tencent.polaris.api.config.Configuration configuration = sdkContext.getConfig(); com.tencent.polaris.api.config.Configuration configuration = polarisSDKContextManager.getSDKContext()
.getConfig();
List<ServerConnectorConfigImpl> serverConnectorConfigs = configuration.getGlobal().getServerConnectors(); List<ServerConnectorConfigImpl> serverConnectorConfigs = configuration.getGlobal().getServerConnectors();
Optional<ServerConnectorConfigImpl> optionalServerConnectorConfig = serverConnectorConfigs.stream().filter( Optional<ServerConnectorConfigImpl> optionalServerConnectorConfig = serverConnectorConfigs.stream().filter(
item -> "nacos".equals(item.getId()) item -> "nacos".equals(item.getId())
@ -87,5 +88,9 @@ public class NacosContextPropertiesTest {
@SpringBootApplication @SpringBootApplication
protected static class TestApplication { protected static class TestApplication {
static {
PolarisSDKContextManager.innerDestroy();
}
} }
} }

@ -70,12 +70,11 @@ public class PolarisAutoServiceRegistrationTest {
@BeforeEach @BeforeEach
void setUp() { void setUp() {
doReturn(polarisDiscoveryProperties).when(registration).getPolarisProperties();
doNothing().when(serviceRegistry).register(nullable(PolarisRegistration.class)); doNothing().when(serviceRegistry).register(nullable(PolarisRegistration.class));
polarisAutoServiceRegistration = polarisAutoServiceRegistration =
new PolarisAutoServiceRegistration(serviceRegistry, autoServiceRegistrationProperties, registration); new PolarisAutoServiceRegistration(serviceRegistry, autoServiceRegistrationProperties, registration,
polarisDiscoveryProperties, null);
doReturn(environment).when(applicationContext).getEnvironment(); doReturn(environment).when(applicationContext).getEnvironment();
polarisAutoServiceRegistration.setApplicationContext(applicationContext); polarisAutoServiceRegistration.setApplicationContext(applicationContext);
@ -117,7 +116,7 @@ public class PolarisAutoServiceRegistrationTest {
doReturn("application").when(environment).getProperty(anyString(), anyString()); doReturn("application").when(environment).getProperty(anyString(), anyString());
assertThat(polarisAutoServiceRegistration.getAppName()).isEqualTo("application"); assertThat(polarisAutoServiceRegistration.getAppName()).isEqualTo("application");
doReturn(SERVICE_PROVIDER).when(polarisDiscoveryProperties).getService(); doReturn(SERVICE_PROVIDER).when(registration).getServiceId();
assertThat(polarisAutoServiceRegistration.getAppName()).isEqualTo(SERVICE_PROVIDER); assertThat(polarisAutoServiceRegistration.getAppName()).isEqualTo(SERVICE_PROVIDER);
} }
} }

@ -0,0 +1,76 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.polaris.registry;
import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryClientConfiguration;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import static com.tencent.polaris.test.common.Consts.PORT;
import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
/**
* Test for {@link PolarisRegistrationCustomizer}.
*
* @author Haotian Zhang
*/
public class PolarisRegistrationCustomizerTest {
private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(
PolarisContextAutoConfiguration.class,
PolarisServiceRegistryAutoConfiguration.class,
PolarisDiscoveryClientConfiguration.class))
.withPropertyValues("spring.application.name=" + SERVICE_PROVIDER)
.withPropertyValues("server.port=" + PORT)
.withPropertyValues("spring.cloud.polaris.address=grpc://127.0.0.1:10081");
@BeforeEach
public void setUp() {
PolarisSDKContextManager.innerDestroy();
}
@Test
public void testCustomize() {
this.contextRunner.run(context -> {
PolarisRegistrationCustomizer customizer = context.getBean(PolarisRegistrationCustomizer.class);
verify(customizer, times(1)).customize(any(PolarisRegistration.class));
});
}
@Configuration
@EnableAutoConfiguration
static class PolarisServiceRegistryAutoConfiguration {
@Bean
public PolarisRegistrationCustomizer polarisRegistrationCustomizer() {
return mock(PolarisRegistrationCustomizer.class);
}
}
}

@ -57,16 +57,13 @@ import static org.mockito.Mockito.when;
@MockitoSettings(strictness = Strictness.LENIENT) @MockitoSettings(strictness = Strictness.LENIENT)
public class PolarisRegistrationTest { public class PolarisRegistrationTest {
private static final int testLocalPort = 10086;
private NacosContextProperties nacosContextProperties; private NacosContextProperties nacosContextProperties;
private PolarisRegistration polarisRegistration1; private PolarisRegistration polarisRegistration1;
private PolarisRegistration polarisRegistration2; private PolarisRegistration polarisRegistration2;
private PolarisRegistration polarisRegistration3; private PolarisRegistration polarisRegistration3;
private PolarisRegistration polarisRegistration4; private PolarisRegistration polarisRegistration4;
private static int testLocalPort = 10086;
@BeforeEach @BeforeEach
void setUp() { void setUp() {
// mock PolarisDiscoveryProperties // mock PolarisDiscoveryProperties
@ -122,21 +119,21 @@ public class PolarisRegistrationTest {
ReactiveWebServerApplicationContext reactiveWebServerApplicationContext = mock(ReactiveWebServerApplicationContext.class); ReactiveWebServerApplicationContext reactiveWebServerApplicationContext = mock(ReactiveWebServerApplicationContext.class);
doReturn(reactiveWebServer).when(reactiveWebServerApplicationContext).getWebServer(); doReturn(reactiveWebServer).when(reactiveWebServerApplicationContext).getWebServer();
polarisRegistration1 = new PolarisRegistration(polarisDiscoveryProperties, null, consulContextProperties, polarisRegistration1 = PolarisRegistration.registration(polarisDiscoveryProperties, null, consulContextProperties,
polarisContext, staticMetadataManager, nacosContextProperties, polarisContext, staticMetadataManager, nacosContextProperties,
servletWebServerApplicationContext, null); servletWebServerApplicationContext, null, null);
polarisRegistration2 = new PolarisRegistration(polarisDiscoveryProperties, null, consulContextProperties, polarisRegistration2 = PolarisRegistration.registration(polarisDiscoveryProperties, null, consulContextProperties,
polarisContext, staticMetadataManager, nacosContextProperties, polarisContext, staticMetadataManager, nacosContextProperties,
null, reactiveWebServerApplicationContext); null, reactiveWebServerApplicationContext, null);
polarisRegistration3 = new PolarisRegistration(polarisDiscoveryProperties, null, consulContextProperties, polarisRegistration3 = PolarisRegistration.registration(polarisDiscoveryProperties, null, consulContextProperties,
polarisContext, staticMetadataManager, nacosContextProperties, polarisContext, staticMetadataManager, nacosContextProperties,
null, null); null, null, null);
polarisRegistration4 = new PolarisRegistration(polarisDiscoveryProperties, polarisContextProperties, consulContextProperties, polarisRegistration4 = PolarisRegistration.registration(polarisDiscoveryProperties, polarisContextProperties, consulContextProperties,
polarisContext, staticMetadataManager, nacosContextProperties, polarisContext, staticMetadataManager, nacosContextProperties,
null, null); null, null, null);
} }
@Test @Test
@ -187,11 +184,6 @@ public class PolarisRegistrationTest {
assertThat(metadata.get("key1")).isEqualTo("value1"); assertThat(metadata.get("key1")).isEqualTo("value1");
} }
@Test
public void testGetPolarisProperties() {
assertThat(polarisRegistration1.getPolarisProperties()).isNotNull();
}
@Test @Test
public void testIsRegisterEnabled() { public void testIsRegisterEnabled() {
assertThat(polarisRegistration1.isRegisterEnabled()).isTrue(); assertThat(polarisRegistration1.isRegisterEnabled()).isTrue();

@ -17,12 +17,14 @@
package com.tencent.cloud.polaris.registry; package com.tencent.cloud.polaris.registry;
import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration; import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryAutoConfiguration; import com.tencent.cloud.polaris.discovery.PolarisDiscoveryAutoConfiguration;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryClientConfiguration; import com.tencent.cloud.polaris.discovery.PolarisDiscoveryClientConfiguration;
import com.tencent.polaris.test.mock.discovery.NamingServer; import com.tencent.polaris.test.mock.discovery.NamingServer;
import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
@ -65,6 +67,11 @@ public class PolarisServiceRegistryAutoConfigurationTest {
} }
} }
@BeforeEach
void setUp() {
PolarisSDKContextManager.innerDestroy();
}
@Test @Test
public void testDefaultInitialization() { public void testDefaultInitialization() {
this.contextRunner.run(context -> { this.contextRunner.run(context -> {

@ -17,6 +17,7 @@
package com.tencent.cloud.polaris.registry; package com.tencent.cloud.polaris.registry;
import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration; import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryAutoConfiguration; import com.tencent.cloud.polaris.discovery.PolarisDiscoveryAutoConfiguration;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryClientConfiguration; import com.tencent.cloud.polaris.discovery.PolarisDiscoveryClientConfiguration;
@ -24,6 +25,7 @@ import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.test.mock.discovery.NamingServer; import com.tencent.polaris.test.mock.discovery.NamingServer;
import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.mockito.Mockito; import org.mockito.Mockito;
@ -89,6 +91,11 @@ public class PolarisServiceRegistryTest {
} }
} }
@BeforeEach
void setUp() {
PolarisSDKContextManager.innerDestroy();
}
@Test @Test
public void testRegister() { public void testRegister() {
this.contextRunner.run(context -> { this.contextRunner.run(context -> {

@ -20,6 +20,8 @@ package com.tencent.cloud.polaris.ribbon;
import com.netflix.client.config.DefaultClientConfigImpl; import com.netflix.client.config.DefaultClientConfigImpl;
import com.netflix.client.config.IClientConfig; import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.ServerList; import com.netflix.loadbalancer.ServerList;
import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
@ -40,6 +42,11 @@ public class PolarisRibbonServerListConfigurationTest {
private final ApplicationContextRunner applicationContextRunner = new ApplicationContextRunner(); private final ApplicationContextRunner applicationContextRunner = new ApplicationContextRunner();
@BeforeAll
static void beforeAll() {
PolarisSDKContextManager.innerDestroy();
}
@Test @Test
public void testDefaultInitialization() { public void testDefaultInitialization() {
this.applicationContextRunner this.applicationContextRunner

@ -22,6 +22,7 @@ import java.util.List;
import com.netflix.client.config.IClientConfig; import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.Server; import com.netflix.loadbalancer.Server;
import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration; import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryAutoConfiguration; import com.tencent.cloud.polaris.discovery.PolarisDiscoveryAutoConfiguration;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryClientConfiguration; import com.tencent.cloud.polaris.discovery.PolarisDiscoveryClientConfiguration;
@ -60,8 +61,7 @@ public class PolarisServerListTest {
PolarisContextAutoConfiguration.class, PolarisContextAutoConfiguration.class,
PolarisServerListTest.PolarisPropertiesConfiguration.class, PolarisServerListTest.PolarisPropertiesConfiguration.class,
PolarisDiscoveryClientConfiguration.class, PolarisDiscoveryClientConfiguration.class,
PolarisDiscoveryAutoConfiguration.class, PolarisDiscoveryAutoConfiguration.class))
PolarisContextAutoConfiguration.class))
.withPropertyValues("spring.application.name=" + SERVICE_PROVIDER) .withPropertyValues("spring.application.name=" + SERVICE_PROVIDER)
.withPropertyValues("server.port=" + PORT) .withPropertyValues("server.port=" + PORT)
.withPropertyValues("spring.cloud.polaris.address=grpc://127.0.0.1:10081") .withPropertyValues("spring.cloud.polaris.address=grpc://127.0.0.1:10081")
@ -78,6 +78,7 @@ public class PolarisServerListTest {
namingServer.getNamingService().addService(new ServiceKey(NAMESPACE_TEST, SERVICE_PROVIDER)); namingServer.getNamingService().addService(new ServiceKey(NAMESPACE_TEST, SERVICE_PROVIDER));
} }
@AfterAll @AfterAll
static void afterAll() { static void afterAll() {
if (null != namingServer) { if (null != namingServer) {
@ -91,6 +92,7 @@ public class PolarisServerListTest {
iClientConfig = mock(IClientConfig.class); iClientConfig = mock(IClientConfig.class);
when(iClientConfig.getClientName()).thenReturn(SERVICE_PROVIDER); when(iClientConfig.getClientName()).thenReturn(SERVICE_PROVIDER);
PolarisSDKContextManager.innerDestroy();
} }
@Test @Test

@ -18,6 +18,7 @@
package com.tencent.cloud.polaris.ratelimit.config; package com.tencent.cloud.polaris.ratelimit.config;
import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
import com.tencent.cloud.polaris.context.ServiceRuleManager; import com.tencent.cloud.polaris.context.ServiceRuleManager;
import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration; import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration;
import com.tencent.cloud.polaris.ratelimit.filter.QuotaCheckReactiveFilter; import com.tencent.cloud.polaris.ratelimit.filter.QuotaCheckReactiveFilter;
@ -27,9 +28,6 @@ import com.tencent.cloud.polaris.ratelimit.resolver.RateLimitRuleArgumentServlet
import com.tencent.cloud.polaris.ratelimit.spi.PolarisRateLimiterLabelReactiveResolver; import com.tencent.cloud.polaris.ratelimit.spi.PolarisRateLimiterLabelReactiveResolver;
import com.tencent.cloud.polaris.ratelimit.spi.PolarisRateLimiterLabelServletResolver; import com.tencent.cloud.polaris.ratelimit.spi.PolarisRateLimiterLabelServletResolver;
import com.tencent.cloud.polaris.ratelimit.spi.PolarisRateLimiterLimitedFallback; import com.tencent.cloud.polaris.ratelimit.spi.PolarisRateLimiterLimitedFallback;
import com.tencent.polaris.client.api.SDKContext;
import com.tencent.polaris.ratelimit.api.core.LimitAPI;
import com.tencent.polaris.ratelimit.factory.LimitAPIFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureAfter;
@ -58,12 +56,6 @@ import static javax.servlet.DispatcherType.REQUEST;
@ConditionalOnPolarisRateLimitEnabled @ConditionalOnPolarisRateLimitEnabled
public class PolarisRateLimitAutoConfiguration { public class PolarisRateLimitAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public LimitAPI limitAPI(SDKContext polarisContext) {
return LimitAPIFactory.createLimitAPIByContext(polarisContext);
}
/** /**
* Create when web application type is SERVLET. * Create when web application type is SERVLET.
*/ */
@ -79,11 +71,12 @@ public class PolarisRateLimitAutoConfiguration {
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public QuotaCheckServletFilter quotaCheckFilter(LimitAPI limitAPI, public QuotaCheckServletFilter quotaCheckFilter(PolarisSDKContextManager polarisSDKContextManager,
PolarisRateLimitProperties polarisRateLimitProperties, PolarisRateLimitProperties polarisRateLimitProperties,
RateLimitRuleArgumentServletResolver rateLimitRuleArgumentResolver, RateLimitRuleArgumentServletResolver rateLimitRuleArgumentResolver,
@Autowired(required = false) PolarisRateLimiterLimitedFallback polarisRateLimiterLimitedFallback) { @Autowired(required = false) PolarisRateLimiterLimitedFallback polarisRateLimiterLimitedFallback) {
return new QuotaCheckServletFilter(limitAPI, polarisRateLimitProperties, rateLimitRuleArgumentResolver, polarisRateLimiterLimitedFallback); return new QuotaCheckServletFilter(polarisSDKContextManager.getLimitAPI(), polarisRateLimitProperties,
rateLimitRuleArgumentResolver, polarisRateLimiterLimitedFallback);
} }
@Bean @Bean
@ -113,11 +106,12 @@ public class PolarisRateLimitAutoConfiguration {
} }
@Bean @Bean
public QuotaCheckReactiveFilter quotaCheckReactiveFilter(LimitAPI limitAPI, public QuotaCheckReactiveFilter quotaCheckReactiveFilter(PolarisSDKContextManager polarisSDKContextManager,
PolarisRateLimitProperties polarisRateLimitProperties, PolarisRateLimitProperties polarisRateLimitProperties,
RateLimitRuleArgumentReactiveResolver rateLimitRuleArgumentResolver, RateLimitRuleArgumentReactiveResolver rateLimitRuleArgumentResolver,
@Nullable PolarisRateLimiterLimitedFallback polarisRateLimiterLimitedFallback) { @Nullable PolarisRateLimiterLimitedFallback polarisRateLimiterLimitedFallback) {
return new QuotaCheckReactiveFilter(limitAPI, polarisRateLimitProperties, rateLimitRuleArgumentResolver, polarisRateLimiterLimitedFallback); return new QuotaCheckReactiveFilter(polarisSDKContextManager.getLimitAPI(), polarisRateLimitProperties,
rateLimitRuleArgumentResolver, polarisRateLimiterLimitedFallback);
} }
} }
} }

@ -15,12 +15,17 @@
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*/ */
package com.tencent.cloud.polaris.ratelimit.controller; package com.tencent.cloud.polaris.context;
import com.tencent.cloud.polaris.ratelimit.config.PolarisRateLimitProperties;
import com.tencent.cloud.polaris.ratelimit.filter.QuotaCheckServletFilter;
import com.tencent.cloud.polaris.ratelimit.resolver.RateLimitRuleArgumentServletResolver;
import com.tencent.cloud.polaris.ratelimit.spi.PolarisRateLimiterLimitedFallback;
import com.tencent.polaris.api.pojo.ServiceKey; import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.ratelimit.api.core.LimitAPI; import com.tencent.polaris.ratelimit.api.core.LimitAPI;
import com.tencent.polaris.ratelimit.api.rpc.QuotaResponse; import com.tencent.polaris.ratelimit.api.rpc.QuotaResponse;
import com.tencent.polaris.ratelimit.api.rpc.QuotaResultCode; import com.tencent.polaris.ratelimit.api.rpc.QuotaResultCode;
import com.tencent.polaris.ratelimit.factory.LimitAPIFactory;
import com.tencent.polaris.test.mock.discovery.NamingServer; import com.tencent.polaris.test.mock.discovery.NamingServer;
import com.tencent.polaris.test.mock.discovery.NamingService; import com.tencent.polaris.test.mock.discovery.NamingService;
import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterAll;
@ -36,6 +41,7 @@ import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.web.server.LocalServerPort; import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.web.client.HttpClientErrorException.TooManyRequests; import org.springframework.web.client.HttpClientErrorException.TooManyRequests;
import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestClientException;
@ -144,5 +150,19 @@ public class CalleeControllerTests {
return new RestTemplate(); return new RestTemplate();
} }
@Bean
public LimitAPI limitAPI(PolarisSDKContextManager polarisSDKContextManager) {
return LimitAPIFactory.createLimitAPIByContext(polarisSDKContextManager.getSDKContext());
}
@Bean
@Primary
public QuotaCheckServletFilter quotaCheckFilter(LimitAPI limitAPI,
PolarisRateLimitProperties polarisRateLimitProperties,
RateLimitRuleArgumentServletResolver rateLimitRuleArgumentResolver,
@Autowired(required = false) PolarisRateLimiterLimitedFallback polarisRateLimiterLimitedFallback) {
return new QuotaCheckServletFilter(limitAPI, polarisRateLimitProperties,
rateLimitRuleArgumentResolver, polarisRateLimiterLimitedFallback);
}
} }
} }

@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*/ */
package com.tencent.cloud.polaris.ratelimit.controller; package com.tencent.cloud.polaris.context;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;

@ -22,7 +22,6 @@ import com.tencent.cloud.polaris.ratelimit.filter.QuotaCheckReactiveFilter;
import com.tencent.cloud.polaris.ratelimit.filter.QuotaCheckServletFilter; import com.tencent.cloud.polaris.ratelimit.filter.QuotaCheckServletFilter;
import com.tencent.cloud.polaris.ratelimit.resolver.RateLimitRuleArgumentReactiveResolver; import com.tencent.cloud.polaris.ratelimit.resolver.RateLimitRuleArgumentReactiveResolver;
import com.tencent.cloud.polaris.ratelimit.resolver.RateLimitRuleArgumentServletResolver; import com.tencent.cloud.polaris.ratelimit.resolver.RateLimitRuleArgumentServletResolver;
import com.tencent.polaris.ratelimit.api.core.LimitAPI;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
@ -55,7 +54,6 @@ public class PolarisRateLimitAutoConfigurationTest {
PolarisRateLimitProperties.class, PolarisRateLimitProperties.class,
PolarisRateLimitAutoConfiguration.class)) PolarisRateLimitAutoConfiguration.class))
.run(context -> { .run(context -> {
assertThat(context).hasSingleBean(LimitAPI.class);
assertThat(context).doesNotHaveBean(RateLimitRuleArgumentServletResolver.class); assertThat(context).doesNotHaveBean(RateLimitRuleArgumentServletResolver.class);
assertThat(context).doesNotHaveBean(RateLimitRuleArgumentReactiveResolver.class); assertThat(context).doesNotHaveBean(RateLimitRuleArgumentReactiveResolver.class);
assertThat(context).doesNotHaveBean(PolarisRateLimitAutoConfiguration.QuotaCheckFilterConfig.class); assertThat(context).doesNotHaveBean(PolarisRateLimitAutoConfiguration.QuotaCheckFilterConfig.class);
@ -73,7 +71,6 @@ public class PolarisRateLimitAutoConfigurationTest {
PolarisRateLimitProperties.class, PolarisRateLimitProperties.class,
PolarisRateLimitAutoConfiguration.class)) PolarisRateLimitAutoConfiguration.class))
.run(context -> { .run(context -> {
assertThat(context).hasSingleBean(LimitAPI.class);
assertThat(context).hasSingleBean(RateLimitRuleArgumentServletResolver.class); assertThat(context).hasSingleBean(RateLimitRuleArgumentServletResolver.class);
assertThat(context).hasSingleBean(PolarisRateLimitAutoConfiguration.QuotaCheckFilterConfig.class); assertThat(context).hasSingleBean(PolarisRateLimitAutoConfiguration.QuotaCheckFilterConfig.class);
assertThat(context).hasSingleBean(QuotaCheckServletFilter.class); assertThat(context).hasSingleBean(QuotaCheckServletFilter.class);
@ -91,7 +88,6 @@ public class PolarisRateLimitAutoConfigurationTest {
PolarisRateLimitProperties.class, PolarisRateLimitProperties.class,
PolarisRateLimitAutoConfiguration.class)) PolarisRateLimitAutoConfiguration.class))
.run(context -> { .run(context -> {
assertThat(context).hasSingleBean(LimitAPI.class);
assertThat(context).doesNotHaveBean(RateLimitRuleArgumentServletResolver.class); assertThat(context).doesNotHaveBean(RateLimitRuleArgumentServletResolver.class);
assertThat(context).hasSingleBean(RateLimitRuleArgumentReactiveResolver.class); assertThat(context).hasSingleBean(RateLimitRuleArgumentReactiveResolver.class);
assertThat(context).doesNotHaveBean(PolarisRateLimitAutoConfiguration.QuotaCheckFilterConfig.class); assertThat(context).doesNotHaveBean(PolarisRateLimitAutoConfiguration.QuotaCheckFilterConfig.class);

@ -23,6 +23,7 @@ import java.util.List;
import com.netflix.client.config.IClientConfig; import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule; import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.tencent.cloud.common.util.BeanFactoryUtils; import com.tencent.cloud.common.util.BeanFactoryUtils;
import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
import com.tencent.cloud.polaris.loadbalancer.config.PolarisLoadBalancerProperties; import com.tencent.cloud.polaris.loadbalancer.config.PolarisLoadBalancerProperties;
import com.tencent.cloud.polaris.router.PolarisLoadBalancerCompositeRule; import com.tencent.cloud.polaris.router.PolarisLoadBalancerCompositeRule;
import com.tencent.cloud.polaris.router.spi.RouterRequestInterceptor; import com.tencent.cloud.polaris.router.spi.RouterRequestInterceptor;
@ -47,7 +48,8 @@ public class PolarisLoadBalancerCompositeRuleBeanPostProcessor implements BeanPo
@Override @Override
public Object postProcessBeforeInitialization(@NonNull Object bean, @NonNull String beanName) throws BeansException { public Object postProcessBeforeInitialization(@NonNull Object bean, @NonNull String beanName) throws BeansException {
if (bean instanceof AbstractLoadBalancerRule) { if (bean instanceof AbstractLoadBalancerRule) {
RouterAPI routerAPI = beanFactory.getBean(RouterAPI.class); PolarisSDKContextManager polarisSDKContextManager = beanFactory.getBean(PolarisSDKContextManager.class);
RouterAPI routerAPI = polarisSDKContextManager.getRouterAPI();
PolarisLoadBalancerProperties polarisLoadBalancerProperties = beanFactory.getBean(PolarisLoadBalancerProperties.class); PolarisLoadBalancerProperties polarisLoadBalancerProperties = beanFactory.getBean(PolarisLoadBalancerProperties.class);
IClientConfig iClientConfig = beanFactory.getBean(IClientConfig.class); IClientConfig iClientConfig = beanFactory.getBean(IClientConfig.class);
List<RouterRequestInterceptor> requestInterceptors = BeanFactoryUtils.getBeans(beanFactory, RouterRequestInterceptor.class); List<RouterRequestInterceptor> requestInterceptors = BeanFactoryUtils.getBeans(beanFactory, RouterRequestInterceptor.class);

@ -27,6 +27,8 @@ import com.netflix.loadbalancer.RandomRule;
import com.netflix.loadbalancer.RoundRobinRule; import com.netflix.loadbalancer.RoundRobinRule;
import com.netflix.loadbalancer.ZoneAvoidanceRule; import com.netflix.loadbalancer.ZoneAvoidanceRule;
import com.tencent.cloud.common.util.ReflectionUtils; import com.tencent.cloud.common.util.ReflectionUtils;
import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration;
import com.tencent.cloud.polaris.loadbalancer.config.PolarisLoadBalancerProperties; import com.tencent.cloud.polaris.loadbalancer.config.PolarisLoadBalancerProperties;
import com.tencent.cloud.polaris.router.PolarisLoadBalancerCompositeRule; import com.tencent.cloud.polaris.router.PolarisLoadBalancerCompositeRule;
import com.tencent.cloud.polaris.router.config.RibbonConfiguration; import com.tencent.cloud.polaris.router.config.RibbonConfiguration;
@ -36,6 +38,7 @@ import com.tencent.cloud.polaris.router.spi.RouterRequestInterceptor;
import com.tencent.polaris.client.api.SDKContext; import com.tencent.polaris.client.api.SDKContext;
import com.tencent.polaris.router.api.core.RouterAPI; import com.tencent.polaris.router.api.core.RouterAPI;
import com.tencent.polaris.router.client.api.DefaultRouterAPI; import com.tencent.polaris.router.client.api.DefaultRouterAPI;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
@ -62,10 +65,16 @@ public class PolarisLoadBalancerCompositeRuleBeanPostProcessorTest {
private static final String SERVICE_2 = "service2"; private static final String SERVICE_2 = "service2";
@BeforeEach
void setUp() {
PolarisSDKContextManager.innerDestroy();
}
@Test @Test
public void test1() { public void test1() {
ApplicationContextRunner contextRunner = new ApplicationContextRunner() ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of( .withConfiguration(AutoConfigurations.of(
PolarisContextAutoConfiguration.class,
RibbonDefaultConfig.class, RibbonDefaultConfig.class,
PolarisRibbonTest.class, PolarisRibbonTest.class,
RibbonAutoConfiguration.class, RibbonAutoConfiguration.class,
@ -86,7 +95,8 @@ public class PolarisLoadBalancerCompositeRuleBeanPostProcessorTest {
@Test @Test
public void test2() { public void test2() {
ApplicationContextRunner contextRunner = new ApplicationContextRunner() ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(RibbonDefaultConfig.class, PolarisRibbonTest.class, RibbonAutoConfiguration.class)) .withConfiguration(AutoConfigurations.of(PolarisContextAutoConfiguration.class,
RibbonDefaultConfig.class, PolarisRibbonTest.class, RibbonAutoConfiguration.class))
.withPropertyValues("spring.cloud.polaris.loadbalancer.strategy = random"); .withPropertyValues("spring.cloud.polaris.loadbalancer.strategy = random");
contextRunner.run(context -> { contextRunner.run(context -> {
SpringClientFactory springClientFactory = context.getBean(SpringClientFactory.class); SpringClientFactory springClientFactory = context.getBean(SpringClientFactory.class);
@ -102,7 +112,8 @@ public class PolarisLoadBalancerCompositeRuleBeanPostProcessorTest {
@Test @Test
public void test3() { public void test3() {
ApplicationContextRunner contextRunner = new ApplicationContextRunner() ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(RibbonDefaultConfig.class, PolarisRibbonTest.class, RibbonAutoConfiguration.class)) .withConfiguration(AutoConfigurations.of(PolarisContextAutoConfiguration.class,
RibbonDefaultConfig.class, PolarisRibbonTest.class, RibbonAutoConfiguration.class))
.withPropertyValues("service1.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RoundRobinRule"); .withPropertyValues("service1.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RoundRobinRule");
contextRunner.run(context -> { contextRunner.run(context -> {
SpringClientFactory springClientFactory = context.getBean(SpringClientFactory.class); SpringClientFactory springClientFactory = context.getBean(SpringClientFactory.class);
@ -125,7 +136,8 @@ public class PolarisLoadBalancerCompositeRuleBeanPostProcessorTest {
@Test @Test
public void test4() { public void test4() {
ApplicationContextRunner contextRunner = new ApplicationContextRunner() ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(CustomRibbonConfig.class, PolarisRibbonTest.class, RibbonAutoConfiguration.class)); .withConfiguration(AutoConfigurations.of(PolarisContextAutoConfiguration.class,
CustomRibbonConfig.class, PolarisRibbonTest.class, RibbonAutoConfiguration.class));
contextRunner.run(context -> { contextRunner.run(context -> {
SpringClientFactory springClientFactory = context.getBean(SpringClientFactory.class); SpringClientFactory springClientFactory = context.getBean(SpringClientFactory.class);

@ -48,11 +48,6 @@ public class MetadataContext {
*/ */
public static final String FRAGMENT_DISPOSABLE = "disposable"; public static final String FRAGMENT_DISPOSABLE = "disposable";
/**
* load balancer context.
*/
public static final String FRAGMENT_LOAD_BALANCER = "loadbalancer";
/** /**
* upstream disposable Context. * upstream disposable Context.
*/ */
@ -115,8 +110,12 @@ public class MetadataContext {
private final Map<String, Map<String, String>> fragmentContexts; private final Map<String, Map<String, String>> fragmentContexts;
private final Map<String, Object> loadbalancerMetadata;
public MetadataContext() { public MetadataContext() {
this.fragmentContexts = new ConcurrentHashMap<>(); this.fragmentContexts = new ConcurrentHashMap<>();
this.loadbalancerMetadata = new ConcurrentHashMap<>();
} }
public Map<String, String> getDisposableMetadata() { public Map<String, String> getDisposableMetadata() {
@ -148,8 +147,8 @@ public class MetadataContext {
return this.getFragmentContext(MetadataContext.FRAGMENT_RAW_TRANSHEADERS_KV); return this.getFragmentContext(MetadataContext.FRAGMENT_RAW_TRANSHEADERS_KV);
} }
public Map<String, String> getLoadbalancerMetadata() { public Map<String, Object> getLoadbalancerMetadata() {
return this.getFragmentContext(FRAGMENT_LOAD_BALANCER); return this.loadbalancerMetadata;
} }
public void setTransitiveMetadata(Map<String, String> transitiveMetadata) { public void setTransitiveMetadata(Map<String, String> transitiveMetadata) {
@ -172,8 +171,8 @@ public class MetadataContext {
this.putContext(FRAGMENT_RAW_TRANSHEADERS, key, value); this.putContext(FRAGMENT_RAW_TRANSHEADERS, key, value);
} }
public void setLoadbalancer(String key, String value) { public void setLoadbalancer(String key, Object value) {
this.putContext(FRAGMENT_LOAD_BALANCER, key, value); this.loadbalancerMetadata.put(key, value);
} }
public Map<String, String> getFragmentContext(String fragment) { public Map<String, String> getFragmentContext(String fragment) {

@ -78,6 +78,11 @@
<groupId>com.tencent.cloud</groupId> <groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-gateway-plugin</artifactId> <artifactId>spring-cloud-tencent-gateway-plugin</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-discovery-adapter-plugin</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>

@ -70,11 +70,11 @@
</developers> </developers>
<properties> <properties>
<revision>1.11.7-Hoxton.SR12</revision> <revision>1.12.0-Hoxton.SR12-SNAPSHOT</revision>
<!-- Dependencies --> <!-- Dependencies -->
<polaris.version>1.12.9</polaris.version> <polaris.version>1.14.0-SNAPSHOT</polaris.version>
<guava.version>31.0.1-jre</guava.version> <guava.version>32.0.1-jre</guava.version>
<logback.version>1.2.11</logback.version> <logback.version>1.2.11</logback.version>
<mocktio.version>4.5.1</mocktio.version> <mocktio.version>4.5.1</mocktio.version>
<byte-buddy.version>1.12.10</byte-buddy.version> <byte-buddy.version>1.12.10</byte-buddy.version>
@ -168,6 +168,12 @@
</dependency> </dependency>
<!-- spring cloud tencent plugins --> <!-- spring cloud tencent plugins -->
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-discovery-adapter-plugin</artifactId>
<version>${revision}</version>
</dependency>
<dependency> <dependency>
<groupId>com.tencent.cloud</groupId> <groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-featureenv-plugin</artifactId> <artifactId>spring-cloud-tencent-featureenv-plugin</artifactId>
@ -269,6 +275,7 @@
<version>${system-stubs-jupiter.version}</version> <version>${system-stubs-jupiter.version}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>

@ -5,7 +5,7 @@ spring:
name: MetadataBackendService name: MetadataBackendService
cloud: cloud:
polaris: polaris:
address: grpc://183.47.111.80:8091 address: grpc://119.91.66.223:8091
namespace: default namespace: default
enabled: true enabled: true
discovery: discovery:

@ -5,7 +5,7 @@ spring:
name: MetadataFrontendService name: MetadataFrontendService
cloud: cloud:
polaris: polaris:
address: grpc://183.47.111.80:8091 address: grpc://119.91.66.223:8091
namespace: default namespace: default
enabled: true enabled: true
discovery: discovery:

@ -5,7 +5,7 @@ spring:
name: MetadataMiddleService name: MetadataMiddleService
cloud: cloud:
polaris: polaris:
address: grpc://183.47.111.80:8091 address: grpc://119.91.66.223:8091
namespace: default namespace: default
enabled: true enabled: true
discovery: discovery:

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>multiple-discovery-nacos-example</artifactId>
<groupId>com.tencent.cloud</groupId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>nacos-callee-service-a</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,34 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.multiple.discovery.nacos;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* Circuit breaker example callee application.
*
* @author Haotian Zhang
*/
@SpringBootApplication
public class NacosCalleeServiceA {
public static void main(String[] args) {
SpringApplication.run(NacosCalleeServiceA.class, args);
}
}

@ -13,31 +13,38 @@
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * 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 * CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*
*/ */
package com.tencent.cloud.rpc.enhancement.resttemplate; package com.tencent.cloud.multiple.discovery.nacos;
import org.aspectj.lang.ProceedingJoinPoint; import org.springframework.web.bind.annotation.GetMapping;
import org.aspectj.lang.annotation.Around; import org.springframework.web.bind.annotation.RequestMapping;
import org.aspectj.lang.annotation.Aspect; import org.springframework.web.bind.annotation.RestController;
import org.aspectj.lang.annotation.Pointcut;
/** /**
* Intercept for BlockingLoadBalancerClient, put host and port to thread local. * Service B Controller.
* *
* @author lepdou 2022-09-05 * @author Haotian Zhang
*/ */
@Aspect @RestController
public class BlockingLoadBalancerClientAspect { @RequestMapping("/example/service/b")
public class NacosCalleeServiceAController {
@Pointcut("execution(public * org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient.reconstructURI(..)) ")
public void pointcut() {
/**
* Get service information.
*
* @return service information
*/
@GetMapping("/info")
public String info() {
return "hello world ! I'm a service B1";
} }
@Around("pointcut()") @GetMapping("/health")
public Object invoke(ProceedingJoinPoint joinPoint) throws Throwable { public String health() {
LoadBalancerClientAspectUtils.extractLoadBalancerResult(joinPoint); System.out.println("health check: 200 instance");
return joinPoint.proceed(); return "hello world ! I'm a service B1";
} }
} }

@ -0,0 +1,16 @@
server:
port: 48082
spring:
application:
name: NacosCalleeService
cloud:
polaris:
address: grpc://119.91.66.223:8091
namespace: default
enabled: true
stat:
enabled: true
port: 28083
nacos:
discovery:
server-addr: 127.0.0.1:8848

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>multiple-discovery-nacos-example</artifactId>
<groupId>com.tencent.cloud</groupId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>nacos-callee-service-b</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,34 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.multiple.discovery.nacos;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* Circuit breaker example callee application.
*
* @author Haotian Zhang
*/
@SpringBootApplication
public class NacosCalleeServiceB {
public static void main(String[] args) {
SpringApplication.run(NacosCalleeServiceB.class, args);
}
}

@ -0,0 +1,54 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
*/
package com.tencent.cloud.multiple.discovery.nacos;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
/**
* Service B Controller.
*
* @author Haotian Zhang
*/
@RestController
@RequestMapping("/example/service/b")
public class NacosCalleeServiceBController {
/**
* Get service information.
*
* @return service information
*/
@GetMapping("/info")
@ResponseStatus(code = HttpStatus.BAD_GATEWAY)
public String info() {
return "BAD_GATEWAY ! from service B2";
}
@GetMapping("/health")
@ResponseStatus(value = HttpStatus.BAD_GATEWAY, reason = "failed for call my service")
public String health() {
System.out.println("health check: 502 instance");
return "hello world ! I'm a service B1";
}
}

@ -0,0 +1,17 @@
server:
port: 48081
spring:
application:
name: NacosCalleeService
cloud:
polaris:
address: grpc://119.91.66.223:8091
namespace: default
enabled: true
stat:
enabled: true
port: 28083
nacos:
discovery:
server-addr: 127.0.0.1:8848

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>multiple-discovery-nacos-example</artifactId>
<groupId>com.tencent.cloud</groupId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>nacos-discovery-caller</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-router</artifactId>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-discovery-adapter-plugin</artifactId>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-circuitbreaker</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,36 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.multiple.discovery.nacos;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
/**
* Circuit breaker example callee application.
*
* @author Haotian Zhang
*/
@SpringBootApplication
@EnableFeignClients
public class NacosCallerService {
public static void main(String[] args) {
SpringApplication.run(NacosCallerService.class, args);
}
}

@ -0,0 +1,42 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.multiple.discovery.nacos;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* NacosCallerServiceController.
*
* @author Haotian Zhang
*/
@RestController
@RequestMapping("/example/service/a")
public class NacosCallerServiceController {
@Autowired
private ProviderB polarisServiceB;
@GetMapping("/getBServiceInfo")
public String getBServiceInfoFallbackFromCode() {
return polarisServiceB.info();
}
}

@ -0,0 +1,38 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.multiple.discovery.nacos;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
/**
* Circuit breaker example callee provider.
*
* @author Haotian Zhang
*/
@FeignClient(name = "NacosCalleeService")
public interface ProviderB {
/**
* Get info of service B.
*
* @return info of service B
*/
@GetMapping("/example/service/b/info")
String info();
}

@ -0,0 +1,27 @@
server:
port: 48080
spring:
application:
name: NacosCallerService
cloud:
polaris:
address: grpc://119.91.66.223:8091
namespace: default
enabled: true
loadbalancer:
enabled: true
discoveryType: Nacos
circuitbreaker:
enabled: true
nacos:
discovery:
server-addr: 127.0.0.1:8848
feign:
hystrix:
enabled: true
logging:
level:
root: info
com.tencent.cloud: debug

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>multiple-discovery-example</artifactId>
<groupId>com.tencent.cloud</groupId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>multiple-discovery-nacos-example</artifactId>
<packaging>pom</packaging>
<modules>
<module>nacos-callee-service-a</module>
<module>nacos-callee-service-b</module>
<module>nacos-discovery-caller</module>
</modules>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2.2.9.RELEASE</version>
</dependency>
</dependencies>
</project>

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-tencent-examples</artifactId>
<groupId>com.tencent.cloud</groupId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>multiple-discovery-example</artifactId>
<name>Spring Cloud Starter Tencent Multiple Discovery Example</name>
<packaging>pom</packaging>
<modules>
<module>multiple-discovery-nacos-example</module>
</modules>
</project>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save