feat:upgrade api circuit breaker. (#1442)

* feat:upgrade api circuit breaker.

* feat:upgrade api circuit breaker.

* feat:upgrade api circuit breaker.

* update junit test.
pull/1445/head
Haotian Zhang 3 months ago committed by GitHub
parent b39621a339
commit b0be2c2a97
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -34,3 +34,4 @@
- [fix: fix TSF context bootstrap configuration](https://github.com/Tencent/spring-cloud-tencent/pull/1424) - [fix: fix TSF context bootstrap configuration](https://github.com/Tencent/spring-cloud-tencent/pull/1424)
- [fix: fix PolarisCircuitBreakerConfiguration not clear when gateway invoke by wildcard apis](https://github.com/Tencent/spring-cloud-tencent/pull/1426) - [fix: fix PolarisCircuitBreakerConfiguration not clear when gateway invoke by wildcard apis](https://github.com/Tencent/spring-cloud-tencent/pull/1426)
- [fix:fix actuator name warning from #1428 .](https://github.com/Tencent/spring-cloud-tencent/pull/1431) - [fix:fix actuator name warning from #1428 .](https://github.com/Tencent/spring-cloud-tencent/pull/1431)
- [feat:upgrade api circuit breaker.](https://github.com/Tencent/spring-cloud-tencent/pull/1442)

@ -89,7 +89,7 @@
<properties> <properties>
<!-- Project revision --> <!-- Project revision -->
<revision>2.0.0.0-2023.0.0-RC2</revision> <revision>2.0.0.0-2023.0.0-SNAPSHOT</revision>
<!-- Spring Framework --> <!-- Spring Framework -->
<spring.framework.version>6.1.6</spring.framework.version> <spring.framework.version>6.1.6</spring.framework.version>

@ -118,12 +118,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>

@ -53,7 +53,8 @@ public class PolarisCircuitBreaker implements CircuitBreaker {
public PolarisCircuitBreaker(PolarisCircuitBreakerConfigBuilder.PolarisCircuitBreakerConfiguration conf, public PolarisCircuitBreaker(PolarisCircuitBreakerConfigBuilder.PolarisCircuitBreakerConfiguration conf,
ConsumerAPI consumerAPI, ConsumerAPI consumerAPI,
CircuitBreakAPI circuitBreakAPI) { CircuitBreakAPI circuitBreakAPI) {
FunctionalDecoratorRequest makeDecoratorRequest = new FunctionalDecoratorRequest(new ServiceKey(conf.getNamespace(), conf.getService()), conf.getMethod()); FunctionalDecoratorRequest makeDecoratorRequest = new FunctionalDecoratorRequest(
new ServiceKey(conf.getNamespace(), conf.getService()), conf.getProtocol(), conf.getMethod(), conf.getPath());
makeDecoratorRequest.setSourceService(new ServiceKey(conf.getSourceNamespace(), conf.getSourceService())); makeDecoratorRequest.setSourceService(new ServiceKey(conf.getSourceNamespace(), conf.getSourceService()));
makeDecoratorRequest.setResultToErrorCode(new PolarisResultToErrorCode()); makeDecoratorRequest.setResultToErrorCode(new PolarisResultToErrorCode());
this.consumerAPI = consumerAPI; this.consumerAPI = consumerAPI;

@ -43,24 +43,25 @@ import org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory;
public class PolarisCircuitBreakerFactory public class PolarisCircuitBreakerFactory
extends CircuitBreakerFactory<PolarisCircuitBreakerConfigBuilder.PolarisCircuitBreakerConfiguration, PolarisCircuitBreakerConfigBuilder> implements DisposableBean { extends CircuitBreakerFactory<PolarisCircuitBreakerConfigBuilder.PolarisCircuitBreakerConfiguration, PolarisCircuitBreakerConfigBuilder> implements DisposableBean {
private final CircuitBreakAPI circuitBreakAPI;
private final ConsumerAPI consumerAPI;
private final ScheduledExecutorService cleanupService = Executors.newSingleThreadScheduledExecutor(
new NamedThreadFactory("sct-circuitbreaker-cleanup", true));
private Function<String, PolarisCircuitBreakerConfigBuilder.PolarisCircuitBreakerConfiguration> defaultConfiguration = private Function<String, PolarisCircuitBreakerConfigBuilder.PolarisCircuitBreakerConfiguration> defaultConfiguration =
id -> { id -> {
String[] metadata = PolarisCircuitBreakerUtils.resolveCircuitBreakerId(id); String[] metadata = PolarisCircuitBreakerUtils.resolveCircuitBreakerId(id);
return new PolarisCircuitBreakerConfigBuilder() return new PolarisCircuitBreakerConfigBuilder()
.namespace(metadata[0]) .namespace(metadata[0])
.service(metadata[1]) .service(metadata[1])
.method(metadata[2]) .path(metadata[2])
.protocol(metadata[3])
.method(metadata[4])
.build(); .build();
}; };
private final CircuitBreakAPI circuitBreakAPI;
private final ConsumerAPI consumerAPI;
private final ScheduledExecutorService cleanupService = Executors.newSingleThreadScheduledExecutor(
new NamedThreadFactory("sct-circuitbreaker-cleanup", true));
public PolarisCircuitBreakerFactory(CircuitBreakAPI circuitBreakAPI, ConsumerAPI consumerAPI, public PolarisCircuitBreakerFactory(CircuitBreakAPI circuitBreakAPI, ConsumerAPI consumerAPI,
PolarisCircuitBreakerProperties polarisCircuitBreakerProperties) { PolarisCircuitBreakerProperties polarisCircuitBreakerProperties) {
this.circuitBreakAPI = circuitBreakAPI; this.circuitBreakAPI = circuitBreakAPI;
@ -83,7 +84,7 @@ public class PolarisCircuitBreakerFactory
@Override @Override
protected PolarisCircuitBreakerConfigBuilder configBuilder(String id) { protected PolarisCircuitBreakerConfigBuilder configBuilder(String id) {
String[] metadata = PolarisCircuitBreakerUtils.resolveCircuitBreakerId(id); String[] metadata = PolarisCircuitBreakerUtils.resolveCircuitBreakerId(id);
return new PolarisCircuitBreakerConfigBuilder(metadata[0], metadata[1], metadata[2]); return new PolarisCircuitBreakerConfigBuilder(metadata[0], metadata[1], metadata[2], metadata[3], metadata[4]);
} }
@Override @Override
@ -93,7 +94,7 @@ public class PolarisCircuitBreakerFactory
@Override @Override
public void destroy() { public void destroy() {
ThreadPoolUtils.waitAndStopThreadPools(new ExecutorService[]{cleanupService}); ThreadPoolUtils.waitAndStopThreadPools(new ExecutorService[] {cleanupService});
} }
} }

@ -51,7 +51,8 @@ public class ReactivePolarisCircuitBreaker implements ReactiveCircuitBreaker {
public ReactivePolarisCircuitBreaker(PolarisCircuitBreakerConfigBuilder.PolarisCircuitBreakerConfiguration conf, public ReactivePolarisCircuitBreaker(PolarisCircuitBreakerConfigBuilder.PolarisCircuitBreakerConfiguration conf,
ConsumerAPI consumerAPI, ConsumerAPI consumerAPI,
CircuitBreakAPI circuitBreakAPI) { CircuitBreakAPI circuitBreakAPI) {
InvokeContext.RequestContext requestContext = new FunctionalDecoratorRequest(new ServiceKey(conf.getNamespace(), conf.getService()), conf.getMethod()); InvokeContext.RequestContext requestContext = new FunctionalDecoratorRequest(
new ServiceKey(conf.getNamespace(), conf.getService()), conf.getProtocol(), conf.getMethod(), conf.getPath());
requestContext.setSourceService(new ServiceKey(conf.getSourceNamespace(), conf.getSourceService())); requestContext.setSourceService(new ServiceKey(conf.getSourceNamespace(), conf.getSourceService()));
requestContext.setResultToErrorCode(new PolarisResultToErrorCode()); requestContext.setResultToErrorCode(new PolarisResultToErrorCode());
this.consumerAPI = consumerAPI; this.consumerAPI = consumerAPI;

@ -43,23 +43,25 @@ import org.springframework.cloud.client.circuitbreaker.ReactiveCircuitBreakerFac
public class ReactivePolarisCircuitBreakerFactory extends public class ReactivePolarisCircuitBreakerFactory extends
ReactiveCircuitBreakerFactory<PolarisCircuitBreakerConfigBuilder.PolarisCircuitBreakerConfiguration, PolarisCircuitBreakerConfigBuilder> implements DisposableBean { ReactiveCircuitBreakerFactory<PolarisCircuitBreakerConfigBuilder.PolarisCircuitBreakerConfiguration, PolarisCircuitBreakerConfigBuilder> implements DisposableBean {
private final CircuitBreakAPI circuitBreakAPI;
private final ConsumerAPI consumerAPI;
private final ScheduledExecutorService cleanupService = Executors.newSingleThreadScheduledExecutor(
new NamedThreadFactory("sct-reactive-circuitbreaker-cleanup", true));
private Function<String, PolarisCircuitBreakerConfigBuilder.PolarisCircuitBreakerConfiguration> defaultConfiguration = private Function<String, PolarisCircuitBreakerConfigBuilder.PolarisCircuitBreakerConfiguration> defaultConfiguration =
id -> { id -> {
String[] metadata = PolarisCircuitBreakerUtils.resolveCircuitBreakerId(id); String[] metadata = PolarisCircuitBreakerUtils.resolveCircuitBreakerId(id);
return new PolarisCircuitBreakerConfigBuilder() return new PolarisCircuitBreakerConfigBuilder()
.namespace(metadata[0]) .namespace(metadata[0])
.service(metadata[1]) .service(metadata[1])
.method(metadata[2]) .path(metadata[2])
.protocol(metadata[3])
.method(metadata[4])
.build(); .build();
}; };
private final CircuitBreakAPI circuitBreakAPI;
private final ConsumerAPI consumerAPI;
private final ScheduledExecutorService cleanupService = Executors.newSingleThreadScheduledExecutor(
new NamedThreadFactory("sct-reactive-circuitbreaker-cleanup", true));
public ReactivePolarisCircuitBreakerFactory(CircuitBreakAPI circuitBreakAPI, ConsumerAPI consumerAPI, public ReactivePolarisCircuitBreakerFactory(CircuitBreakAPI circuitBreakAPI, ConsumerAPI consumerAPI,
PolarisCircuitBreakerProperties polarisCircuitBreakerProperties) { PolarisCircuitBreakerProperties polarisCircuitBreakerProperties) {
this.circuitBreakAPI = circuitBreakAPI; this.circuitBreakAPI = circuitBreakAPI;
@ -72,17 +74,17 @@ public class ReactivePolarisCircuitBreakerFactory extends
polarisCircuitBreakerProperties.getConfigurationCleanupInterval(), TimeUnit.MILLISECONDS); polarisCircuitBreakerProperties.getConfigurationCleanupInterval(), TimeUnit.MILLISECONDS);
} }
@Override @Override
public ReactiveCircuitBreaker create(String id) { public ReactiveCircuitBreaker create(String id) {
PolarisCircuitBreakerConfigBuilder.PolarisCircuitBreakerConfiguration conf = getConfigurations() PolarisCircuitBreakerConfigBuilder.PolarisCircuitBreakerConfiguration conf = getConfigurations()
.computeIfAbsent(id, defaultConfiguration); .computeIfAbsent(id, defaultConfiguration);
return new ReactivePolarisCircuitBreaker(conf, consumerAPI, circuitBreakAPI); return new ReactivePolarisCircuitBreaker(conf, consumerAPI, circuitBreakAPI);
} }
@Override @Override
protected PolarisCircuitBreakerConfigBuilder configBuilder(String id) { protected PolarisCircuitBreakerConfigBuilder configBuilder(String id) {
String[] metadata = PolarisCircuitBreakerUtils.resolveCircuitBreakerId(id); String[] metadata = PolarisCircuitBreakerUtils.resolveCircuitBreakerId(id);
return new PolarisCircuitBreakerConfigBuilder(metadata[0], metadata[1], metadata[2]); return new PolarisCircuitBreakerConfigBuilder(metadata[0], metadata[1], metadata[2], metadata[3], metadata[4]);
} }
@Override @Override
@ -93,6 +95,6 @@ public class ReactivePolarisCircuitBreakerFactory extends
@Override @Override
public void destroy() { public void destroy() {
ThreadPoolUtils.waitAndStopThreadPools(new ExecutorService[]{cleanupService}); ThreadPoolUtils.waitAndStopThreadPools(new ExecutorService[] {cleanupService});
} }
} }

@ -32,15 +32,21 @@ public class PolarisCircuitBreakerConfigBuilder implements ConfigBuilder<Polaris
private String service; private String service;
private String protocol;
private String method; private String method;
private String path;
public PolarisCircuitBreakerConfigBuilder() { public PolarisCircuitBreakerConfigBuilder() {
} }
public PolarisCircuitBreakerConfigBuilder(String namespace, String service, String method) { public PolarisCircuitBreakerConfigBuilder(String namespace, String service, String path, String protocol, String method) {
this.namespace = namespace; this.namespace = namespace;
this.service = service; this.service = service;
this.path = path;
this.protocol = protocol;
this.method = method; this.method = method;
} }
@ -54,17 +60,29 @@ public class PolarisCircuitBreakerConfigBuilder implements ConfigBuilder<Polaris
return this; return this;
} }
public PolarisCircuitBreakerConfigBuilder protocol(String protocol) {
this.protocol = protocol;
return this;
}
public PolarisCircuitBreakerConfigBuilder method(String method) { public PolarisCircuitBreakerConfigBuilder method(String method) {
this.method = method; this.method = method;
return this; return this;
} }
public PolarisCircuitBreakerConfigBuilder path(String path) {
this.path = path;
return this;
}
@Override @Override
public PolarisCircuitBreakerConfiguration build() { public PolarisCircuitBreakerConfiguration build() {
PolarisCircuitBreakerConfiguration conf = new PolarisCircuitBreakerConfiguration(); PolarisCircuitBreakerConfiguration conf = new PolarisCircuitBreakerConfiguration();
conf.setNamespace(namespace); conf.setNamespace(namespace);
conf.setService(service); conf.setService(service);
conf.setProtocol(protocol);
conf.setMethod(method); conf.setMethod(method);
conf.setPath(path);
return conf; return conf;
} }
@ -78,8 +96,12 @@ public class PolarisCircuitBreakerConfigBuilder implements ConfigBuilder<Polaris
private String service; private String service;
private String protocol;
private String method; private String method;
private String path;
public String getNamespace() { public String getNamespace() {
return namespace; return namespace;
} }
@ -96,6 +118,14 @@ public class PolarisCircuitBreakerConfigBuilder implements ConfigBuilder<Polaris
this.service = service; this.service = service;
} }
public String getProtocol() {
return protocol;
}
public void setProtocol(String protocol) {
this.protocol = protocol;
}
public String getMethod() { public String getMethod() {
return method; return method;
} }
@ -104,6 +134,14 @@ public class PolarisCircuitBreakerConfigBuilder implements ConfigBuilder<Polaris
this.method = method; this.method = method;
} }
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getSourceNamespace() { public String getSourceNamespace() {
return sourceNamespace; return sourceNamespace;
} }

@ -22,13 +22,16 @@ import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.polaris.api.utils.CollectionUtils;
import com.tencent.polaris.api.utils.StringUtils;
import feign.Request;
import feign.Target; import feign.Target;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.cloud.openfeign.CircuitBreakerNameResolver; import org.springframework.cloud.openfeign.CircuitBreakerNameResolver;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import static org.springframework.core.annotation.AnnotatedElementUtils.findMergedAnnotation; import static org.springframework.core.annotation.AnnotatedElementUtils.findMergedAnnotation;
@ -47,7 +50,7 @@ public class PolarisCircuitBreakerNameResolver implements CircuitBreakerNameReso
String path = ""; String path = "";
// Get path in @FeignClient. // Get path in @FeignClient.
if (StringUtils.hasText(target.url())) { if (StringUtils.isNotBlank(target.url())) {
URI uri = null; URI uri = null;
try { try {
uri = new URI(target.url()); uri = new URI(target.url());
@ -60,16 +63,24 @@ public class PolarisCircuitBreakerNameResolver implements CircuitBreakerNameReso
} }
} }
// Get path in @RequestMapping. // Get path and method in @RequestMapping.
RequestMapping requestMapping = findMergedAnnotation(method, RequestMapping.class); RequestMapping requestMapping = findMergedAnnotation(method, RequestMapping.class);
String httpMethod = Request.HttpMethod.GET.name();
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];
RequestMethod[] requestMethods = requestMapping.method();
if (CollectionUtils.isNotEmpty(requestMethods)) {
httpMethod = requestMethods[0].name();
}
} }
return "".equals(path) ?
return StringUtils.isBlank(path) ?
MetadataContext.LOCAL_NAMESPACE + "#" + serviceName : MetadataContext.LOCAL_NAMESPACE + "#" + serviceName :
MetadataContext.LOCAL_NAMESPACE + "#" + serviceName + "#" + path; MetadataContext.LOCAL_NAMESPACE + "#" + serviceName + "#" + path + "#http#" + httpMethod;
} }
} }

@ -28,6 +28,7 @@ import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.polaris.api.pojo.CircuitBreakerStatus; import com.tencent.polaris.api.pojo.CircuitBreakerStatus;
import com.tencent.polaris.circuitbreak.client.exception.CallAbortedException; import com.tencent.polaris.circuitbreak.client.exception.CallAbortedException;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
@ -73,12 +74,9 @@ import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.r
*/ */
public class PolarisCircuitBreakerFilterFactory extends SpringCloudCircuitBreakerFilterFactory { public class PolarisCircuitBreakerFilterFactory extends SpringCloudCircuitBreakerFilterFactory {
private String routeIdPrefix;
private final ReactiveCircuitBreakerFactory reactiveCircuitBreakerFactory; private final ReactiveCircuitBreakerFactory reactiveCircuitBreakerFactory;
private final ObjectProvider<DispatcherHandler> dispatcherHandlerProvider; private final ObjectProvider<DispatcherHandler> dispatcherHandlerProvider;
private String routeIdPrefix;
// do not use this dispatcherHandler directly, use getDispatcherHandler() instead. // do not use this dispatcherHandler directly, use getDispatcherHandler() instead.
private volatile DispatcherHandler dispatcherHandler; private volatile DispatcherHandler dispatcherHandler;
@ -190,7 +188,8 @@ public class PolarisCircuitBreakerFilterFactory extends SpringCloudCircuitBreake
serviceName = route.getUri().getHost(); serviceName = route.getUri().getHost();
} }
String path = exchange.getRequest().getPath().value(); String path = exchange.getRequest().getPath().value();
ReactiveCircuitBreaker cb = reactiveCircuitBreakerFactory.create(serviceName + "#" + path); String method = exchange.getRequest().getMethod().name();
ReactiveCircuitBreaker cb = reactiveCircuitBreakerFactory.create(MetadataContext.LOCAL_NAMESPACE + "#" + serviceName + "#" + path + "#http#" + method);
return cb.run( return cb.run(
chain.filter(exchange) chain.filter(exchange)
.doOnSuccess(v -> { .doOnSuccess(v -> {
@ -200,6 +199,9 @@ public class PolarisCircuitBreakerFilterFactory extends SpringCloudCircuitBreake
statusNeedToCheck.addAll(statuses); statusNeedToCheck.addAll(statuses);
statusNeedToCheck.addAll(getDefaultStatus()); statusNeedToCheck.addAll(getDefaultStatus());
HttpStatusCode status = exchange.getResponse().getStatusCode(); HttpStatusCode status = exchange.getResponse().getStatusCode();
if (status == null) {
throw new CircuitBreakerStatusCodeException(HttpStatus.INTERNAL_SERVER_ERROR);
}
if (statusNeedToCheck.contains(HttpStatus.resolve(status.value()))) { if (statusNeedToCheck.contains(HttpStatus.resolve(status.value()))) {
throw new CircuitBreakerStatusCodeException(status); throw new CircuitBreakerStatusCodeException(status);
} }
@ -222,7 +224,8 @@ public class PolarisCircuitBreakerFilterFactory extends SpringCloudCircuitBreake
ServerHttpResponse response = exchange.getResponse(); ServerHttpResponse response = exchange.getResponse();
response.setRawStatusCode(fallbackInfo.getCode()); response.setRawStatusCode(fallbackInfo.getCode());
if (fallbackInfo.getHeaders() != null) { if (fallbackInfo.getHeaders() != null) {
fallbackInfo.getHeaders().forEach((k, v) -> response.getHeaders().add(k, v)); fallbackInfo.getHeaders()
.forEach((k, v) -> response.getHeaders().add(k, v));
} }
DataBuffer bodyBuffer = null; DataBuffer bodyBuffer = null;
if (fallbackInfo.getBody() != null) { if (fallbackInfo.getBody() != null) {

@ -20,6 +20,7 @@ package com.tencent.cloud.polaris.circuitbreaker.resttemplate;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.polaris.circuitbreaker.exception.FallbackWrapperException; import com.tencent.cloud.polaris.circuitbreaker.exception.FallbackWrapperException;
import com.tencent.polaris.api.pojo.CircuitBreakerStatus; import com.tencent.polaris.api.pojo.CircuitBreakerStatus;
import com.tencent.polaris.circuitbreak.client.exception.CallAbortedException; import com.tencent.polaris.circuitbreak.client.exception.CallAbortedException;
@ -65,7 +66,8 @@ public class PolarisCircuitBreakerRestTemplateInterceptor implements ClientHttpR
@Override @Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
try { try {
return circuitBreakerFactory.create(request.getURI().getHost() + "#" + request.getURI().getPath()).run( return circuitBreakerFactory.create(MetadataContext.LOCAL_NAMESPACE + "#" + request.getURI()
.getHost() + "#" + request.getURI().getPath() + "#http#" + request.getMethod().name()).run(
() -> { () -> {
try { try {
ClientHttpResponse response = execution.execute(request, body); ClientHttpResponse response = execution.execute(request, body);
@ -84,7 +86,8 @@ public class PolarisCircuitBreakerRestTemplateInterceptor implements ClientHttpR
CircuitBreakerStatus.FallbackInfo fallbackInfo = new CircuitBreakerStatus.FallbackInfo(200, null, polarisCircuitBreaker.fallback()); CircuitBreakerStatus.FallbackInfo fallbackInfo = new CircuitBreakerStatus.FallbackInfo(200, null, polarisCircuitBreaker.fallback());
return new PolarisCircuitBreakerHttpResponse(fallbackInfo); return new PolarisCircuitBreakerHttpResponse(fallbackInfo);
} }
if (!PolarisCircuitBreakerFallback.class.toGenericString().equals(polarisCircuitBreaker.fallbackClass().toGenericString())) { if (!PolarisCircuitBreakerFallback.class.toGenericString()
.equals(polarisCircuitBreaker.fallbackClass().toGenericString())) {
Method method = ReflectionUtils.findMethod(PolarisCircuitBreakerFallback.class, "fallback"); Method method = ReflectionUtils.findMethod(PolarisCircuitBreakerFallback.class, "fallback");
PolarisCircuitBreakerFallback polarisCircuitBreakerFallback = applicationContext.getBean(polarisCircuitBreaker.fallbackClass()); PolarisCircuitBreakerFallback polarisCircuitBreakerFallback = applicationContext.getBean(polarisCircuitBreaker.fallbackClass());
return (PolarisCircuitBreakerHttpResponse) ReflectionUtils.invokeMethod(method, polarisCircuitBreakerFallback); return (PolarisCircuitBreakerHttpResponse) ReflectionUtils.invokeMethod(method, polarisCircuitBreakerFallback);

@ -45,29 +45,36 @@ public final class PolarisCircuitBreakerUtils {
} }
/** /**
* Format:
* 0. namespace#service#path#protocol#method
* 1. namespace#service#method
* 2. service#method
* 3. service
* namespace set as default spring.cloud.polaris.namespace if absent.
* *
* @param id CircuitBreakerId * @param id CircuitBreakerId
* Format: namespace#service#method or service#method or service ,
* namespace set as default spring.cloud.polaris.namespace if absent
* @return String[]{namespace, service, method} * @return String[]{namespace, service, method}
*/ */
public static String[] resolveCircuitBreakerId(String id) { public static String[] resolveCircuitBreakerId(String id) {
Assert.hasText(id, "A CircuitBreaker must have an id. Id could be : namespace#service#method or service#method or service"); Assert.hasText(id, "A CircuitBreaker must have an id. Id could be : namespace#service#method or service#method or service");
String[] polarisCircuitBreakerMetaData = id.split("#"); String[] polarisCircuitBreakerMetaData = id.split("#");
if (polarisCircuitBreakerMetaData.length == 2) { if (polarisCircuitBreakerMetaData.length == 2) {
return new String[] {MetadataContext.LOCAL_NAMESPACE, polarisCircuitBreakerMetaData[0], polarisCircuitBreakerMetaData[1]}; return new String[] {MetadataContext.LOCAL_NAMESPACE, polarisCircuitBreakerMetaData[0], polarisCircuitBreakerMetaData[1], "http", ""};
} }
if (polarisCircuitBreakerMetaData.length == 3) { if (polarisCircuitBreakerMetaData.length == 3) {
return new String[] {polarisCircuitBreakerMetaData[0], polarisCircuitBreakerMetaData[1], polarisCircuitBreakerMetaData[2]}; return new String[] {polarisCircuitBreakerMetaData[0], polarisCircuitBreakerMetaData[1], polarisCircuitBreakerMetaData[2], "http", ""};
} }
return new String[] {MetadataContext.LOCAL_NAMESPACE, id, ""}; if (polarisCircuitBreakerMetaData.length == 5) {
return new String[] {polarisCircuitBreakerMetaData[0], polarisCircuitBreakerMetaData[1], polarisCircuitBreakerMetaData[2], polarisCircuitBreakerMetaData[3], polarisCircuitBreakerMetaData[4]};
}
return new String[] {MetadataContext.LOCAL_NAMESPACE, id, "", "http", ""};
} }
public static void reportStatus(ConsumerAPI consumerAPI, public static void reportStatus(ConsumerAPI consumerAPI,
PolarisCircuitBreakerConfigBuilder.PolarisCircuitBreakerConfiguration conf, CallAbortedException e) { PolarisCircuitBreakerConfigBuilder.PolarisCircuitBreakerConfiguration conf, CallAbortedException e) {
try { try {
ServiceCallResult result = new ServiceCallResult(); ServiceCallResult result = new ServiceCallResult();
result.setMethod(conf.getMethod()); result.setMethod(conf.getPath());
result.setNamespace(conf.getNamespace()); result.setNamespace(conf.getNamespace());
result.setService(conf.getService()); result.setService(conf.getService());
result.setRuleName(e.getRuleName()); result.setRuleName(e.getRuleName());

@ -93,7 +93,7 @@ public class PolarisCircuitBreakerNameResolverTest {
Method method = ReflectionUtils.findMethod(PolarisCircuitBreakerNameResolverTest.class, "mockRequestMapping2"); Method method = ReflectionUtils.findMethod(PolarisCircuitBreakerNameResolverTest.class, "mockRequestMapping2");
PolarisCircuitBreakerNameResolver resolver = new PolarisCircuitBreakerNameResolver(); PolarisCircuitBreakerNameResolver resolver = new PolarisCircuitBreakerNameResolver();
String polarisCircuitBreakerName = resolver.resolveCircuitBreakerName("test", target, method); String polarisCircuitBreakerName = resolver.resolveCircuitBreakerName("test", target, method);
assertThat(polarisCircuitBreakerName).isEqualTo("Test#test-svc#/"); assertThat(polarisCircuitBreakerName).isEqualTo("Test#test-svc#/#http#GET");
} }
@Test @Test
@ -103,7 +103,7 @@ public class PolarisCircuitBreakerNameResolverTest {
Method method = ReflectionUtils.findMethod(PolarisCircuitBreakerNameResolverTest.class, "mockRequestMapping3"); Method method = ReflectionUtils.findMethod(PolarisCircuitBreakerNameResolverTest.class, "mockRequestMapping3");
PolarisCircuitBreakerNameResolver resolver = new PolarisCircuitBreakerNameResolver(); PolarisCircuitBreakerNameResolver resolver = new PolarisCircuitBreakerNameResolver();
String polarisCircuitBreakerName = resolver.resolveCircuitBreakerName("test", target, method); String polarisCircuitBreakerName = resolver.resolveCircuitBreakerName("test", target, method);
assertThat(polarisCircuitBreakerName).isEqualTo("Test#test-svc#/"); assertThat(polarisCircuitBreakerName).isEqualTo("Test#test-svc#/#http#GET");
} }

@ -57,7 +57,6 @@ import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWeb
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.CircuitBreakerFactory;
import org.springframework.cloud.client.circuitbreaker.Customizer; import org.springframework.cloud.client.circuitbreaker.Customizer;
import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock;
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;
@ -85,12 +84,10 @@ import static org.assertj.core.api.Assertions.assertThat;
"spring.cloud.gateway.enabled=true", "spring.cloud.gateway.enabled=true",
"spring.cloud.polaris.namespace=" + NAMESPACE_TEST, "spring.cloud.polaris.namespace=" + NAMESPACE_TEST,
"spring.cloud.polaris.service=test", "spring.cloud.polaris.service=test",
"spring.main.web-application-type=reactive", "spring.main.web-application-type=reactive"
"httpbin=http://localhost:${wiremock.server.port}"
}, },
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 {

@ -71,9 +71,11 @@ public class PolarisCircuitBreakerUtilsTests {
@Test @Test
public void testResolveCircuitBreakerId() { public void testResolveCircuitBreakerId() {
assertThat(PolarisCircuitBreakerUtils.resolveCircuitBreakerId("test_svc")).isEqualTo(new String[]{NAMESPACE_TEST, "test_svc", ""}); assertThat(PolarisCircuitBreakerUtils.resolveCircuitBreakerId("test_svc")).isEqualTo(new String[] {NAMESPACE_TEST, "test_svc", "", "http", ""});
assertThat(PolarisCircuitBreakerUtils.resolveCircuitBreakerId("test_svc#test_path")).isEqualTo(new String[]{NAMESPACE_TEST, "test_svc", "test_path"}); assertThat(PolarisCircuitBreakerUtils.resolveCircuitBreakerId("test_svc#test_path")).isEqualTo(new String[] {NAMESPACE_TEST, "test_svc", "test_path", "http", ""});
assertThat(PolarisCircuitBreakerUtils.resolveCircuitBreakerId("test_ns#test_svc#test_path")).isEqualTo(new String[]{"test_ns", "test_svc", "test_path"}); assertThat(PolarisCircuitBreakerUtils.resolveCircuitBreakerId("test_ns#test_svc#test_path")).isEqualTo(new String[] {"test_ns", "test_svc", "test_path", "http", ""});
assertThat(PolarisCircuitBreakerUtils.resolveCircuitBreakerId("test_ns#test_svc#test_path")).isEqualTo(new String[] {"test_ns", "test_svc", "test_path", "http", ""});
assertThat(PolarisCircuitBreakerUtils.resolveCircuitBreakerId("test_ns#test_svc#test_path#tcp#POST")).isEqualTo(new String[] {"test_ns", "test_svc", "test_path", "tcp", "POST"});
} }
} }

@ -17,15 +17,10 @@
package com.tencent.cloud.polaris.config.tsf; package com.tencent.cloud.polaris.config.tsf;
import com.tencent.cloud.common.tsf.ConditionalOnTsfEnabled; import com.tencent.cloud.common.tsf.ConditionalOnTsfConsulEnabled;
import com.tencent.cloud.polaris.config.ConditionalOnPolarisConfigEnabled; import com.tencent.cloud.polaris.config.ConditionalOnPolarisConfigEnabled;
import com.tencent.cloud.polaris.config.config.PolarisConfigProperties;
import com.tencent.cloud.polaris.config.tsf.controller.PolarisAdaptorTsfConfigController; import com.tencent.cloud.polaris.config.tsf.controller.PolarisAdaptorTsfConfigController;
import com.tencent.cloud.polaris.context.tsf.config.TsfCoreProperties;
import com.tencent.cloud.polaris.context.tsf.consul.TsfConsulProperties;
import com.tencent.tsf.consul.config.watch.TsfConsulConfigRefreshEventListener; import com.tencent.tsf.consul.config.watch.TsfConsulConfigRefreshEventListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@ -37,17 +32,10 @@ import org.springframework.context.annotation.Configuration;
* @Date Jul 23, 2023 3:52:48 PM * @Date Jul 23, 2023 3:52:48 PM
*/ */
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@ConditionalOnTsfEnabled @ConditionalOnTsfConsulEnabled
@ConditionalOnPolarisConfigEnabled @ConditionalOnPolarisConfigEnabled
public class PolarisAdaptorTsfConfigAutoConfiguration { public class PolarisAdaptorTsfConfigAutoConfiguration {
private static final Logger LOGGER = LoggerFactory.getLogger(PolarisAdaptorTsfConfigAutoConfiguration.class);
{
System.setProperty("spring.cloud.polaris.config.refresh-type", "refresh_context");
LOGGER.info("PolarisAdaptorTsfConfigAutoConfiguration init set spring.cloud.polaris.config.refresh-type to refresh_context");
}
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
@ConditionalOnProperty(name = "spring.cloud.consul.config.watch.enabled", matchIfMissing = true) @ConditionalOnProperty(name = "spring.cloud.consul.config.watch.enabled", matchIfMissing = true)
@ -67,10 +55,4 @@ public class PolarisAdaptorTsfConfigAutoConfiguration {
public PolarisAdaptorTsfConfigController polarisAdaptorTsfConfigController() { public PolarisAdaptorTsfConfigController polarisAdaptorTsfConfigController() {
return new PolarisAdaptorTsfConfigController(); return new PolarisAdaptorTsfConfigController();
} }
@Bean
@ConditionalOnMissingBean
public TsfConfigurationModifier tsfConfigModifier(TsfCoreProperties tsfCoreProperties, TsfConsulProperties tsfConsulProperties, PolarisConfigProperties polarisConfigProperties) {
return new TsfConfigurationModifier(tsfCoreProperties, tsfConsulProperties, polarisConfigProperties);
}
} }

@ -1,37 +0,0 @@
/*
* 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.tsf;
import com.tencent.cloud.common.tsf.ConditionalOnTsfEnabled;
import com.tencent.cloud.polaris.config.ConditionalOnPolarisConfigEnabled;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
/**
* @author juanyinyang
* @Date Jul 23, 2023 3:52:48 PM
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty("spring.cloud.polaris.enabled")
@ConditionalOnTsfEnabled
@ConditionalOnPolarisConfigEnabled
public class PolarisAdaptorTsfConfigBootstrapConfiguration {
}

@ -1,78 +0,0 @@
/*
* 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.tsf;
import java.util.ArrayList;
import java.util.List;
import com.tencent.cloud.common.constant.OrderConstant;
import com.tencent.cloud.polaris.config.config.ConfigFileGroup;
import com.tencent.cloud.polaris.config.config.PolarisConfigProperties;
import com.tencent.cloud.polaris.context.PolarisConfigModifier;
import com.tencent.cloud.polaris.context.tsf.config.TsfCoreProperties;
import com.tencent.cloud.polaris.context.tsf.consul.TsfConsulProperties;
import com.tencent.polaris.factory.config.ConfigurationImpl;
/**
* TSF config modifier.
*
* @author Haotian Zhang
*/
public class TsfConfigurationModifier implements PolarisConfigModifier {
private final TsfCoreProperties tsfCoreProperties;
private final TsfConsulProperties tsfConsulProperties;
private final PolarisConfigProperties polarisConfigProperties;
public TsfConfigurationModifier(TsfCoreProperties tsfCoreProperties, TsfConsulProperties tsfConsulProperties, PolarisConfigProperties polarisConfigProperties) {
this.tsfCoreProperties = tsfCoreProperties;
this.tsfConsulProperties = tsfConsulProperties;
this.polarisConfigProperties = polarisConfigProperties;
}
@Override
public void modify(ConfigurationImpl configuration) {
if (polarisConfigProperties != null && tsfCoreProperties != null) {
polarisConfigProperties.setEnabled(true);
if (!tsfCoreProperties.isTsePolarisEnable()) {
polarisConfigProperties.setDataSource("consul");
polarisConfigProperties.setAddress("http://" + tsfConsulProperties.getHost() + ":" + tsfConsulProperties.getPort());
polarisConfigProperties.setPort(tsfConsulProperties.getPort());
polarisConfigProperties.setToken(tsfConsulProperties.getAclToken());
List<ConfigFileGroup> groups = new ArrayList<>();
polarisConfigProperties.setGroups(groups);
groups.clear();
ConfigFileGroup tsfGroup = new ConfigFileGroup();
tsfGroup.setNamespace("config");
tsfGroup.setName("application");
List<String> files = new ArrayList<>();
tsfGroup.setFiles(files);
files.add(tsfCoreProperties.getTsfNamespaceId() + "/");
files.add(tsfCoreProperties.getTsfApplicationId() + "/" + tsfCoreProperties.getTsfGroupId() + "/");
}
}
}
@Override
public int getOrder() {
return OrderConstant.Modifier.CONFIG_ORDER - 1;
}
}

@ -1,346 +0,0 @@
/*
* 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.tsf.adaptor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import com.google.common.collect.Sets;
import com.tencent.cloud.polaris.config.adapter.PolarisConfigCustomExtensionLayer;
import com.tencent.cloud.polaris.config.adapter.PolarisConfigPropertyAutoRefresher;
import com.tencent.cloud.polaris.config.adapter.PolarisPropertySource;
import com.tencent.cloud.polaris.config.adapter.PolarisPropertySourceManager;
import com.tencent.cloud.polaris.config.enums.ConfigFileFormat;
import com.tencent.cloud.polaris.config.tsf.encrypt.EncryptConfig;
import com.tencent.cloud.polaris.config.utils.PolarisPropertySourceUtils;
import com.tencent.polaris.configuration.api.core.ConfigFileGroup;
import com.tencent.polaris.configuration.api.core.ConfigFileMetadata;
import com.tencent.polaris.configuration.api.core.ConfigFileService;
import com.tencent.polaris.configuration.api.core.ConfigKVFile;
import com.tencent.polaris.configuration.client.internal.CompositeConfigFile;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.Environment;
import org.springframework.util.CollectionUtils;
/**
* @author juanyinyang
*/
public class PolarisAdaptorTsfConfigExtensionLayer implements PolarisConfigCustomExtensionLayer {
private static final Logger LOGGER = LoggerFactory.getLogger(PolarisAdaptorTsfConfigExtensionLayer.class);
/**
* .
*/
private static final String APP_CONFIG = "appconfig";
/**
* .
*/
private static final String PUB_CONFIG = "pubconfig";
/**
* TSFID.
*/
private static final String TSF_APPLICATION_ID = "tsf_application_id";
/**
* TSFID.
*/
private static final String TSF_GROUP_ID = "tsf_group_id";
/**
* TSFID.
*/
private static final String TSF_NAMESPACE_ID = "tsf_namespace_id";
/**
* TSFID.
*/
private static final String POLARIS_ADAPTOR_TSF_CONFIG_FORMAT = "spring.cloud.polaris.config.format";
// 最近一次的全量PolarisPropertySource集合PolarisPropertySource按 namespace + fileGroup + fileName 确保唯一)
private static final Set<String> registedPolarisPropertySets = Sets.newConcurrentHashSet();
// 命名空间分组namespace + fileGroup的去重Set集合如果这个分组已添加了ConfigFileGroupListener
private static final Set<String> registedConfigFileGroupListenerSets = Sets.newConcurrentHashSet();
private PolarisConfigPropertyAutoRefresher polarisConfigPropertyAutoRefresher;
@Override
public boolean isEnabled() {
// tse_polaris_enable
String tsePolarisEnable = System.getenv("tse_polaris_enable");
if (StringUtils.isBlank(tsePolarisEnable)) {
tsePolarisEnable = System.getProperty("tse_polaris_enable", "false");
}
return StringUtils.equals(tsePolarisEnable, "true");
}
/**
* @see PolarisConfigCustomExtensionLayer#initConfigFiles(CompositePropertySource,
* PolarisPropertySourceManager,
* ConfigFileService)
*/
@Override
public void initConfigFiles(Environment environment, CompositePropertySource compositePropertySource,
ConfigFileService configFileService) {
String tsfApplicationId = "";
String tsfGroupId = "";
String tsfNamespaceId = "";
String polarisAdaptorTsfConfigFormat = "";
if (environment != null) {
tsfApplicationId = environment.getProperty(TSF_APPLICATION_ID);
tsfGroupId = environment.getProperty(TSF_GROUP_ID);
tsfNamespaceId = environment.getProperty(TSF_NAMESPACE_ID);
polarisAdaptorTsfConfigFormat = environment.getProperty(POLARIS_ADAPTOR_TSF_CONFIG_FORMAT);
}
else {
tsfApplicationId = System.getProperty(TSF_APPLICATION_ID);
if (StringUtils.isEmpty(tsfApplicationId)) {
tsfApplicationId = System.getenv(TSF_APPLICATION_ID);
}
tsfGroupId = System.getProperty(TSF_GROUP_ID);
if (StringUtils.isEmpty(tsfGroupId)) {
tsfGroupId = System.getenv(TSF_GROUP_ID);
}
tsfNamespaceId = System.getProperty(TSF_NAMESPACE_ID);
if (StringUtils.isEmpty(tsfNamespaceId)) {
tsfNamespaceId = System.getenv(TSF_NAMESPACE_ID);
}
polarisAdaptorTsfConfigFormat = System.getProperty(POLARIS_ADAPTOR_TSF_CONFIG_FORMAT);
if (StringUtils.isEmpty(polarisAdaptorTsfConfigFormat)) {
polarisAdaptorTsfConfigFormat = System.getenv(POLARIS_ADAPTOR_TSF_CONFIG_FORMAT);
}
}
LOGGER.info(
"PolarisAdaptorTsfConfigExtensionLayer initConfigFiles start, tsfNamespaceId:{}, tsfApplicationId:{}, tsfGroupId:{}",
tsfNamespaceId, tsfApplicationId, tsfGroupId);
loadAllPolarisConfigFile(compositePropertySource, configFileService,
tsfNamespaceId, tsfApplicationId, tsfGroupId, polarisAdaptorTsfConfigFormat);
LOGGER.info("PolarisAdaptorTsfConfigExtensionLayer initConfigFiles end");
}
private void loadAllPolarisConfigFile(CompositePropertySource compositePropertySource,
ConfigFileService configFileService, String tsfNamespaceId, String tsfApplicationId, String tsfGroupId,
String polarisAdaptorTsfConfigFormat) {
boolean isInitTsfEnv = StringUtils.isNotBlank(tsfNamespaceId) && StringUtils.isNotBlank(tsfApplicationId)
&& StringUtils.isNotBlank(tsfGroupId);
if (isInitTsfEnv) {
String appConfigGroup = APP_CONFIG + "." + tsfApplicationId + "." + tsfGroupId;
loadPolarisConfigFile(tsfNamespaceId, tsfApplicationId, tsfGroupId, polarisAdaptorTsfConfigFormat,
compositePropertySource, configFileService, appConfigGroup);
}
String pubConfigGroup = PUB_CONFIG;
loadPolarisConfigFile(tsfNamespaceId, tsfApplicationId, tsfGroupId, polarisAdaptorTsfConfigFormat,
compositePropertySource, configFileService, pubConfigGroup);
}
private PolarisPropertySource loadPolarisPropertySource(String configFileGroupNamespace, String configFileGroupName,
List<ConfigFileMetadata> configFileMetadataList, String polarisAdaptorTsfConfigFormat,
ConfigFileService configFileService) {
List<ConfigKVFile> configKVFiles = new ArrayList<>();
for (ConfigFileMetadata configFileMetadata : configFileMetadataList) {
ConfigKVFile configKVFile;
String namespace = configFileMetadata.getNamespace();
String group = configFileMetadata.getFileGroup();
String fileName = configFileMetadata.getFileName();
if (StringUtils.isNotBlank(polarisAdaptorTsfConfigFormat)) {
switch (polarisAdaptorTsfConfigFormat) {
case "properties":
configKVFile = configFileService.getConfigPropertiesFile(namespace, group, fileName);
break;
case "yaml":
default:
configKVFile = configFileService.getConfigYamlFile(namespace, group, fileName);
}
}
// unknown extension is resolved as yaml file
else if (ConfigFileFormat.isYamlFile(fileName) || ConfigFileFormat.isUnknownFile(fileName)) {
configKVFile = configFileService.getConfigYamlFile(namespace, group, fileName);
}
else if (ConfigFileFormat.isPropertyFile(fileName)) {
configKVFile = configFileService.getConfigPropertiesFile(namespace, group, fileName);
}
else {
LOGGER.warn("Unsupported config file. namespace = {}, group = {}, fileName = {}", namespace,
group, fileName);
throw new IllegalStateException("Only configuration files in the format of properties / yaml / yaml"
+ " can be injected into the spring context");
}
configKVFiles.add(configKVFile);
}
CompositeConfigFile compositeConfigFile = new CompositeConfigFile(configKVFiles);
Map<String, Object> map = new ConcurrentHashMap<>();
for (String key : compositeConfigFile.getPropertyNames()) {
String value = compositeConfigFile.getProperty(key, null);
if (EncryptConfig.needDecrypt(value)) {
LOGGER.debug("Need Decrypt {}: {}", key, value);
value = EncryptConfig.getProvider()
.decrypt(EncryptConfig.realContent(value), EncryptConfig.getPassword());
}
map.put(key, value);
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("namespace='" + configFileGroupNamespace + '\''
+ ", group='" + configFileGroupName + '\'' + ", fileName='" + compositeConfigFile + '\''
+ ", map='" + map + '\'');
}
return new PolarisPropertySource(configFileGroupNamespace, configFileGroupName, "", compositeConfigFile, map);
}
private void loadPolarisConfigFile(String namespace, String tsfApplicationId, String tsfGroupId,
String polarisAdaptorTsfConfigFormat, CompositePropertySource compositePropertySource,
ConfigFileService configFileService, String configGroup) {
LOGGER.debug(
"PolarisAdaptorTsfConfigExtensionLayer loadPolarisConfigFile start, namespace:{}, group:{}",
namespace, configGroup);
ConfigFileGroup configFileGroup = configFileService.getConfigFileGroup(namespace, configGroup);
if (configFileGroup == null) {
throw new IllegalStateException(
"PolarisAdaptorTsfConfigExtensionLayer configFileGroup is null");
}
List<ConfigFileMetadata> configFileMetadataList = configFileGroup.getConfigFileMetadataList();
if (!CollectionUtils.isEmpty(configFileMetadataList)) {
LOGGER.info("PolarisAdaptorTsfConfigExtensionLayer getConfigFileMetadataList:{}",
configFileMetadataList);
}
else {
LOGGER.info("PolarisAdaptorTsfConfigExtensionLayer getConfigFileMetadataList empty. file = {}:{}",
configFileGroup.getNamespace(), configFileGroup.getNamespace());
}
PolarisPropertySource polarisPropertySource = loadPolarisPropertySource(namespace, configGroup,
configFileMetadataList, polarisAdaptorTsfConfigFormat, configFileService);
compositePropertySource.addPropertySource(polarisPropertySource);
PolarisPropertySourceManager.addPropertySource(polarisPropertySource);
LOGGER.info("PolarisAdaptorTsfConfigExtensionLayer Load and inject polaris config file from config group:{}. file = {}",
configGroup, polarisPropertySource.getConfigKVFile());
String namespaceConfigGroup = namespace + "-" + configGroup;
// 用ConcurrentHashSet保证不重复添加ConfigFileGroupChangeListener
if (registedConfigFileGroupListenerSets.add(namespaceConfigGroup)) {
LOGGER.info("PolarisAdaptorTsfConfigExtensionLayer configFileGroup addChangeListener namespaceConfigGroup:{}",
namespaceConfigGroup);
configFileGroup.addChangeListener(event -> {
try {
LOGGER.info("PolarisAdaptorTsfConfigExtensionLayer receive onChange event:{}",
event);
List<ConfigFileMetadata> oldConfigFileMetadataList = event.getOldConfigFileMetadataList();
List<ConfigFileMetadata> newConfigFileMetadataList = event.getNewConfigFileMetadataList();
List<String> toUnregister = calculateUnregister(oldConfigFileMetadataList, newConfigFileMetadataList);
toUnregister.forEach(registedPolarisPropertySets::remove);
if (CollectionUtils.isEmpty(newConfigFileMetadataList)) {
LOGGER.info("PolarisAdaptorTsfConfigExtensionLayer receive configFileMetadataList is empty");
}
else {
PolarisPropertySource polarisPropertySource1 = loadPolarisPropertySource(
event.getConfigFileGroupMetadata().getNamespace(),
event.getConfigFileGroupMetadata().getFileGroupName(),
newConfigFileMetadataList, polarisAdaptorTsfConfigFormat, configFileService);
// 用ConcurrentHashSet保证不重复注册PolarisConfigPublishChangeListener
CompositeConfigFile configKVFile = (CompositeConfigFile) polarisPropertySource1.getConfigKVFile();
for (ConfigKVFile cf : configKVFile.getConfigKVFiles()) {
LOGGER.info(
"PolarisAdaptorTsfConfigExtensionLayer Load and inject polaris config file from onChange event config group:{}. file = {}",
configGroup, cf);
PolarisPropertySource p = new PolarisPropertySource(cf.getNamespace(), cf.getFileGroup(), cf.getFileName(), cf, new HashMap<>());
if (executeRegisterPublishChangeListener(p)) {
polarisConfigPropertyAutoRefresher.registerPolarisConfigPublishChangeListener(p);
}
}
}
LOGGER.info("PolarisAdaptorTsfConfigExtensionLayer start refresh All Config");
polarisConfigPropertyAutoRefresher.refreshConfigurationProperties(null);
}
catch (Exception e) {
LOGGER.info("PolarisAdaptorTsfConfigExtensionLayer receive onChange exception:",
e);
}
});
}
LOGGER.info("PolarisAdaptorTsfConfigExtensionLayer loadPolarisConfigFile end, namespace:{}, group:{}",
namespace, configGroup);
}
/**
* @see PolarisConfigCustomExtensionLayer#executeAfterLocateConfigReturning(CompositePropertySource)
*/
@Override
public void executeAfterLocateConfigReturning(CompositePropertySource compositePropertySource) {
}
/**
* @see PolarisConfigCustomExtensionLayer#initRegisterConfig(PolarisConfigPropertyAutoRefresher)
*/
@Override
public void initRegisterConfig(PolarisConfigPropertyAutoRefresher polarisConfigPropertyAutoRefresher) {
LOGGER.info(
"PolarisAdaptorTsfConfigExtensionLayer initRegisterConfig polarisConfigPropertyAutoRefresher:{}",
polarisConfigPropertyAutoRefresher.getClass());
this.polarisConfigPropertyAutoRefresher = polarisConfigPropertyAutoRefresher;
}
/**
* @see PolarisConfigCustomExtensionLayer#executeRegisterPublishChangeListener(PolarisPropertySource)
*/
@Override
public boolean executeRegisterPublishChangeListener(PolarisPropertySource polarisPropertySource) {
boolean isRegisterSuccess = registedPolarisPropertySets.add(polarisPropertySource.getPropertySourceName());
if (isRegisterSuccess) {
// 已防止重复注册,仅打印注册成功的即可
LOGGER.info("start to register configFile polarisConfigPublishChangeListener:{}",
polarisPropertySource);
}
return isRegisterSuccess;
}
private List<String> calculateUnregister(List<ConfigFileMetadata> oldConfigFileMetadataList, List<ConfigFileMetadata> newConfigFileMetadataList) {
List<String> newNameList = new ArrayList<>();
for (ConfigFileMetadata configFileMetadata : newConfigFileMetadataList) {
newNameList.add(PolarisPropertySourceUtils.generateName(configFileMetadata.getNamespace(),
configFileMetadata.getFileGroup(), configFileMetadata.getFileName()));
}
List<String> toUnregister = new ArrayList<>();
for (ConfigFileMetadata configFileMetadata : oldConfigFileMetadataList) {
String oldName = (PolarisPropertySourceUtils.generateName(configFileMetadata.getNamespace(),
configFileMetadata.getFileGroup(), configFileMetadata.getFileName()));
if (!newNameList.contains(oldName)) {
toUnregister.add(oldName);
}
}
return toUnregister;
}
}

@ -37,7 +37,7 @@ public final class EncryptConfig {
/** /**
* . * .
*/ */
private static String providerClass = "com.tencent.cloud.tsf.config.encrypt.ConfigEncryptAESProvider"; private static String providerClass = "com.tencent.cloud.polaris.config.tsf.encrypt.ConfigEncryptAESProvider";
static { static {
// 环境变量 // 环境变量

@ -1,6 +1,5 @@
org.springframework.cloud.bootstrap.BootstrapConfiguration=\ org.springframework.cloud.bootstrap.BootstrapConfiguration=\
com.tencent.cloud.polaris.config.PolarisConfigBootstrapAutoConfiguration,\ com.tencent.cloud.polaris.config.PolarisConfigBootstrapAutoConfiguration
com.tencent.cloud.polaris.config.tsf.PolarisAdaptorTsfConfigBootstrapConfiguration
# ConfigData Location Resolvers # ConfigData Location Resolvers
org.springframework.boot.context.config.ConfigDataLocationResolver=\ org.springframework.boot.context.config.ConfigDataLocationResolver=\
com.tencent.cloud.polaris.config.configdata.PolarisConfigDataLocationResolver com.tencent.cloud.polaris.config.configdata.PolarisConfigDataLocationResolver

@ -1,26 +0,0 @@
/*
* 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.contract.config;
/**
* Extend contract properties.
*
* @author Haotian Zhang
*/
public interface ExtendedContractProperties extends ContractProperties {
}

@ -17,10 +17,6 @@
package com.tencent.cloud.polaris.contract.config; package com.tencent.cloud.polaris.contract.config;
import java.util.Objects;
import javax.annotation.Nullable;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
@ -32,8 +28,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("spring.cloud.polaris.contract") @ConfigurationProperties("spring.cloud.polaris.contract")
public class PolarisContractProperties implements ContractProperties { public class PolarisContractProperties implements ContractProperties {
private final ExtendedContractProperties extendContractProperties;
private boolean enabled = true; private boolean enabled = true;
/** /**
* Packages to be scanned. Split by ",". * Packages to be scanned. Split by ",".
@ -59,103 +53,63 @@ public class PolarisContractProperties implements ContractProperties {
private String name; private String name;
public PolarisContractProperties(@Nullable ExtendedContractProperties extendContractProperties) {
this.extendContractProperties = extendContractProperties;
}
@Override @Override
public boolean isEnabled() { public boolean isEnabled() {
if (Objects.nonNull(extendContractProperties)) {
return extendContractProperties.isEnabled();
}
return enabled; return enabled;
} }
@Override @Override
public void setEnabled(boolean enabled) { public void setEnabled(boolean enabled) {
if (Objects.nonNull(extendContractProperties)) {
extendContractProperties.setEnabled(enabled);
}
this.enabled = enabled; this.enabled = enabled;
} }
@Override @Override
public String getBasePackage() { public String getBasePackage() {
if (Objects.nonNull(extendContractProperties)) {
return extendContractProperties.getBasePackage();
}
return basePackage; return basePackage;
} }
@Override @Override
public void setBasePackage(String basePackage) { public void setBasePackage(String basePackage) {
if (Objects.nonNull(extendContractProperties)) {
extendContractProperties.setBasePackage(basePackage);
}
this.basePackage = basePackage; this.basePackage = basePackage;
} }
@Override @Override
public String getExcludePath() { public String getExcludePath() {
if (Objects.nonNull(extendContractProperties)) {
return extendContractProperties.getExcludePath();
}
return excludePath; return excludePath;
} }
@Override @Override
public void setExcludePath(String excludePath) { public void setExcludePath(String excludePath) {
if (Objects.nonNull(extendContractProperties)) {
extendContractProperties.setExcludePath(excludePath);
}
this.excludePath = excludePath; this.excludePath = excludePath;
} }
@Override @Override
public String getGroup() { public String getGroup() {
if (Objects.nonNull(extendContractProperties)) {
return extendContractProperties.getGroup();
}
return group; return group;
} }
@Override @Override
public void setGroup(String group) { public void setGroup(String group) {
if (Objects.nonNull(extendContractProperties)) {
extendContractProperties.setGroup(group);
}
this.group = group; this.group = group;
} }
@Override @Override
public String getBasePath() { public String getBasePath() {
if (Objects.nonNull(extendContractProperties)) {
return extendContractProperties.getBasePath();
}
return basePath; return basePath;
} }
@Override @Override
public void setBasePath(String basePath) { public void setBasePath(String basePath) {
if (Objects.nonNull(extendContractProperties)) {
extendContractProperties.setBasePath(basePath);
}
this.basePath = basePath; this.basePath = basePath;
} }
@Override @Override
public boolean isExposure() { public boolean isExposure() {
if (Objects.nonNull(extendContractProperties)) {
return extendContractProperties.isExposure();
}
return exposure; return exposure;
} }
@Override @Override
public void setExposure(boolean exposure) { public void setExposure(boolean exposure) {
if (Objects.nonNull(extendContractProperties)) {
extendContractProperties.setExposure(exposure);
}
this.exposure = exposure; this.exposure = exposure;
} }
@ -170,17 +124,11 @@ public class PolarisContractProperties implements ContractProperties {
} }
public String getName() { public String getName() {
if (Objects.nonNull(extendContractProperties)) {
return extendContractProperties.getName();
}
return name; return name;
} }
@Override @Override
public void setName(String name) { public void setName(String name) {
if (Objects.nonNull(extendContractProperties)) {
extendContractProperties.setName(name);
}
this.name = name; this.name = name;
} }
} }

@ -22,7 +22,6 @@ import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled;
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;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.lang.Nullable;
/** /**
* Auto configuration for Polaris contract properties. * Auto configuration for Polaris contract properties.
@ -35,8 +34,8 @@ public class PolarisContractPropertiesAutoConfiguration {
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public PolarisContractProperties polarisContractProperties(@Nullable ExtendedContractProperties extendedContractProperties) { public PolarisContractProperties polarisContractProperties() {
return new PolarisContractProperties(extendedContractProperties); return new PolarisContractProperties();
} }
@Bean @Bean

@ -1,136 +0,0 @@
/*
* 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.contract.tsf;
import com.tencent.cloud.polaris.contract.config.ExtendedContractProperties;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* Properties for TSF contract.
*
* @author Haotian Zhang
*/
@ConfigurationProperties("tsf.swagger")
public class TsfContractProperties implements ExtendedContractProperties {
@Value("${tsf.swagger.basePackage:}")
private String basePackage;
@Value("${tsf.swagger.excludePath:}")
private String excludePath;
@Value("${tsf.swagger.enabled:true}")
private boolean enabled;
@Value("${tsf.swagger.group:polaris}")
private String groupName;
@Value("${tsf.swagger.basePath:/**}")
private String basePath;
@Value("${tsf.swagger.doc.auto-startup:true}")
private boolean exposure;
/**
* applicationId Id.
*/
@Value("${tsf_application_id:}")
private String name;
@Override
public boolean isEnabled() {
return enabled;
}
@Override
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@Override
public String getBasePackage() {
return basePackage;
}
@Override
public void setBasePackage(String basePackage) {
this.basePackage = basePackage;
}
@Override
public String getExcludePath() {
return excludePath;
}
@Override
public void setExcludePath(String excludePath) {
this.excludePath = excludePath;
}
@Override
public String getGroup() {
return groupName;
}
@Override
public void setGroup(String group) {
this.groupName = group;
}
@Override
public String getBasePath() {
return basePath;
}
@Override
public void setBasePath(String basePath) {
this.basePath = basePath;
}
@Override
public boolean isExposure() {
return exposure;
}
@Override
public void setExposure(boolean exposure) {
this.exposure = exposure;
}
@Override
public boolean isReportEnabled() {
return enabled;
}
@Override
public void setReportEnabled(boolean reportEnabled) {
}
@Override
public String getName() {
return name;
}
@Override
public void setName(String name) {
this.name = name;
}
}

@ -1,40 +0,0 @@
/*
* 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.contract.tsf;
import com.tencent.cloud.common.tsf.ConditionalOnTsfEnabled;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Auto configuration for TSF contract properties.
*
* @author Haotian Zhang
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnTsfEnabled
public class TsfContractPropertiesAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public TsfContractProperties tsfContractProperties() {
return new TsfContractProperties();
}
}

@ -1,35 +0,0 @@
/*
* 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.contract.tsf;
import com.tencent.cloud.common.tsf.ConditionalOnTsfEnabled;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* Bootstrap configuration for TSF contract properties.
*
* @author Haotian Zhang
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnTsfEnabled
@Import(TsfContractPropertiesAutoConfiguration.class)
public class TsfContractPropertiesBootstrapConfiguration {
}

@ -16,7 +16,7 @@
*/ */
package com.tencent.cloud.polaris.contract.tsf; package com.tencent.cloud.polaris.contract.tsf;
import com.tencent.cloud.common.tsf.ConditionalOnTsfEnabled; import com.tencent.cloud.common.tsf.ConditionalOnTsfConsulEnabled;
import com.tencent.cloud.polaris.contract.config.PolarisContractProperties; import com.tencent.cloud.polaris.contract.config.PolarisContractProperties;
import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.OpenAPI;
import org.springdoc.core.providers.ObjectMapperProvider; import org.springdoc.core.providers.ObjectMapperProvider;
@ -24,18 +24,14 @@ import org.springdoc.webflux.api.MultipleOpenApiWebFluxResource;
import org.springdoc.webmvc.api.MultipleOpenApiWebMvcResource; import org.springdoc.webmvc.api.MultipleOpenApiWebMvcResource;
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.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
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.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@EnableWebMvc
@Configuration @Configuration
@ConditionalOnTsfEnabled @ConditionalOnTsfConsulEnabled
@ConditionalOnClass(name = "org.springframework.web.servlet.config.annotation.EnableWebMvc")
@ConditionalOnProperty(value = "tsf.swagger.enabled", havingValue = "true", matchIfMissing = true) @ConditionalOnProperty(value = "tsf.swagger.enabled", havingValue = "true", matchIfMissing = true)
public class TsfSwaggerAutoConfiguration { public class TsfSwaggerAutoConfiguration {

@ -1,5 +1,4 @@
org.springframework.cloud.bootstrap.BootstrapConfiguration=\ org.springframework.cloud.bootstrap.BootstrapConfiguration=\
com.tencent.cloud.polaris.contract.config.PolarisContractPropertiesBootstrapConfiguration,\ com.tencent.cloud.polaris.contract.config.PolarisContractPropertiesBootstrapConfiguration
com.tencent.cloud.polaris.contract.tsf.TsfContractPropertiesBootstrapConfiguration
org.springframework.context.ApplicationListener=\ org.springframework.context.ApplicationListener=\
com.tencent.cloud.polaris.contract.PolarisSwaggerApplicationListener com.tencent.cloud.polaris.contract.PolarisSwaggerApplicationListener

@ -1,4 +1,3 @@
com.tencent.cloud.polaris.contract.config.PolarisSwaggerAutoConfiguration com.tencent.cloud.polaris.contract.config.PolarisSwaggerAutoConfiguration
com.tencent.cloud.polaris.contract.config.PolarisContractPropertiesAutoConfiguration com.tencent.cloud.polaris.contract.config.PolarisContractPropertiesAutoConfiguration
com.tencent.cloud.polaris.contract.tsf.TsfContractPropertiesAutoConfiguration
com.tencent.cloud.polaris.contract.tsf.TsfSwaggerAutoConfiguration com.tencent.cloud.polaris.contract.tsf.TsfSwaggerAutoConfiguration

@ -17,16 +17,23 @@
*/ */
package com.tencent.cloud.polaris; package com.tencent.cloud.polaris;
import com.tencent.cloud.common.util.inet.PolarisInetUtils;
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.context.PolarisSDKContextManager;
import com.tencent.cloud.polaris.context.config.extend.consul.ConsulProperties;
import com.tencent.cloud.polaris.context.config.extend.tsf.TsfCoreProperties;
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.ConsulDiscoveryConfigModifier;
import com.tencent.cloud.polaris.extend.consul.ConsulContextProperties; import com.tencent.cloud.polaris.extend.consul.ConsulDiscoveryProperties;
import com.tencent.cloud.polaris.extend.consul.ConsulHeartbeatProperties;
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 io.micrometer.common.lang.Nullable;
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;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
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;
@ -45,12 +52,6 @@ public class DiscoveryPropertiesAutoConfiguration {
return new PolarisDiscoveryProperties(); return new PolarisDiscoveryProperties();
} }
@Bean
@ConditionalOnMissingBean
public ConsulContextProperties consulContextProperties() {
return new ConsulContextProperties();
}
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public NacosContextProperties nacosContextProperties() { public NacosContextProperties nacosContextProperties() {
@ -70,12 +71,6 @@ public class DiscoveryPropertiesAutoConfiguration {
return new DiscoveryConfigModifier(polarisDiscoveryProperties); return new DiscoveryConfigModifier(polarisDiscoveryProperties);
} }
@Bean
@ConditionalOnMissingBean
public ConsulConfigModifier consulConfigModifier(@Autowired(required = false) ConsulContextProperties consulContextProperties) {
return new ConsulConfigModifier(consulContextProperties);
}
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public PolarisDiscoveryConfigModifier polarisDiscoveryConfigModifier(PolarisDiscoveryProperties polarisDiscoveryProperties) { public PolarisDiscoveryConfigModifier polarisDiscoveryConfigModifier(PolarisDiscoveryProperties polarisDiscoveryProperties) {
@ -87,4 +82,34 @@ public class DiscoveryPropertiesAutoConfiguration {
public NacosConfigModifier nacosConfigModifier(@Autowired(required = false) NacosContextProperties nacosContextProperties) { public NacosConfigModifier nacosConfigModifier(@Autowired(required = false) NacosContextProperties nacosContextProperties) {
return new NacosConfigModifier(nacosContextProperties); return new NacosConfigModifier(nacosContextProperties);
} }
/**
* Create when consul is enabled.
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(value = "spring.cloud.consul.enabled", havingValue = "true")
protected static class ConsulDiscoveryConfiguration {
@Bean
@ConditionalOnMissingBean
public ConsulDiscoveryProperties consulDiscoveryProperties(PolarisInetUtils polarisInetUtils) {
return new ConsulDiscoveryProperties(polarisInetUtils);
}
@Bean
@ConditionalOnMissingBean
public ConsulHeartbeatProperties consulHeartbeatProperties() {
return new ConsulHeartbeatProperties();
}
@Bean
@ConditionalOnMissingBean
public ConsulDiscoveryConfigModifier consulDiscoveryConfigModifier(
PolarisDiscoveryProperties polarisDiscoveryProperties, ConsulProperties consulProperties,
ConsulDiscoveryProperties consulContextProperties, ConsulHeartbeatProperties consulHeartbeatProperties,
@Nullable TsfCoreProperties tsfCoreProperties, ApplicationContext applicationContext) {
return new ConsulDiscoveryConfigModifier(polarisDiscoveryProperties, consulProperties, consulContextProperties,
consulHeartbeatProperties, tsfCoreProperties, applicationContext);
}
}
} }

@ -1,120 +0,0 @@
/*
* 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.extend.consul;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Map;
import com.tencent.cloud.common.constant.OrderConstant;
import com.tencent.cloud.polaris.context.PolarisConfigModifier;
import com.tencent.polaris.api.config.plugin.DefaultPlugins;
import com.tencent.polaris.factory.config.ConfigurationImpl;
import com.tencent.polaris.factory.config.consumer.DiscoveryConfigImpl;
import com.tencent.polaris.factory.config.global.ServerConnectorConfigImpl;
import com.tencent.polaris.factory.config.provider.RegisterConfigImpl;
import com.tencent.polaris.plugins.connector.common.constant.ConsulConstant;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
/**
* @author lingxiao.wlx
*/
public class ConsulConfigModifier implements PolarisConfigModifier {
private static final Logger LOGGER = LoggerFactory.getLogger(ConsulConfigModifier.class);
private static final String ID = "consul";
private final ConsulContextProperties consulContextProperties;
public ConsulConfigModifier(ConsulContextProperties consulContextProperties) {
this.consulContextProperties = consulContextProperties;
}
@Override
public void modify(ConfigurationImpl configuration) {
if (consulContextProperties != null && consulContextProperties.isEnabled()) {
// Check if Consul client Available
boolean consulAvailable = false;
try {
consulAvailable = null != Class.forName("com.ecwid.consul.v1.ConsulClient");
}
catch (Throwable ignored) {
}
if (!consulAvailable) {
LOGGER.error("Please import \"connector-consul\" dependency when enabling consul service registration and discovery.\n"
+ "Add dependency configuration below to pom.xml:\n"
+ "<dependency>\n"
+ "\t<groupId>com.tencent.polaris</groupId>\n"
+ "\t<artifactId>connector-consul</artifactId>\n"
+ "</dependency>");
throw new RuntimeException("Dependency \"connector-consul\" not found.");
}
if (CollectionUtils.isEmpty(configuration.getGlobal().getServerConnectors())) {
configuration.getGlobal().setServerConnectors(new ArrayList<>());
}
if (CollectionUtils.isEmpty(configuration.getGlobal().getServerConnectors())
&& null != configuration.getGlobal().getServerConnector()) {
configuration.getGlobal().getServerConnectors().add(configuration.getGlobal().getServerConnector());
}
ServerConnectorConfigImpl serverConnectorConfig = new ServerConnectorConfigImpl();
serverConnectorConfig.setId(ID);
serverConnectorConfig.setAddresses(
Collections.singletonList(consulContextProperties.getHost() + ":" + consulContextProperties.getPort()));
serverConnectorConfig.setProtocol(DefaultPlugins.SERVER_CONNECTOR_CONSUL);
Map<String, String> metadata = serverConnectorConfig.getMetadata();
if (StringUtils.isNotBlank(consulContextProperties.getServiceName())) {
metadata.put(ConsulConstant.MetadataMapKey.SERVICE_NAME_KEY, consulContextProperties.getServiceName());
}
if (StringUtils.isNotBlank(consulContextProperties.getInstanceId())) {
metadata.put(ConsulConstant.MetadataMapKey.INSTANCE_ID_KEY, consulContextProperties.getInstanceId());
}
if (StringUtils.isNotBlank(consulContextProperties.getAclToken())) {
serverConnectorConfig.setToken(consulContextProperties.getAclToken());
}
if (consulContextProperties.isPreferIpAddress()
&& StringUtils.isNotBlank(consulContextProperties.getIpAddress())) {
metadata.put(ConsulConstant.MetadataMapKey.PREFER_IP_ADDRESS_KEY,
String.valueOf(consulContextProperties.isPreferIpAddress()));
metadata.put(ConsulConstant.MetadataMapKey.IP_ADDRESS_KEY, consulContextProperties.getIpAddress());
}
configuration.getGlobal().getServerConnectors().add(serverConnectorConfig);
DiscoveryConfigImpl discoveryConfig = new DiscoveryConfigImpl();
discoveryConfig.setServerConnectorId(ID);
discoveryConfig.setEnable(consulContextProperties.isDiscoveryEnabled());
configuration.getConsumer().getDiscoveries().add(discoveryConfig);
RegisterConfigImpl registerConfig = new RegisterConfigImpl();
registerConfig.setServerConnectorId(ID);
registerConfig.setEnable(consulContextProperties.isRegister());
configuration.getProvider().getRegisters().add(registerConfig);
}
}
@Override
public int getOrder() {
return OrderConstant.Modifier.CONSUL_DISCOVERY_CONFIG_ORDER;
}
}

@ -1,140 +0,0 @@
/*
* 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.extend.consul;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* Discovery configuration of Consul.
*
* @author Haotian Zhang
*/
@ConfigurationProperties("spring.cloud.consul")
public class ConsulContextProperties {
/**
* Host of consul(or consul agent).
*/
private String host;
private int port;
private boolean enabled = false;
@Value("${spring.cloud.consul.discovery.register:#{'true'}}")
private boolean register;
@Value("${spring.cloud.consul.discovery.enabled:#{'true'}}")
private boolean discoveryEnabled;
@Value("${spring.cloud.consul.discovery.instance-id:}")
private String instanceId;
@Value("${spring.cloud.consul.discovery.service-name:${spring.application.name:}}")
private String serviceName;
@Value("${spring.cloud.consul.discovery.ip-address:}")
private String ipAddress;
@Value("${spring.cloud.consul.discovery.prefer-ip-address:#{'false'}}")
private boolean preferIpAddress;
@Value("${consul.token:${CONSUL_TOKEN:${spring.cloud.consul.token:${SPRING_CLOUD_CONSUL_TOKEN:${spring.cloud.consul.discovery.acl-token:}}}}}")
private String aclToken;
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public boolean isRegister() {
return register;
}
public void setRegister(boolean register) {
this.register = register;
}
public boolean isDiscoveryEnabled() {
return discoveryEnabled;
}
public void setDiscoveryEnabled(boolean discoveryEnabled) {
this.discoveryEnabled = discoveryEnabled;
}
public String getInstanceId() {
return instanceId;
}
public void setInstanceId(String instanceId) {
this.instanceId = instanceId;
}
public String getServiceName() {
return serviceName;
}
public void setServiceName(String serviceName) {
this.serviceName = serviceName;
}
public String getIpAddress() {
return ipAddress;
}
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
}
public boolean isPreferIpAddress() {
return preferIpAddress;
}
public void setPreferIpAddress(boolean preferIpAddress) {
this.preferIpAddress = preferIpAddress;
}
public String getAclToken() {
return aclToken;
}
public void setAclToken(String aclToken) {
this.aclToken = aclToken;
}
}

@ -0,0 +1,157 @@
/*
* 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.extend.consul;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Map;
import com.tencent.cloud.common.constant.OrderConstant;
import com.tencent.cloud.common.util.JacksonUtils;
import com.tencent.cloud.polaris.PolarisDiscoveryProperties;
import com.tencent.cloud.polaris.context.PolarisConfigModifier;
import com.tencent.cloud.polaris.context.config.extend.consul.ConsulProperties;
import com.tencent.cloud.polaris.context.config.extend.tsf.TsfCoreProperties;
import com.tencent.polaris.api.config.plugin.DefaultPlugins;
import com.tencent.polaris.api.utils.StringUtils;
import com.tencent.polaris.factory.config.ConfigurationImpl;
import com.tencent.polaris.factory.config.consumer.DiscoveryConfigImpl;
import com.tencent.polaris.factory.config.global.ServerConnectorConfigImpl;
import com.tencent.polaris.factory.config.provider.RegisterConfigImpl;
import com.tencent.polaris.plugins.connector.common.constant.ConsulConstant;
import io.micrometer.common.lang.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.util.CollectionUtils;
/**
* Modifier for Consul discovery.
*
* @author lingxiao.wlx, Haotian Zhang
*/
public class ConsulDiscoveryConfigModifier implements PolarisConfigModifier {
private static final Logger LOGGER = LoggerFactory.getLogger(ConsulDiscoveryConfigModifier.class);
private final PolarisDiscoveryProperties polarisDiscoveryProperties;
private final ConsulProperties consulProperties;
private final ConsulDiscoveryProperties consulDiscoveryProperties;
private final ConsulHeartbeatProperties consulHeartbeatProperties;
private final ApplicationContext context;
private final TsfCoreProperties tsfCoreProperties;
public ConsulDiscoveryConfigModifier(PolarisDiscoveryProperties polarisDiscoveryProperties, ConsulProperties consulProperties,
ConsulDiscoveryProperties consulDiscoveryProperties, ConsulHeartbeatProperties consulHeartbeatProperties,
@Nullable TsfCoreProperties tsfCoreProperties, ApplicationContext context) {
this.polarisDiscoveryProperties = polarisDiscoveryProperties;
this.consulProperties = consulProperties;
this.consulDiscoveryProperties = consulDiscoveryProperties;
this.consulHeartbeatProperties = consulHeartbeatProperties;
this.tsfCoreProperties = tsfCoreProperties;
this.context = context;
}
@Override
public void modify(ConfigurationImpl configuration) {
// init server connectors.
if (CollectionUtils.isEmpty(configuration.getGlobal().getServerConnectors())) {
configuration.getGlobal().setServerConnectors(new ArrayList<>());
}
// init consul connector.
ServerConnectorConfigImpl serverConnectorConfig = new ServerConnectorConfigImpl();
serverConnectorConfig.setId(ConsulDiscoveryUtil.ID);
serverConnectorConfig.setAddresses(
Collections.singletonList(consulProperties.getHost() + ":" + consulProperties.getPort()));
LOGGER.info("Will register to consul server: [" + consulProperties.getHost() + ":" + consulProperties.getPort() + "]");
serverConnectorConfig.setProtocol(DefaultPlugins.SERVER_CONNECTOR_CONSUL);
// set consul connector metadata.
Map<String, String> metadata = serverConnectorConfig.getMetadata();
// namespace
if (StringUtils.isNotBlank(polarisDiscoveryProperties.getNamespace())) {
metadata.put(ConsulConstant.MetadataMapKey.NAMESPACE_KEY, polarisDiscoveryProperties.getNamespace());
}
// service name
String appName = ConsulDiscoveryUtil.getAppName(consulDiscoveryProperties, context.getEnvironment());
if (StringUtils.isNotBlank(appName)) {
metadata.put(ConsulConstant.MetadataMapKey.SERVICE_NAME_KEY, ConsulDiscoveryUtil.normalizeForDns(appName));
}
// instance ID
String instanceId = ConsulDiscoveryUtil.getInstanceId(consulDiscoveryProperties, context);
if (StringUtils.isNotBlank(instanceId)) {
metadata.put(ConsulConstant.MetadataMapKey.INSTANCE_ID_KEY, instanceId);
}
// token
if (StringUtils.isNotBlank(consulProperties.getAclToken())) {
serverConnectorConfig.setToken(consulProperties.getAclToken());
}
// default query tag
if (StringUtils.isNotBlank(consulDiscoveryProperties.getDefaultQueryTag())) {
metadata.put(ConsulConstant.MetadataMapKey.QUERY_TAG_KEY, consulDiscoveryProperties.getDefaultQueryTag());
}
// query passing
metadata.put(ConsulConstant.MetadataMapKey.QUERY_PASSING_KEY, String.valueOf(consulDiscoveryProperties.isQueryPassing()));
// prefer ip address
if (consulDiscoveryProperties.isPreferIpAddress()
&& StringUtils.isNotBlank(consulDiscoveryProperties.getIpAddress())) {
metadata.put(ConsulConstant.MetadataMapKey.PREFER_IP_ADDRESS_KEY,
String.valueOf(consulDiscoveryProperties.isPreferIpAddress()));
metadata.put(ConsulConstant.MetadataMapKey.IP_ADDRESS_KEY, consulDiscoveryProperties.getIpAddress());
}
// is not prefer agent address
if (!consulDiscoveryProperties.isPreferAgentAddress()) {
metadata.put(ConsulConstant.MetadataMapKey.PREFER_IP_ADDRESS_KEY,
String.valueOf(consulDiscoveryProperties.isPreferIpAddress()));
metadata.put(ConsulConstant.MetadataMapKey.IP_ADDRESS_KEY, consulDiscoveryProperties.getHostname());
}
if (tsfCoreProperties != null) {
// tags
metadata.put(ConsulConstant.MetadataMapKey.TAGS_KEY, JacksonUtils.serialize2Json(tsfCoreProperties.getTsfTags()));
}
configuration.getGlobal().getServerConnectors().add(serverConnectorConfig);
// discovery
DiscoveryConfigImpl discoveryConfig = new DiscoveryConfigImpl();
discoveryConfig.setServerConnectorId(ConsulDiscoveryUtil.ID);
discoveryConfig.setEnable(consulDiscoveryProperties.isEnabled());
configuration.getConsumer().getDiscoveries().add(discoveryConfig);
// register
RegisterConfigImpl registerConfig = new RegisterConfigImpl();
registerConfig.setServerConnectorId(ConsulDiscoveryUtil.ID);
registerConfig.setEnable(consulDiscoveryProperties.isRegister());
configuration.getProvider().getRegisters().add(registerConfig);
// heartbeat
polarisDiscoveryProperties.setHeartbeatInterval(Long.valueOf(
consulHeartbeatProperties.computeHeartbeatInterval().toStandardDuration().getMillis()).intValue());
}
@Override
public int getOrder() {
return OrderConstant.Modifier.CONSUL_DISCOVERY_CONFIG_ORDER;
}
}

@ -0,0 +1,679 @@
/*
* 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.extend.consul;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import com.ecwid.consul.v1.ConsistencyMode;
import com.tencent.cloud.common.util.inet.PolarisInetUtils;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.commons.util.InetUtils.HostInfo;
import org.springframework.cloud.commons.util.InetUtilsProperties;
import org.springframework.core.style.ToStringCreator;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
/**
* Copy from org.springframework.cloud.consul.discovery.ConsulDiscoveryProperties.
* Defines configuration for service discovery and registration.
*
* @author Spencer Gibb
* @author Donnabell Dmello
* @author Venil Noronha
* @author Richard Kettelerij
*/
@ConfigurationProperties(ConsulDiscoveryProperties.PREFIX)
public class ConsulDiscoveryProperties {
/**
* Consul discovery properties prefix.
*/
public static final String PREFIX = "spring.cloud.consul.discovery";
protected static final String MANAGEMENT = "management";
private HostInfo hostInfo;
/** Tags to use when registering service. */
private List<String> tags = new ArrayList<>();
/** Metadata to use when registering service. */
private Map<String, String> metadata = new LinkedHashMap<>();
/** Enable tag override for the registered service. */
private Boolean enableTagOverride;
/** Is service discovery enabled? */
private boolean enabled = true;
/** Tags to use when registering management service. */
private List<String> managementTags = new ArrayList<>();
/** Enable tag override for the registered management service. */
private Boolean managementEnableTagOverride;
/** Metadata to use when registering management service. */
private Map<String, String> managementMetadata;
/** Alternate server path to invoke for health checking. */
private String healthCheckPath = "/actuator/health";
/** Custom health check url to override default. */
private String healthCheckUrl;
/** Headers to be applied to the Health Check calls. */
private Map<String, List<String>> healthCheckHeaders = new HashMap<>();
/** How often to perform the health check (e.g. 10s), defaults to 10s. */
private String healthCheckInterval = "10s";
/** Timeout for health check (e.g. 10s). */
private String healthCheckTimeout;
/**
* Timeout to deregister services critical for longer than timeout (e.g. 30m).
* Requires consul version 7.x or higher.
*/
private String healthCheckCriticalTimeout;
/**
* IP address to use when accessing service (must also set preferIpAddress to use).
*/
private String ipAddress;
/** Hostname to use when accessing server. */
private String hostname;
/** Port to register the service under (defaults to listening port). */
private Integer port;
/** Port to register the management service under (defaults to management port). */
private Integer managementPort;
private Lifecycle lifecycle = new Lifecycle();
/** Use ip address rather than hostname during registration. */
private boolean preferIpAddress = true;
/** Source of how we will determine the address to use. */
private boolean preferAgentAddress = false;
/** The delay between calls to watch consul catalog in millis, default is 1000. */
private int catalogServicesWatchDelay = 1000;
/** The number of seconds to block while watching consul catalog, default is 2. */
private int catalogServicesWatchTimeout = 55;
/** Service name. */
private String serviceName;
/** Unique service instance id. */
private String instanceId;
/** Service instance zone. */
private String instanceZone;
/** Service instance group. */
private String instanceGroup;
/**
* Whether hostname is included into the default instance id when registering service.
*/
private boolean includeHostnameInInstanceId = false;
/**
* Consistency mode for health service request.
*/
private ConsistencyMode consistencyMode = ConsistencyMode.DEFAULT;
/**
* Service instance zone comes from metadata. This allows changing the metadata tag
* name.
*/
private String defaultZoneMetadataName = "zone";
/** Whether to register an http or https service. */
private String scheme = "http";
/** Suffix to use when registering management service. */
private String managementSuffix = MANAGEMENT;
/**
* Map of serviceId's -> tag to query for in server list. This allows filtering
* services by one more tags. Multiple tags can be specified with a comma separated
* value.
*/
private Map<String, String> serverListQueryTags = new HashMap<>();
/**
* Map of serviceId's -> datacenter to query for in server list. This allows looking
* up services in another datacenters.
*/
private Map<String, String> datacenters = new HashMap<>();
/**
* Tag to query for in service list if one is not listed in serverListQueryTags.
* Multiple tags can be specified with a comma separated value.
*/
private String defaultQueryTag;
/**
* Add the 'passing` parameter to /v1/health/service/serviceName. This pushes health
* check passing to the server.
*/
private boolean queryPassing = true;
/** Register as a service in consul. */
private boolean register = true;
/** Disable automatic de-registration of service in consul. */
private boolean deregister = true;
/** Register health check in consul. Useful during development of a service. */
private boolean registerHealthCheck = true;
/**
* Throw exceptions during service registration if true, otherwise, log warnings
* (defaults to true).
*/
private boolean failFast = true;
/**
* Skips certificate verification during service checks if true, otherwise runs
* certificate verification.
*/
private Boolean healthCheckTlsSkipVerify;
/**
* Order of the discovery client used by `CompositeDiscoveryClient` for sorting
* available clients.
*/
private int order = 0;
@SuppressWarnings("unused")
private ConsulDiscoveryProperties() {
this(new PolarisInetUtils(new InetUtilsProperties()));
}
public ConsulDiscoveryProperties(PolarisInetUtils polarisInetUtils) {
this.managementTags.add(MANAGEMENT);
this.hostInfo = polarisInetUtils.findFirstNonLoopbackHostInfo();
this.ipAddress = this.hostInfo.getIpAddress();
this.hostname = this.hostInfo.getHostname();
}
/**
* Gets the tag to use when looking up the instances for a particular service. If the
* service has an entry in {@link #serverListQueryTags} that will be used. Otherwise
* the content of {@link #defaultQueryTag} will be used.
* @param serviceId the service whose instances are being looked up
* @return the tag to filter the service instances by or null if no tags are
* configured for the service and the default query tag is not configured
*/
public String getQueryTagForService(String serviceId) {
String tag = this.serverListQueryTags.get(serviceId);
return tag != null ? tag : this.defaultQueryTag;
}
/**
* Gets the array of tags to use when looking up the instances for a particular
* service. If the service has an entry in {@link #serverListQueryTags} that will be
* used. Otherwise the content of {@link #defaultQueryTag} will be used. This differs
* from {@link #getQueryTagForService(String)} in that it assumes the configured tag
* property value may represent multiple tags when separated by commas. When the tag
* property is set to a single tag then this method behaves identical to its
* aforementioned counterpart except that it returns a single element array with the
* single tag value.
* <p>
* The expected format of the tag property value is {@code tag1,tag2,..,tagN}.
* Whitespace will be trimmed off each entry.
* @param serviceId the service whose instances are being looked up
* @return the array of tags to filter the service instances by - it will be null if
* no tags are configured for the service and the default query tag is not configured
* or if a single tag is configured and it is the empty string
*/
@Nullable
public String[] getQueryTagsForService(String serviceId) {
String queryTagStr = getQueryTagForService(serviceId);
if (queryTagStr == null || queryTagStr.isEmpty()) {
return null;
}
return StringUtils.tokenizeToStringArray(queryTagStr, ",");
}
public String getHostname() {
return this.preferIpAddress ? this.ipAddress : this.hostname;
}
public void setHostname(String hostname) {
this.hostname = hostname;
this.hostInfo.override = true;
}
private HostInfo getHostInfo() {
return this.hostInfo;
}
private void setHostInfo(HostInfo hostInfo) {
this.hostInfo = hostInfo;
}
public List<String> getTags() {
return this.tags;
}
public void setTags(List<String> tags) {
this.tags = tags;
}
public boolean isEnableTagOverride() {
return enableTagOverride;
}
public Map<String, String> getMetadata() {
return metadata;
}
public void setMetadata(Map<String, String> metadata) {
this.metadata = metadata;
}
public boolean isEnabled() {
return this.enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public List<String> getManagementTags() {
return this.managementTags;
}
public void setManagementTags(List<String> managementTags) {
this.managementTags = managementTags;
}
public String getHealthCheckPath() {
return this.healthCheckPath;
}
public void setHealthCheckPath(String healthCheckPath) {
this.healthCheckPath = healthCheckPath;
}
public String getHealthCheckUrl() {
return this.healthCheckUrl;
}
public void setHealthCheckUrl(String healthCheckUrl) {
this.healthCheckUrl = healthCheckUrl;
}
public Map<String, List<String>> getHealthCheckHeaders() {
return this.healthCheckHeaders;
}
public void setHealthCheckHeaders(Map<String, List<String>> healthCheckHeaders) {
this.healthCheckHeaders = healthCheckHeaders;
}
public String getHealthCheckInterval() {
return this.healthCheckInterval;
}
public void setHealthCheckInterval(String healthCheckInterval) {
this.healthCheckInterval = healthCheckInterval;
}
public String getHealthCheckTimeout() {
return this.healthCheckTimeout;
}
public void setHealthCheckTimeout(String healthCheckTimeout) {
this.healthCheckTimeout = healthCheckTimeout;
}
public String getHealthCheckCriticalTimeout() {
return this.healthCheckCriticalTimeout;
}
public void setHealthCheckCriticalTimeout(String healthCheckCriticalTimeout) {
this.healthCheckCriticalTimeout = healthCheckCriticalTimeout;
}
public String getIpAddress() {
return this.ipAddress;
}
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
this.hostInfo.override = true;
}
public Integer getPort() {
return this.port;
}
public void setPort(Integer port) {
this.port = port;
}
public Integer getManagementPort() {
return this.managementPort;
}
public void setManagementPort(Integer managementPort) {
this.managementPort = managementPort;
}
public Lifecycle getLifecycle() {
return this.lifecycle;
}
public void setLifecycle(Lifecycle lifecycle) {
this.lifecycle = lifecycle;
}
public boolean isPreferIpAddress() {
return this.preferIpAddress;
}
public void setPreferIpAddress(boolean preferIpAddress) {
this.preferIpAddress = preferIpAddress;
}
public boolean isPreferAgentAddress() {
return this.preferAgentAddress;
}
public void setPreferAgentAddress(boolean preferAgentAddress) {
this.preferAgentAddress = preferAgentAddress;
}
public int getCatalogServicesWatchDelay() {
return this.catalogServicesWatchDelay;
}
public void setCatalogServicesWatchDelay(int catalogServicesWatchDelay) {
this.catalogServicesWatchDelay = catalogServicesWatchDelay;
}
public int getCatalogServicesWatchTimeout() {
return this.catalogServicesWatchTimeout;
}
public void setCatalogServicesWatchTimeout(int catalogServicesWatchTimeout) {
this.catalogServicesWatchTimeout = catalogServicesWatchTimeout;
}
public String getServiceName() {
return this.serviceName;
}
public void setServiceName(String serviceName) {
this.serviceName = serviceName;
}
public String getInstanceId() {
return this.instanceId;
}
public void setInstanceId(String instanceId) {
this.instanceId = instanceId;
}
public String getInstanceZone() {
return this.instanceZone;
}
public void setInstanceZone(String instanceZone) {
this.instanceZone = instanceZone;
}
public String getInstanceGroup() {
return this.instanceGroup;
}
public void setInstanceGroup(String instanceGroup) {
this.instanceGroup = instanceGroup;
}
public boolean isIncludeHostnameInInstanceId() {
return includeHostnameInInstanceId;
}
public void setIncludeHostnameInInstanceId(boolean includeHostnameInInstanceId) {
this.includeHostnameInInstanceId = includeHostnameInInstanceId;
}
public ConsistencyMode getConsistencyMode() {
return consistencyMode;
}
public void setConsistencyMode(ConsistencyMode consistencyMode) {
this.consistencyMode = consistencyMode;
}
public String getDefaultZoneMetadataName() {
return this.defaultZoneMetadataName;
}
public void setDefaultZoneMetadataName(String defaultZoneMetadataName) {
this.defaultZoneMetadataName = defaultZoneMetadataName;
}
public String getScheme() {
return this.scheme;
}
public void setScheme(String scheme) {
this.scheme = scheme;
}
public String getManagementSuffix() {
return this.managementSuffix;
}
public void setManagementSuffix(String managementSuffix) {
this.managementSuffix = managementSuffix;
}
public Map<String, String> getServerListQueryTags() {
return this.serverListQueryTags;
}
public void setServerListQueryTags(Map<String, String> serverListQueryTags) {
this.serverListQueryTags = serverListQueryTags;
}
public Map<String, String> getDatacenters() {
return this.datacenters;
}
public void setDatacenters(Map<String, String> datacenters) {
this.datacenters = datacenters;
}
public String getDefaultQueryTag() {
return this.defaultQueryTag;
}
public void setDefaultQueryTag(String defaultQueryTag) {
this.defaultQueryTag = defaultQueryTag;
}
public boolean isQueryPassing() {
return this.queryPassing;
}
public void setQueryPassing(boolean queryPassing) {
this.queryPassing = queryPassing;
}
public boolean isRegister() {
return this.register;
}
public void setRegister(boolean register) {
this.register = register;
}
public boolean isDeregister() {
return this.deregister;
}
public void setDeregister(boolean deregister) {
this.deregister = deregister;
}
public boolean isRegisterHealthCheck() {
return this.registerHealthCheck;
}
public void setRegisterHealthCheck(boolean registerHealthCheck) {
this.registerHealthCheck = registerHealthCheck;
}
public boolean isFailFast() {
return this.failFast;
}
public void setFailFast(boolean failFast) {
this.failFast = failFast;
}
public Boolean getHealthCheckTlsSkipVerify() {
return this.healthCheckTlsSkipVerify;
}
public void setHealthCheckTlsSkipVerify(Boolean healthCheckTlsSkipVerify) {
this.healthCheckTlsSkipVerify = healthCheckTlsSkipVerify;
}
public int getOrder() {
return this.order;
}
public void setOrder(int order) {
this.order = order;
}
public Map<String, String> getManagementMetadata() {
return this.managementMetadata;
}
public void setManagementMetadata(Map<String, String> managementMetadata) {
this.managementMetadata = managementMetadata;
}
public Boolean getEnableTagOverride() {
return this.enableTagOverride;
}
public void setEnableTagOverride(boolean enableTagOverride) {
this.enableTagOverride = enableTagOverride;
}
public void setEnableTagOverride(Boolean enableTagOverride) {
this.enableTagOverride = enableTagOverride;
}
public Boolean getManagementEnableTagOverride() {
return this.managementEnableTagOverride;
}
public void setManagementEnableTagOverride(Boolean managementEnableTagOverride) {
this.managementEnableTagOverride = managementEnableTagOverride;
}
@Override
public String toString() {
return new ToStringCreator(this)
.append("catalogServicesWatchDelay", this.catalogServicesWatchDelay)
.append("catalogServicesWatchTimeout", this.catalogServicesWatchTimeout)
.append("consistencyMode", this.consistencyMode)
.append("datacenters", this.datacenters)
.append("defaultQueryTag", this.defaultQueryTag)
.append("defaultZoneMetadataName", this.defaultZoneMetadataName)
.append("deregister", this.deregister)
.append("enabled", this.enabled)
.append("enableTagOverride", this.enableTagOverride)
.append("failFast", this.failFast)
.append("hostInfo", this.hostInfo)
.append("healthCheckCriticalTimeout", this.healthCheckCriticalTimeout)
.append("healthCheckHeaders", this.healthCheckHeaders)
.append("healthCheckInterval", this.healthCheckInterval)
.append("healthCheckPath", this.healthCheckPath)
.append("healthCheckTimeout", this.healthCheckTimeout)
.append("healthCheckTlsSkipVerify", this.healthCheckTlsSkipVerify)
.append("healthCheckUrl", this.healthCheckUrl)
.append("hostname", this.hostname)
.append("includeHostnameInInstanceId", this.includeHostnameInInstanceId)
.append("instanceId", this.instanceId)
.append("instanceGroup", this.instanceGroup)
.append("instanceZone", this.instanceZone)
.append("ipAddress", this.ipAddress)
.append("lifecycle", this.lifecycle)
.append("metadata", this.metadata)
.append("managementEnableTagOverride", this.managementEnableTagOverride)
.append("managementMetadata", this.managementMetadata)
.append("managementPort", this.managementPort)
.append("managementSuffix", this.managementSuffix)
.append("managementTags", this.managementTags)
.append("order", this.order)
.append("port", this.port)
.append("preferAgentAddress", this.preferAgentAddress)
.append("preferIpAddress", this.preferIpAddress)
.append("queryPassing", this.queryPassing)
.append("register", this.register)
.append("registerHealthCheck", this.registerHealthCheck)
.append("scheme", this.scheme)
.append("serviceName", this.serviceName)
.append("serverListQueryTags", this.serverListQueryTags)
.append("tags", this.tags)
.toString();
}
/**
* Properties releated to the lifecycle.
*/
public static class Lifecycle {
private boolean enabled = true;
public boolean isEnabled() {
return this.enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@Override
public String toString() {
return "Lifecycle{" + "enabled=" + this.enabled + '}';
}
}
}

@ -15,17 +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.tsf.util; package com.tencent.cloud.polaris.extend.consul;
import java.util.Map; import java.util.Map;
import com.ecwid.consul.v1.agent.model.NewService; import com.ecwid.consul.v1.agent.model.NewService;
import com.tencent.cloud.common.util.AddressUtils;
import com.tencent.cloud.common.util.JacksonUtils; import com.tencent.cloud.common.util.JacksonUtils;
import com.tencent.cloud.polaris.context.tsf.config.TsfCoreProperties; import com.tencent.cloud.polaris.context.config.extend.tsf.TsfCoreProperties;
import com.tencent.cloud.polaris.tsf.TsfDiscoveryProperties;
import com.tencent.cloud.polaris.tsf.TsfHeartbeatProperties;
import com.tencent.polaris.api.config.Configuration; import com.tencent.polaris.api.config.Configuration;
import com.tencent.polaris.api.utils.IPAddressUtils;
import com.tencent.polaris.api.utils.StringUtils;
import com.tencent.polaris.factory.config.global.ServerConnectorConfigImpl; import com.tencent.polaris.factory.config.global.ServerConnectorConfigImpl;
import com.tencent.polaris.plugins.connector.common.constant.ConsulConstant; import com.tencent.polaris.plugins.connector.common.constant.ConsulConstant;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -39,38 +38,39 @@ import org.springframework.cloud.commons.util.IdUtils;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/** /**
* TSF registration utils. * TSF registration utils.
* *
* @author Haotian Zhang * @author Haotian Zhang
*/ */
public final class RegistrationUtil { public final class ConsulDiscoveryUtil {
/** /**
* - . * - .
*/ */
public static final char SEPARATOR = '-'; public static final char SEPARATOR = '-';
/** /**
* Server connector ID. * Server connector ID.
*/ */
public static final String ID = "consul"; public static final String ID = "consul";
private static final Logger LOGGER = LoggerFactory.getLogger(RegistrationUtil.class);
private RegistrationUtil() { private static final Logger LOGGER = LoggerFactory.getLogger(ConsulDiscoveryUtil.class);
private ConsulDiscoveryUtil() {
} }
public static String getAppName(TsfDiscoveryProperties properties, Environment env) { public static String getAppName(ConsulDiscoveryProperties properties, Environment env) {
String appName = properties.getServiceName(); String appName = properties.getServiceName();
if (!StringUtils.isEmpty(appName)) { if (StringUtils.isNotBlank(appName)) {
return appName; return appName;
} }
return env.getProperty("spring.application.name", "application"); return env.getProperty("spring.application.name", "application");
} }
public static String getInstanceId(TsfCoreProperties properties, ApplicationContext context) { public static String getInstanceId(ConsulDiscoveryProperties properties, ApplicationContext context) {
// tsf consul 不支持 dns所以这里不需要 normalize并且由于优雅下线readiness probe 联动都是依赖 service id 的normalize 后两边对不上,所以需要去掉 normalize // tsf consul 不支持 dns所以这里不需要 normalize并且由于优雅下线readiness probe 联动都是依赖 service id 的normalize 后两边对不上,所以需要去掉 normalize
if (!StringUtils.hasText(properties.getInstanceId())) { if (StringUtils.isBlank(properties.getInstanceId())) {
return IdUtils.getDefaultInstanceId(context.getEnvironment(), false); return IdUtils.getDefaultInstanceId(context.getEnvironment(), false);
} }
else { else {
@ -78,17 +78,7 @@ public final class RegistrationUtil {
} }
} }
// 更新了判断逻辑,仅判断为空的场景
public static String normalizeForDns(String s) { public static String normalizeForDns(String s) {
// if (s == null || !Character.isLetter(s.charAt(0))
// || !Character.isLetterOrDigit(s.charAt(s.length()-1))) {
// throw new IllegalArgumentException("Consul service ids must not be empty,
// must start with a letter, end with a letter or digit, and have as interior
// characters only letters, digits, and hyphen");
// }
// tsf not check consul service instance id start with letter and end with
// letter or digit
if (s == null) { if (s == null) {
throw new IllegalArgumentException("Consul service ids must not be empty"); throw new IllegalArgumentException("Consul service ids must not be empty");
} }
@ -113,8 +103,8 @@ public final class RegistrationUtil {
} }
public static void setCheck(AutoServiceRegistrationProperties autoServiceRegistrationProperties, public static void setCheck(AutoServiceRegistrationProperties autoServiceRegistrationProperties,
TsfDiscoveryProperties properties, TsfCoreProperties tsfCoreProperties, ApplicationContext context, ConsulDiscoveryProperties properties, TsfCoreProperties tsfCoreProperties, ApplicationContext context,
TsfHeartbeatProperties tsfHeartbeatProperties, Registration registration, Configuration configuration) { ConsulHeartbeatProperties consulHeartbeatProperties, Registration registration, Configuration configuration) {
if (properties.isRegisterHealthCheck()) { if (properties.isRegisterHealthCheck()) {
Integer checkPort; Integer checkPort;
if (shouldRegisterManagement(autoServiceRegistrationProperties, properties, context)) { if (shouldRegisterManagement(autoServiceRegistrationProperties, properties, context)) {
@ -128,7 +118,7 @@ public final class RegistrationUtil {
for (ServerConnectorConfigImpl config : configuration.getGlobal().getServerConnectors()) { for (ServerConnectorConfigImpl config : configuration.getGlobal().getServerConnectors()) {
if (org.apache.commons.lang.StringUtils.equals(config.getId(), ID)) { if (org.apache.commons.lang.StringUtils.equals(config.getId(), ID)) {
Map<String, String> metadata = config.getMetadata(); Map<String, String> metadata = config.getMetadata();
NewService.Check check = createCheck(checkPort, tsfHeartbeatProperties, properties, tsfCoreProperties); NewService.Check check = createCheck(checkPort, consulHeartbeatProperties, properties, tsfCoreProperties);
String checkJson = JacksonUtils.serialize2Json(check); String checkJson = JacksonUtils.serialize2Json(check);
LOGGER.debug("Check is : {}", checkJson); LOGGER.debug("Check is : {}", checkJson);
metadata.put(ConsulConstant.MetadataMapKey.CHECK_KEY, checkJson); metadata.put(ConsulConstant.MetadataMapKey.CHECK_KEY, checkJson);
@ -138,8 +128,8 @@ public final class RegistrationUtil {
} }
} }
public static NewService.Check createCheck(Integer port, TsfHeartbeatProperties ttlConfig, public static NewService.Check createCheck(Integer port, ConsulHeartbeatProperties ttlConfig,
TsfDiscoveryProperties properties, TsfCoreProperties tsfCoreProperties) { ConsulDiscoveryProperties properties, TsfCoreProperties tsfCoreProperties) {
NewService.Check check = new NewService.Check(); NewService.Check check = new NewService.Check();
if (ttlConfig.isEnabled()) { if (ttlConfig.isEnabled()) {
check.setTtl(ttlConfig.getTtl()); check.setTtl(ttlConfig.getTtl());
@ -154,12 +144,12 @@ public final class RegistrationUtil {
} }
else { else {
check.setHttp(String.format("%s://%s:%s%s", tsfCoreProperties.getScheme(), check.setHttp(String.format("%s://%s:%s%s", tsfCoreProperties.getScheme(),
AddressUtils.getIpCompatible(properties.getHostname()), port, IPAddressUtils.getIpCompatible(properties.getHostname()), port,
properties.getHealthCheckPath())); properties.getHealthCheckPath()));
} }
check.setInterval(properties.getHealthCheckInterval()); check.setInterval(properties.getHealthCheckInterval());
check.setTimeout(properties.getHealthCheckTimeout()); check.setTimeout(properties.getHealthCheckTimeout());
if (StringUtils.hasText(properties.getHealthCheckCriticalTimeout())) { if (StringUtils.isNotBlank(properties.getHealthCheckCriticalTimeout())) {
check.setDeregisterCriticalServiceAfter(properties.getHealthCheckCriticalTimeout()); check.setDeregisterCriticalServiceAfter(properties.getHealthCheckCriticalTimeout());
} }
check.setTlsSkipVerify(properties.getHealthCheckTlsSkipVerify()); check.setTlsSkipVerify(properties.getHealthCheckTlsSkipVerify());
@ -169,7 +159,8 @@ public final class RegistrationUtil {
/** /**
* @return if the management service should be registered with the {@link ServiceRegistry} * @return if the management service should be registered with the {@link ServiceRegistry}
*/ */
public static boolean shouldRegisterManagement(AutoServiceRegistrationProperties autoServiceRegistrationProperties, TsfDiscoveryProperties properties, ApplicationContext context) { public static boolean shouldRegisterManagement(AutoServiceRegistrationProperties autoServiceRegistrationProperties,
ConsulDiscoveryProperties properties, ApplicationContext context) {
return autoServiceRegistrationProperties.isRegisterManagement() return autoServiceRegistrationProperties.isRegisterManagement()
&& getManagementPort(properties, context) != null && getManagementPort(properties, context) != null
&& ManagementServerPortUtils.isDifferent(context); && ManagementServerPortUtils.isDifferent(context);
@ -178,7 +169,7 @@ public final class RegistrationUtil {
/** /**
* @return the port of the Management Service * @return the port of the Management Service
*/ */
public static Integer getManagementPort(TsfDiscoveryProperties properties, ApplicationContext context) { public static Integer getManagementPort(ConsulDiscoveryProperties properties, ApplicationContext context) {
// If an alternate external port is specified, use it instead // If an alternate external port is specified, use it instead
if (properties.getManagementPort() != null) { if (properties.getManagementPort() != null) {
return properties.getManagementPort(); return properties.getManagementPort();

@ -15,24 +15,32 @@
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*/ */
package com.tencent.cloud.polaris.tsf; package com.tencent.cloud.polaris.extend.consul;
import jakarta.validation.constraints.DecimalMax; import jakarta.validation.constraints.DecimalMax;
import jakarta.validation.constraints.DecimalMin; import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.Min; import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import org.apache.commons.logging.Log;
import org.joda.time.Period; import org.joda.time.Period;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.style.ToStringCreator; import org.springframework.core.style.ToStringCreator;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@ConfigurationProperties(prefix = "tsf.discovery.heartbeat") /**
* Copy from org.springframework.cloud.consul.discovery.HeartbeatProperties.
* Properties related to heartbeat verification.
*
* @author Spencer Gibb
* @author Chris Bono
*/
@ConfigurationProperties(prefix = "spring.cloud.consul.discovery.heartbeat")
@Validated @Validated
public class TsfHeartbeatProperties { public class ConsulHeartbeatProperties {
private static final Log log = org.apache.commons.logging.LogFactory.getLog(TsfHeartbeatProperties.class); private static final Logger LOGGER = LoggerFactory.getLogger(ConsulHeartbeatProperties.class);
// TODO: change enabled to default to true when I stop seeing messages like // TODO: change enabled to default to true when I stop seeing messages like
// [WARN] agent: Check 'service:testConsulApp:xtest:8080' missed TTL, is now critical // [WARN] agent: Check 'service:testConsulApp:xtest:8080' missed TTL, is now critical
boolean enabled = true; boolean enabled = true;
@ -49,7 +57,7 @@ public class TsfHeartbeatProperties {
//TODO: did heartbeatInterval need to be a field? //TODO: did heartbeatInterval need to be a field?
protected Period computeHearbeatInterval() { protected Period computeHeartbeatInterval() {
// heartbeat rate at ratio * ttl, but no later than ttl -1s and, (under lesser // heartbeat rate at ratio * ttl, but no later than ttl -1s and, (under lesser
// priority), no sooner than 1s from now // priority), no sooner than 1s from now
double interval = ttlValue * intervalRatio; double interval = ttlValue * intervalRatio;
@ -57,7 +65,7 @@ public class TsfHeartbeatProperties {
int ttlMinus1 = ttlValue - 1; int ttlMinus1 = ttlValue - 1;
double min = Math.min(ttlMinus1, max); double min = Math.min(ttlMinus1, max);
Period heartbeatInterval = new Period(Math.round(1000 * min)); Period heartbeatInterval = new Period(Math.round(1000 * min));
log.debug("Computed heartbeatInterval: " + heartbeatInterval); LOGGER.debug("Computed heartbeatInterval: " + heartbeatInterval);
return heartbeatInterval; return heartbeatInterval;
} }

@ -26,7 +26,7 @@ import java.util.Objects;
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.config.PolarisContextProperties; import com.tencent.cloud.polaris.context.config.PolarisContextProperties;
import com.tencent.cloud.polaris.extend.consul.ConsulContextProperties; import com.tencent.cloud.polaris.extend.consul.ConsulDiscoveryProperties;
import com.tencent.cloud.polaris.extend.nacos.NacosContextProperties; import com.tencent.cloud.polaris.extend.nacos.NacosContextProperties;
import com.tencent.polaris.client.api.SDKContext; import com.tencent.polaris.client.api.SDKContext;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
@ -72,7 +72,7 @@ public class PolarisRegistration implements Registration {
public PolarisRegistration( public PolarisRegistration(
PolarisDiscoveryProperties polarisDiscoveryProperties, PolarisDiscoveryProperties polarisDiscoveryProperties,
@Nullable PolarisContextProperties polarisContextProperties, @Nullable PolarisContextProperties polarisContextProperties,
@Nullable ConsulContextProperties consulContextProperties, @Nullable ConsulDiscoveryProperties consulDiscoveryProperties,
SDKContext context, StaticMetadataManager staticMetadataManager, SDKContext context, StaticMetadataManager staticMetadataManager,
@Nullable NacosContextProperties nacosContextProperties, @Nullable NacosContextProperties nacosContextProperties,
@Nullable ServletWebServerApplicationContext servletWebServerApplicationContext, @Nullable ServletWebServerApplicationContext servletWebServerApplicationContext,
@ -133,8 +133,8 @@ public class PolarisRegistration implements Registration {
if (null != polarisDiscoveryProperties) { if (null != polarisDiscoveryProperties) {
registerEnabled = polarisDiscoveryProperties.isRegisterEnabled(); registerEnabled = polarisDiscoveryProperties.isRegisterEnabled();
} }
if (null != consulContextProperties && consulContextProperties.isEnabled()) { if (null != consulDiscoveryProperties) {
registerEnabled |= consulContextProperties.isRegister(); registerEnabled |= consulDiscoveryProperties.isRegister();
} }
if (null != nacosContextProperties && nacosContextProperties.isEnabled()) { if (null != nacosContextProperties && nacosContextProperties.isEnabled()) {
registerEnabled |= nacosContextProperties.isRegisterEnabled(); registerEnabled |= nacosContextProperties.isRegisterEnabled();
@ -143,7 +143,7 @@ public class PolarisRegistration implements Registration {
public static PolarisRegistration registration(PolarisDiscoveryProperties polarisDiscoveryProperties, public static PolarisRegistration registration(PolarisDiscoveryProperties polarisDiscoveryProperties,
@Nullable PolarisContextProperties polarisContextProperties, @Nullable PolarisContextProperties polarisContextProperties,
@Nullable ConsulContextProperties consulContextProperties, @Nullable ConsulDiscoveryProperties consulContextProperties,
SDKContext context, StaticMetadataManager staticMetadataManager, SDKContext context, StaticMetadataManager staticMetadataManager,
@Nullable NacosContextProperties nacosContextProperties, @Nullable NacosContextProperties nacosContextProperties,
@Nullable ServletWebServerApplicationContext servletWebServerApplicationContext, @Nullable ServletWebServerApplicationContext servletWebServerApplicationContext,

@ -142,6 +142,7 @@ public class PolarisServiceRegistry implements ServiceRegistry<PolarisRegistrati
instanceRegisterResponse = providerClient.register(instanceRegisterRequest); instanceRegisterResponse = providerClient.register(instanceRegisterRequest);
InstanceHeartbeatRequest heartbeatRequest = new InstanceHeartbeatRequest(); InstanceHeartbeatRequest heartbeatRequest = new InstanceHeartbeatRequest();
BeanUtils.copyProperties(instanceRegisterRequest, heartbeatRequest); BeanUtils.copyProperties(instanceRegisterRequest, heartbeatRequest);
heartbeatRequest.setInstanceID(instanceRegisterResponse.getInstanceId());
// Start the heartbeat thread after the registration is successful. // Start the heartbeat thread after the registration is successful.
heartbeat(heartbeatRequest); heartbeat(heartbeatRequest);
} }

@ -25,7 +25,7 @@ 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.ConsulDiscoveryProperties;
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;
@ -68,7 +68,7 @@ public class PolarisServiceRegistryAutoConfiguration {
public PolarisRegistration polarisRegistration( public PolarisRegistration polarisRegistration(
PolarisDiscoveryProperties polarisDiscoveryProperties, PolarisDiscoveryProperties polarisDiscoveryProperties,
PolarisContextProperties polarisContextProperties, PolarisContextProperties polarisContextProperties,
@Autowired(required = false) ConsulContextProperties consulContextProperties, @Autowired(required = false) ConsulDiscoveryProperties consulContextProperties,
PolarisSDKContextManager polarisSDKContextManager, StaticMetadataManager staticMetadataManager, PolarisSDKContextManager polarisSDKContextManager, StaticMetadataManager staticMetadataManager,
NacosContextProperties nacosContextProperties, NacosContextProperties nacosContextProperties,
@Autowired(required = false) ServletWebServerApplicationContext servletWebServerApplicationContext, @Autowired(required = false) ServletWebServerApplicationContext servletWebServerApplicationContext,

@ -1,194 +0,0 @@
/*
* 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.tsf;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Map;
import com.tencent.cloud.common.constant.OrderConstant;
import com.tencent.cloud.common.util.JacksonUtils;
import com.tencent.cloud.polaris.PolarisDiscoveryProperties;
import com.tencent.cloud.polaris.context.PolarisConfigModifier;
import com.tencent.cloud.polaris.context.config.PolarisContextProperties;
import com.tencent.cloud.polaris.context.tsf.TsfUtils;
import com.tencent.cloud.polaris.context.tsf.config.TsfCoreProperties;
import com.tencent.cloud.polaris.context.tsf.consul.TsfConsulProperties;
import com.tencent.cloud.polaris.tsf.util.RegistrationUtil;
import com.tencent.polaris.api.config.plugin.DefaultPlugins;
import com.tencent.polaris.factory.config.ConfigurationImpl;
import com.tencent.polaris.factory.config.consumer.DiscoveryConfigImpl;
import com.tencent.polaris.factory.config.global.ServerConnectorConfigImpl;
import com.tencent.polaris.factory.config.provider.RegisterConfigImpl;
import com.tencent.polaris.plugins.connector.common.constant.ConsulConstant;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.util.CollectionUtils;
/**
* Modifier for TSF discovery.
*
* @author Haotian Zhang
*/
public class TsfDiscoveryConfigModifier implements PolarisConfigModifier {
private static final Logger LOGGER = LoggerFactory.getLogger(TsfDiscoveryConfigModifier.class);
private final TsfCoreProperties tsfCoreProperties;
private final TsfConsulProperties tsfConsulProperties;
private final TsfDiscoveryProperties tsfDiscoveryProperties;
private final TsfHeartbeatProperties tsfHeartbeatProperties;
private final PolarisDiscoveryProperties polarisDiscoveryProperties;
private final PolarisContextProperties polarisContextProperties;
private final ApplicationContext context;
public TsfDiscoveryConfigModifier(TsfCoreProperties tsfCoreProperties, TsfConsulProperties tsfConsulProperties,
TsfDiscoveryProperties tsfDiscoveryProperties, TsfHeartbeatProperties tsfHeartbeatProperties,
PolarisDiscoveryProperties polarisDiscoveryProperties, PolarisContextProperties polarisContextProperties, ApplicationContext context) {
this.tsfCoreProperties = tsfCoreProperties;
this.tsfConsulProperties = tsfConsulProperties;
this.tsfDiscoveryProperties = tsfDiscoveryProperties;
this.tsfHeartbeatProperties = tsfHeartbeatProperties;
this.polarisDiscoveryProperties = polarisDiscoveryProperties;
this.polarisContextProperties = polarisContextProperties;
this.context = context;
}
@Override
public void modify(ConfigurationImpl configuration) {
// namespace id
polarisDiscoveryProperties.setHeartbeatInterval(Long.valueOf(tsfHeartbeatProperties.computeHearbeatInterval()
.toStandardDuration().getMillis()).intValue());
polarisContextProperties.setNamespace(tsfCoreProperties.getTsfNamespaceId());
polarisDiscoveryProperties.setNamespace(tsfCoreProperties.getTsfNamespaceId());
System.setProperty("spring.cloud.polaris.namespace", tsfCoreProperties.getTsfNamespaceId());
// application id
polarisDiscoveryProperties.setVersion(tsfCoreProperties.getTsfProgVersion());
// instance id
polarisDiscoveryProperties.setInstanceId(tsfCoreProperties.getInstanceId());
boolean consulEnable = tsfCoreProperties.isTsfConsulEnable();
boolean polarisEnable = tsfCoreProperties.isTsePolarisEnable();
// 删除可能存在的consul connector配置
if (!CollectionUtils.isEmpty(configuration.getGlobal().getServerConnectors())) {
for (ServerConnectorConfigImpl config : configuration.getGlobal().getServerConnectors()) {
if (StringUtils.equals(config.getId(), RegistrationUtil.ID)) {
configuration.getGlobal().getServerConnectors().remove(config);
}
}
}
else {
configuration.getGlobal().setServerConnectors(new ArrayList<>());
}
// 删除可能存在的consul发现配置
for (DiscoveryConfigImpl dc : configuration.getConsumer().getDiscoveries()) {
if (StringUtils.equals(dc.getServerConnectorId(), RegistrationUtil.ID)) {
configuration.getConsumer().getDiscoveries().remove(dc);
}
}
// 删除可能存在的consul注册配置
for (RegisterConfigImpl rc : configuration.getProvider().getRegisters()) {
if (StringUtils.equals(rc.getServerConnectorId(), RegistrationUtil.ID)) {
configuration.getProvider().getRegisters().remove(rc);
}
}
// 如果ServerConnectors为空则把ServerConnector如有复制过去
if (CollectionUtils.isEmpty(configuration.getGlobal().getServerConnectors())
&& null != configuration.getGlobal().getServerConnector()) {
configuration.getGlobal().getServerConnectors().add(configuration.getGlobal().getServerConnector());
}
if (consulEnable) {
// enable consul
ServerConnectorConfigImpl serverConnectorConfig = new ServerConnectorConfigImpl();
serverConnectorConfig.setId(RegistrationUtil.ID);
serverConnectorConfig.setAddresses(
Collections.singletonList(tsfConsulProperties.getHost() + ":" + tsfConsulProperties.getPort()));
LOGGER.info("Will register to consul server: [" + tsfConsulProperties.getHost() + ":" + tsfConsulProperties.getPort() + "]");
serverConnectorConfig.setProtocol(DefaultPlugins.SERVER_CONNECTOR_CONSUL);
Map<String, String> metadata = serverConnectorConfig.getMetadata();
String appName = RegistrationUtil.getAppName(tsfDiscoveryProperties, context.getEnvironment());
metadata.put(ConsulConstant.MetadataMapKey.SERVICE_NAME_KEY, RegistrationUtil.normalizeForDns(appName));
metadata.put(ConsulConstant.MetadataMapKey.INSTANCE_ID_KEY, RegistrationUtil.getInstanceId(tsfCoreProperties, context));
if (StringUtils.isNotBlank(tsfConsulProperties.getAclToken())) {
serverConnectorConfig.setToken(tsfConsulProperties.getAclToken());
}
metadata.put(ConsulConstant.MetadataMapKey.TAGS_KEY, JacksonUtils.serialize2Json(TsfUtils.createTags(tsfCoreProperties)));
if (StringUtils.isNotBlank(tsfDiscoveryProperties.getDefaultQueryTag())) {
metadata.put(ConsulConstant.MetadataMapKey.QUERY_TAG_KEY, tsfDiscoveryProperties.getDefaultQueryTag());
}
metadata.put(ConsulConstant.MetadataMapKey.QUERY_PASSING_KEY, String.valueOf(tsfDiscoveryProperties.isQueryPassing()));
if (tsfDiscoveryProperties.isPreferIpAddress()
&& StringUtils.isNotBlank(tsfDiscoveryProperties.getIpAddress())) {
metadata.put(ConsulConstant.MetadataMapKey.PREFER_IP_ADDRESS_KEY,
String.valueOf(tsfDiscoveryProperties.isPreferIpAddress()));
metadata.put(ConsulConstant.MetadataMapKey.IP_ADDRESS_KEY, tsfDiscoveryProperties.getIpAddress());
}
if (!tsfDiscoveryProperties.isPreferAgentAddress()) {
metadata.put(ConsulConstant.MetadataMapKey.PREFER_IP_ADDRESS_KEY,
String.valueOf(tsfDiscoveryProperties.isPreferIpAddress()));
metadata.put(ConsulConstant.MetadataMapKey.IP_ADDRESS_KEY, tsfDiscoveryProperties.getHostname());
}
configuration.getGlobal().getServerConnectors().add(serverConnectorConfig);
// 添加发现配置
DiscoveryConfigImpl discoveryConfig = new DiscoveryConfigImpl();
discoveryConfig.setServerConnectorId(RegistrationUtil.ID);
discoveryConfig.setEnable(tsfDiscoveryProperties.isEnabled());
configuration.getConsumer().getDiscoveries().add(discoveryConfig);
// 添加注册配置
RegisterConfigImpl registerConfig = new RegisterConfigImpl();
registerConfig.setServerConnectorId(RegistrationUtil.ID);
registerConfig.setEnable(tsfDiscoveryProperties.isRegister());
configuration.getProvider().getRegisters().add(registerConfig);
}
if (polarisDiscoveryProperties != null) {
if (!polarisEnable) {
configuration.getGlobal().getAPI().setReportEnable(false);
for (DiscoveryConfigImpl dc : configuration.getConsumer().getDiscoveries()) {
if (StringUtils.equals(dc.getServerConnectorId(), "polaris")) {
dc.setEnable(false);
}
}
for (RegisterConfigImpl rc : configuration.getProvider().getRegisters()) {
if (StringUtils.equals(rc.getServerConnectorId(), "polaris")) {
rc.setEnable(false);
rc.setReportServiceContractEnable(false);
}
}
}
}
}
@Override
public int getOrder() {
return OrderConstant.Modifier.CONSUL_DISCOVERY_CONFIG_ORDER + 1;
}
}

@ -1,550 +0,0 @@
/*
* 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.tsf;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.tencent.cloud.common.util.inet.PolarisInetUtils;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.commons.util.InetUtils;
/**
* Defines configuration for service discovery and registration.
*
* @author Spencer Gibb
* @author Donnabell Dmello
* @author Venil Noronha
* @author Richard Kettelerij
*/
@ConfigurationProperties("tsf.discovery")
public class TsfDiscoveryProperties {
protected static final String MANAGEMENT = "management";
private InetUtils.HostInfo hostInfo;
/**
* If service discovery enabled.
*/
private boolean enabled = true;
/**
* Tags to use when registering management service.
*/
private List<String> managementTags = new ArrayList<>();
/**
* Alternate server path to invoke for health checking .
*/
private String healthCheckPath = "/actuator/health";
/**
* Custom health check url to override default.
*/
private String healthCheckUrl;
/**
* How often to perform the health check (e.g. 10s), defaults to 10s.
*/
private String healthCheckInterval = "10s";
/**
* Timeout for health check (e.g. 10s).
*/
private String healthCheckTimeout;
/**
* Timeout to deregister services critical for longer than timeout (e.g. 30m).
* Requires consul version 7.x or higher.
*/
private String healthCheckCriticalTimeout;
/**
* IP address to use when accessing service (must also set preferIpAddress to use).
*/
private String ipAddress;
/**
* Hostname to use when accessing server.
*/
private String hostname;
/**
* Port to register the service under (defaults to listening port).
*/
private Integer port;
/**
* Port to register the management service under (defaults to management port).
*/
private Integer managementPort;
private Lifecycle lifecycle = new Lifecycle();
/**
* Use ip address rather than hostname during registration.
* 使IP
*/
private boolean preferIpAddress = true;
/**
* Source of how we will determine the address to use.
*/
private boolean preferAgentAddress = false;
/**
* The delay between calls to watch consul catalog in millis, default is 1000.
*/
private int catalogServicesWatchDelay = 1000;
/**
* The number of seconds to block while watching consul catalog, default is 2.
*/
private int catalogServicesWatchTimeout = 55;
/**
* Service name.
*/
private String serviceName;
/**
* Suffix to use when registering management service.
*/
private String managementSuffix = MANAGEMENT;
/**
* Map of serviceId's -> tag to query for in server list.
* This allows filtering services by a single tag.
*/
private Map<String, String> serverListQueryTags = new HashMap<>();
/**
* Map of serviceId's -> datacenter to query for in server list.
* This allows looking up services in another datacenters.
*/
private Map<String, String> datacenters = new HashMap<>();
/**
* Tag to query for in service list if one is not listed in serverListQueryTags.
*/
private String defaultQueryTag;
/**
* Add the 'passing` parameter to /v1/health/service/serviceName.
* This pushes health check passing to the server.
*/
private boolean queryPassing = true;
/**
* Register as a service in consul.
*/
private boolean register = true;
/**
* Disable automatic de-registration of service in consul.
*/
private boolean deregister = true;
/**
* Register health check in consul. Useful during development of a service.
*/
private boolean registerHealthCheck = true;
/**
* Throw exceptions during service registration if true, otherwise, log
* warnings (defaults to true).
*/
private boolean failFast = true;
/**
* Skips certificate verification during service checks if true, otherwise
* runs certificate verification.
*/
private Boolean healthCheckTlsSkipVerify;
/**
* 线.
*/
private int callbackPoolSize = 10;
private long callbackInitialDelay = 10 * 1000L;
private long callbackErrorDelay = 30 * 1000L;
/**
* consul 线0线provider线.
* provider线 consul .
*/
private boolean zeroInstanceProtect = true;
private int testConnectivityTimeout = 5000;
private Map<String, String> serviceMeta;
@SuppressWarnings("unused")
private TsfDiscoveryProperties() {
this.managementTags.add(MANAGEMENT);
}
public TsfDiscoveryProperties(PolarisInetUtils polarisInetUtils) {
this();
this.hostInfo = polarisInetUtils.findFirstNonLoopbackHostInfo();
this.ipAddress = this.hostInfo.getIpAddress();
this.hostname = this.hostInfo.getHostname();
}
/**
* @param serviceId The service who's filtering tag is being looked up
* @return The tag the given service id should be filtered by, or null.
*/
public String getQueryTagForService(String serviceId) {
String tag = serverListQueryTags.get(serviceId);
return tag != null ? tag : defaultQueryTag;
}
public String getHostname() {
return this.preferIpAddress ? this.ipAddress : this.hostname;
}
public void setHostname(String hostname) {
this.hostname = hostname;
this.hostInfo.override = true;
}
private InetUtils.HostInfo getHostInfo() {
return hostInfo;
}
private void setHostInfo(InetUtils.HostInfo hostInfo) {
this.hostInfo = hostInfo;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public List<String> getManagementTags() {
return managementTags;
}
public void setManagementTags(List<String> managementTags) {
this.managementTags = managementTags;
}
public String getHealthCheckPath() {
return healthCheckPath;
}
public void setHealthCheckPath(String healthCheckPath) {
this.healthCheckPath = healthCheckPath;
}
public String getHealthCheckUrl() {
return healthCheckUrl;
}
public void setHealthCheckUrl(String healthCheckUrl) {
this.healthCheckUrl = healthCheckUrl;
}
public String getHealthCheckInterval() {
return healthCheckInterval;
}
public void setHealthCheckInterval(String healthCheckInterval) {
this.healthCheckInterval = healthCheckInterval;
}
public String getHealthCheckTimeout() {
return healthCheckTimeout;
}
public void setHealthCheckTimeout(String healthCheckTimeout) {
this.healthCheckTimeout = healthCheckTimeout;
}
public String getHealthCheckCriticalTimeout() {
return healthCheckCriticalTimeout;
}
public void setHealthCheckCriticalTimeout(String healthCheckCriticalTimeout) {
this.healthCheckCriticalTimeout = healthCheckCriticalTimeout;
}
public String getIpAddress() {
return ipAddress;
}
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
this.hostInfo.override = true;
}
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
this.port = port;
}
public Integer getManagementPort() {
return managementPort;
}
public void setManagementPort(Integer managementPort) {
this.managementPort = managementPort;
}
public Lifecycle getLifecycle() {
return lifecycle;
}
public void setLifecycle(Lifecycle lifecycle) {
this.lifecycle = lifecycle;
}
public boolean isPreferIpAddress() {
return preferIpAddress;
}
public void setPreferIpAddress(boolean preferIpAddress) {
this.preferIpAddress = preferIpAddress;
}
public boolean isPreferAgentAddress() {
return preferAgentAddress;
}
public void setPreferAgentAddress(boolean preferAgentAddress) {
this.preferAgentAddress = preferAgentAddress;
}
public int getCatalogServicesWatchDelay() {
return catalogServicesWatchDelay;
}
public void setCatalogServicesWatchDelay(int catalogServicesWatchDelay) {
this.catalogServicesWatchDelay = catalogServicesWatchDelay;
}
public int getCatalogServicesWatchTimeout() {
return catalogServicesWatchTimeout;
}
public void setCatalogServicesWatchTimeout(int catalogServicesWatchTimeout) {
this.catalogServicesWatchTimeout = catalogServicesWatchTimeout;
}
public String getServiceName() {
return serviceName;
}
public void setServiceName(String serviceName) {
this.serviceName = serviceName;
}
public String getManagementSuffix() {
return managementSuffix;
}
public void setManagementSuffix(String managementSuffix) {
this.managementSuffix = managementSuffix;
}
public Map<String, String> getServerListQueryTags() {
return serverListQueryTags;
}
public void setServerListQueryTags(Map<String, String> serverListQueryTags) {
this.serverListQueryTags = serverListQueryTags;
}
public Map<String, String> getDatacenters() {
return datacenters;
}
public void setDatacenters(Map<String, String> datacenters) {
this.datacenters = datacenters;
}
public String getDefaultQueryTag() {
return defaultQueryTag;
}
public void setDefaultQueryTag(String defaultQueryTag) {
this.defaultQueryTag = defaultQueryTag;
}
public boolean isQueryPassing() {
return queryPassing;
}
public void setQueryPassing(boolean queryPassing) {
this.queryPassing = queryPassing;
}
public boolean isRegister() {
return register;
}
public void setRegister(boolean register) {
this.register = register;
}
public boolean isDeregister() {
return deregister;
}
public void setDeregister(boolean deregister) {
this.deregister = deregister;
}
public boolean isRegisterHealthCheck() {
return registerHealthCheck;
}
public void setRegisterHealthCheck(boolean registerHealthCheck) {
this.registerHealthCheck = registerHealthCheck;
}
public boolean isFailFast() {
return failFast;
}
public void setFailFast(boolean failFast) {
this.failFast = failFast;
}
public Boolean getHealthCheckTlsSkipVerify() {
return healthCheckTlsSkipVerify;
}
public void setHealthCheckTlsSkipVerify(Boolean healthCheckTlsSkipVerify) {
this.healthCheckTlsSkipVerify = healthCheckTlsSkipVerify;
}
public Map<String, String> getServiceMeta() {
return serviceMeta;
}
public void setServiceMeta(final Map<String, String> serviceMeta) {
this.serviceMeta = serviceMeta;
}
public int getCallbackPoolSize() {
return callbackPoolSize;
}
public void setCallbackPoolSize(int callbackPoolSize) {
this.callbackPoolSize = callbackPoolSize;
}
public long getCallbackInitialDelay() {
return callbackInitialDelay;
}
public void setCallbackInitialDelay(long callbackInitialDelay) {
this.callbackInitialDelay = callbackInitialDelay;
}
public long getCallbackErrorDelay() {
return callbackErrorDelay;
}
public void setCallbackErrorDelay(long callbackErrorDelay) {
this.callbackErrorDelay = callbackErrorDelay;
}
public boolean isZeroInstanceProtect() {
return zeroInstanceProtect;
}
public void setZeroInstanceProtect(boolean zeroInstanceProtect) {
this.zeroInstanceProtect = zeroInstanceProtect;
}
public int getTestConnectivityTimeout() {
return testConnectivityTimeout;
}
public void setTestConnectivityTimeout(int testConnectivityTimeout) {
this.testConnectivityTimeout = testConnectivityTimeout;
}
@Override
public String toString() {
return "ConsulDiscoveryProperties{" +
"hostInfo=" + hostInfo +
", enabled=" + enabled +
", managementTags=" + managementTags +
", healthCheckPath='" + healthCheckPath + '\'' +
", healthCheckUrl='" + healthCheckUrl + '\'' +
", healthCheckInterval='" + healthCheckInterval + '\'' +
", healthCheckTimeout='" + healthCheckTimeout + '\'' +
", healthCheckCriticalTimeout='" + healthCheckCriticalTimeout + '\'' +
", ipAddress='" + ipAddress + '\'' +
", hostname='" + hostname + '\'' +
", port=" + port +
", managementPort=" + managementPort +
", lifecycle=" + lifecycle +
", preferIpAddress=" + preferIpAddress +
", preferAgentAddress=" + preferAgentAddress +
", catalogServicesWatchDelay=" + catalogServicesWatchDelay +
", catalogServicesWatchTimeout=" + catalogServicesWatchTimeout +
", serviceName='" + serviceName + '\'' +
", managementSuffix='" + managementSuffix + '\'' +
", serverListQueryTags=" + serverListQueryTags +
", datacenters=" + datacenters +
", defaultQueryTag='" + defaultQueryTag + '\'' +
", queryPassing=" + queryPassing +
", register=" + register +
", deregister=" + deregister +
", registerHealthCheck=" + registerHealthCheck +
", failFast=" + failFast +
", healthCheckTlsSkipVerify=" + healthCheckTlsSkipVerify +
'}';
}
public static class Lifecycle {
private boolean enabled = true;
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@Override
public String toString() {
return "Lifecycle{" +
"enabled=" + enabled +
'}';
}
}
}

@ -1,83 +0,0 @@
/*
* 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.tsf;
import com.tencent.cloud.common.tsf.ConditionalOnTsfEnabled;
import com.tencent.cloud.common.util.inet.PolarisInetUtils;
import com.tencent.cloud.plugin.lossless.config.LosslessProperties;
import com.tencent.cloud.polaris.PolarisDiscoveryProperties;
import com.tencent.cloud.polaris.context.config.PolarisContextProperties;
import com.tencent.cloud.polaris.context.tsf.config.TsfCoreProperties;
import com.tencent.cloud.polaris.context.tsf.consul.TsfConsulProperties;
import com.tencent.cloud.polaris.tsf.lossless.TsfLosslessConfigModifier;
import com.tencent.cloud.polaris.tsf.lossless.TsfLosslessProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Auto configuration for TSF discovery.
*
* @author Haotian Zhang
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnTsfEnabled
public class TsfDiscoveryPropertiesAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public TsfDiscoveryProperties tsfDiscoveryProperties(PolarisInetUtils polarisInetUtils) {
return new TsfDiscoveryProperties(polarisInetUtils);
}
@Bean
@ConditionalOnMissingBean
public TsfHeartbeatProperties tsfHeartbeatProperties() {
return new TsfHeartbeatProperties();
}
@Bean
@ConditionalOnMissingBean
public TsfLosslessProperties tsfLosslessProperties() {
return new TsfLosslessProperties();
}
@Bean
@ConditionalOnMissingBean
public TsfDiscoveryConfigModifier tsfDiscoveryConfigModifier(TsfCoreProperties tsfCoreProperties,
TsfConsulProperties tsfConsulProperties, TsfDiscoveryProperties tsfDiscoveryProperties,
TsfHeartbeatProperties tsfHeartbeatProperties, PolarisDiscoveryProperties polarisDiscoveryProperties,
PolarisContextProperties polarisContextProperties, ApplicationContext context) {
return new TsfDiscoveryConfigModifier(tsfCoreProperties, tsfConsulProperties, tsfDiscoveryProperties,
tsfHeartbeatProperties, polarisDiscoveryProperties, polarisContextProperties, context);
}
@Bean
@ConditionalOnMissingBean
public TsfZeroProtectionConfigModifier tsfZeroProtectionConfigModifier() {
return new TsfZeroProtectionConfigModifier();
}
@Bean
@ConditionalOnMissingBean
public TsfLosslessConfigModifier tsfLosslessConfigModifier(LosslessProperties losslessProperties, TsfLosslessProperties tsfLosslessProperties) {
return new TsfLosslessConfigModifier(losslessProperties, tsfLosslessProperties);
}
}

@ -1,39 +0,0 @@
/*
* 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.tsf;
import com.tencent.cloud.common.tsf.ConditionalOnTsfEnabled;
import com.tencent.cloud.polaris.DiscoveryPropertiesAutoConfiguration;
import org.springframework.cloud.commons.util.UtilAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* Bootstrap configuration for TSF discovery.
*
* @author Haotian Zhang
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnTsfEnabled
@Import({TsfDiscoveryPropertiesAutoConfiguration.class,
DiscoveryPropertiesAutoConfiguration.class,
UtilAutoConfiguration.class})
public class TsfDiscoveryPropertiesBootstrapConfiguration {
}

@ -1,40 +0,0 @@
/*
* 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.tsf;
import com.tencent.cloud.common.constant.OrderConstant;
import com.tencent.cloud.polaris.context.PolarisConfigModifier;
import com.tencent.polaris.factory.config.ConfigurationImpl;
/**
* Modifier for TSF discovery zero protection.
*
* @author Haotian Zhang
*/
public class TsfZeroProtectionConfigModifier implements PolarisConfigModifier {
@Override
public void modify(ConfigurationImpl configuration) {
configuration.getConsumer().getZeroProtection().setEnable(true);
configuration.getConsumer().getZeroProtection().setNeedTestConnectivity(true);
}
@Override
public int getOrder() {
return OrderConstant.Modifier.DISCOVERY_ORDER + 1;
}
}

@ -1,50 +0,0 @@
/*
* 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.tsf.lossless;
import com.tencent.cloud.common.constant.OrderConstant;
import com.tencent.cloud.plugin.lossless.config.LosslessProperties;
import com.tencent.cloud.polaris.context.PolarisConfigModifier;
import com.tencent.polaris.factory.config.ConfigurationImpl;
/**
* Modifier for TSF lossless online offline.
*
* @author Haotian Zhang
*/
public class TsfLosslessConfigModifier implements PolarisConfigModifier {
private final LosslessProperties losslessProperties;
private final TsfLosslessProperties tsfLosslessProperties;
public TsfLosslessConfigModifier(LosslessProperties losslessProperties, TsfLosslessProperties tsfLosslessProperties) {
this.losslessProperties = losslessProperties;
this.tsfLosslessProperties = tsfLosslessProperties;
}
@Override
public void modify(ConfigurationImpl configuration) {
losslessProperties.setEnabled(true);
losslessProperties.setPort(tsfLosslessProperties.getPort());
}
@Override
public int getOrder() {
return OrderConstant.Modifier.LOSSLESS_ORDER - 1;
}
}

@ -1,48 +0,0 @@
/*
* 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.tsf.lossless;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* 线.
*
* @author Haotian Zhang
*/
@ConfigurationProperties("tsf.discovery.lossless")
public class TsfLosslessProperties {
@Value("${tsf.discovery.lossless.port:${tsf_sctt_extensions_port:11134}}")
private int port = 11134;
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
@Override
public String toString() {
return "TsfLosslessProperties{" +
"port=" + port +
'}';
}
}

@ -17,12 +17,12 @@
package com.tencent.cloud.polaris.tsf.registry; package com.tencent.cloud.polaris.tsf.registry;
import com.tencent.cloud.common.tsf.ConditionalOnTsfEnabled; import com.tencent.cloud.common.tsf.ConditionalOnTsfConsulEnabled;
import com.tencent.cloud.polaris.context.PolarisSDKContextManager; import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
import com.tencent.cloud.polaris.context.tsf.config.TsfCoreProperties; import com.tencent.cloud.polaris.context.config.extend.tsf.TsfCoreProperties;
import com.tencent.cloud.polaris.extend.consul.ConsulDiscoveryProperties;
import com.tencent.cloud.polaris.extend.consul.ConsulHeartbeatProperties;
import com.tencent.cloud.polaris.registry.PolarisServiceRegistryAutoConfiguration; import com.tencent.cloud.polaris.registry.PolarisServiceRegistryAutoConfiguration;
import com.tencent.cloud.polaris.tsf.TsfDiscoveryProperties;
import com.tencent.cloud.polaris.tsf.TsfHeartbeatProperties;
import jakarta.servlet.ServletContext; import jakarta.servlet.ServletContext;
import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.ObjectProvider;
@ -41,7 +41,7 @@ import org.springframework.context.annotation.Configuration;
* @author Haotian Zhang * @author Haotian Zhang
*/ */
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@ConditionalOnTsfEnabled @ConditionalOnTsfConsulEnabled
@AutoConfigureBefore(PolarisServiceRegistryAutoConfiguration.class) @AutoConfigureBefore(PolarisServiceRegistryAutoConfiguration.class)
public class TsfDiscoveryRegistryAutoConfiguration { public class TsfDiscoveryRegistryAutoConfiguration {
@ -49,10 +49,10 @@ public class TsfDiscoveryRegistryAutoConfiguration {
@ConditionalOnMissingBean @ConditionalOnMissingBean
public TsfPortPolarisRegistrationCustomizer tsfPortPolarisRegistrationCustomizer( public TsfPortPolarisRegistrationCustomizer tsfPortPolarisRegistrationCustomizer(
AutoServiceRegistrationProperties autoServiceRegistrationProperties, AutoServiceRegistrationProperties autoServiceRegistrationProperties,
ApplicationContext context, TsfDiscoveryProperties tsfDiscoveryProperties, TsfCoreProperties tsfCoreProperties, ApplicationContext context, ConsulDiscoveryProperties consulDiscoveryProperties, TsfCoreProperties tsfCoreProperties,
TsfHeartbeatProperties tsfHeartbeatProperties, PolarisSDKContextManager polarisSDKContextManager) { ConsulHeartbeatProperties consulHeartbeatProperties, PolarisSDKContextManager polarisSDKContextManager) {
return new TsfPortPolarisRegistrationCustomizer(autoServiceRegistrationProperties, context, return new TsfPortPolarisRegistrationCustomizer(autoServiceRegistrationProperties, context,
tsfDiscoveryProperties, tsfCoreProperties, tsfHeartbeatProperties, polarisSDKContextManager.getSDKContext()); consulDiscoveryProperties, tsfCoreProperties, consulHeartbeatProperties, polarisSDKContextManager.getSDKContext());
} }
@Bean @Bean

@ -17,12 +17,12 @@
package com.tencent.cloud.polaris.tsf.registry; package com.tencent.cloud.polaris.tsf.registry;
import com.tencent.cloud.polaris.context.tsf.config.TsfCoreProperties; import com.tencent.cloud.polaris.context.config.extend.tsf.TsfCoreProperties;
import com.tencent.cloud.polaris.extend.consul.ConsulDiscoveryProperties;
import com.tencent.cloud.polaris.extend.consul.ConsulDiscoveryUtil;
import com.tencent.cloud.polaris.extend.consul.ConsulHeartbeatProperties;
import com.tencent.cloud.polaris.registry.PolarisRegistration; import com.tencent.cloud.polaris.registry.PolarisRegistration;
import com.tencent.cloud.polaris.registry.PolarisRegistrationCustomizer; import com.tencent.cloud.polaris.registry.PolarisRegistrationCustomizer;
import com.tencent.cloud.polaris.tsf.TsfDiscoveryProperties;
import com.tencent.cloud.polaris.tsf.TsfHeartbeatProperties;
import com.tencent.cloud.polaris.tsf.util.RegistrationUtil;
import com.tencent.polaris.client.api.SDKContext; import com.tencent.polaris.client.api.SDKContext;
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties; import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties;
@ -37,29 +37,29 @@ public class TsfPortPolarisRegistrationCustomizer implements PolarisRegistration
private final AutoServiceRegistrationProperties autoServiceRegistrationProperties; private final AutoServiceRegistrationProperties autoServiceRegistrationProperties;
private final ApplicationContext context; private final ApplicationContext context;
private final TsfDiscoveryProperties tsfDiscoveryProperties; private final ConsulDiscoveryProperties consulDiscoveryProperties;
private final TsfCoreProperties tsfCoreProperties; private final TsfCoreProperties tsfCoreProperties;
private final TsfHeartbeatProperties tsfHeartbeatProperties; private final ConsulHeartbeatProperties consulHeartbeatProperties;
private final SDKContext sdkContext; private final SDKContext sdkContext;
public TsfPortPolarisRegistrationCustomizer(AutoServiceRegistrationProperties autoServiceRegistrationProperties, public TsfPortPolarisRegistrationCustomizer(AutoServiceRegistrationProperties autoServiceRegistrationProperties,
ApplicationContext context, TsfDiscoveryProperties tsfDiscoveryProperties, TsfCoreProperties tsfCoreProperties, ApplicationContext context, ConsulDiscoveryProperties consulDiscoveryProperties, TsfCoreProperties tsfCoreProperties,
TsfHeartbeatProperties tsfHeartbeatProperties, SDKContext sdkContext) { ConsulHeartbeatProperties consulHeartbeatProperties, SDKContext sdkContext) {
this.autoServiceRegistrationProperties = autoServiceRegistrationProperties; this.autoServiceRegistrationProperties = autoServiceRegistrationProperties;
this.context = context; this.context = context;
this.tsfDiscoveryProperties = tsfDiscoveryProperties; this.consulDiscoveryProperties = consulDiscoveryProperties;
this.tsfCoreProperties = tsfCoreProperties; this.tsfCoreProperties = tsfCoreProperties;
this.tsfHeartbeatProperties = tsfHeartbeatProperties; this.consulHeartbeatProperties = consulHeartbeatProperties;
this.sdkContext = sdkContext; this.sdkContext = sdkContext;
} }
@Override @Override
public void customize(PolarisRegistration registration) { public void customize(PolarisRegistration registration) {
if (tsfDiscoveryProperties.getPort() != null) { if (consulDiscoveryProperties.getPort() != null) {
registration.setPort(tsfDiscoveryProperties.getPort()); registration.setPort(consulDiscoveryProperties.getPort());
} }
// we know the port and can set the check // we know the port and can set the check
RegistrationUtil.setCheck(autoServiceRegistrationProperties, tsfDiscoveryProperties, tsfCoreProperties, context, ConsulDiscoveryUtil.setCheck(autoServiceRegistrationProperties, consulDiscoveryProperties, tsfCoreProperties, context,
tsfHeartbeatProperties, registration, sdkContext.getConfig()); consulHeartbeatProperties, registration, sdkContext.getConfig());
} }
} }

@ -1,3 +1,2 @@
org.springframework.cloud.bootstrap.BootstrapConfiguration=\ org.springframework.cloud.bootstrap.BootstrapConfiguration=\
com.tencent.cloud.polaris.DiscoveryPropertiesBootstrapAutoConfiguration,\ com.tencent.cloud.polaris.DiscoveryPropertiesBootstrapAutoConfiguration
com.tencent.cloud.polaris.tsf.TsfDiscoveryPropertiesBootstrapConfiguration

@ -3,5 +3,4 @@ com.tencent.cloud.polaris.discovery.PolarisDiscoveryAutoConfiguration
com.tencent.cloud.polaris.registry.PolarisServiceRegistryAutoConfiguration com.tencent.cloud.polaris.registry.PolarisServiceRegistryAutoConfiguration
com.tencent.cloud.polaris.endpoint.PolarisDiscoveryEndpointAutoConfiguration com.tencent.cloud.polaris.endpoint.PolarisDiscoveryEndpointAutoConfiguration
com.tencent.cloud.polaris.loadbalancer.PolarisLoadBalancerAutoConfiguration com.tencent.cloud.polaris.loadbalancer.PolarisLoadBalancerAutoConfiguration
com.tencent.cloud.polaris.tsf.TsfDiscoveryPropertiesAutoConfiguration
com.tencent.cloud.polaris.tsf.registry.TsfDiscoveryRegistryAutoConfiguration com.tencent.cloud.polaris.tsf.registry.TsfDiscoveryRegistryAutoConfiguration

@ -19,7 +19,7 @@ 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.ConsulDiscoveryProperties;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
@ -43,7 +43,7 @@ public class DiscoveryPropertiesAutoConfigurationTest {
applicationContextRunner.run(context -> { applicationContextRunner.run(context -> {
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).doesNotHaveBean(ConsulDiscoveryProperties.class);
assertThat(context).hasSingleBean(PolarisDiscoveryHandler.class); assertThat(context).hasSingleBean(PolarisDiscoveryHandler.class);
assertThat(context).hasSingleBean(DiscoveryConfigModifier.class); assertThat(context).hasSingleBean(DiscoveryConfigModifier.class);
}); });

@ -37,21 +37,20 @@ import static com.tencent.polaris.plugins.connector.common.constant.ConsulConsta
import static com.tencent.polaris.plugins.connector.common.constant.ConsulConstant.MetadataMapKey.PREFER_IP_ADDRESS_KEY; import static com.tencent.polaris.plugins.connector.common.constant.ConsulConstant.MetadataMapKey.PREFER_IP_ADDRESS_KEY;
import static com.tencent.polaris.plugins.connector.common.constant.ConsulConstant.MetadataMapKey.SERVICE_NAME_KEY; import static com.tencent.polaris.plugins.connector.common.constant.ConsulConstant.MetadataMapKey.SERVICE_NAME_KEY;
import static com.tencent.polaris.test.common.Consts.HOST; import static com.tencent.polaris.test.common.Consts.HOST;
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;
/** /**
* Test for {@link ConsulContextProperties}. * Test for {@link ConsulDiscoveryPropertiesTest}.
* *
* @author Haotian Zhang * @author Haotian Zhang
*/ */
@ExtendWith(SpringExtension.class) @ExtendWith(SpringExtension.class)
@SpringBootTest(classes = ConsulContextPropertiesTest.TestApplication.class) @SpringBootTest(classes = ConsulDiscoveryPropertiesTest.TestApplication.class)
@ActiveProfiles("test") @ActiveProfiles("test")
public class ConsulContextPropertiesTest { public class ConsulDiscoveryPropertiesTest {
@Autowired @Autowired
private ConsulContextProperties consulContextProperties; private ConsulDiscoveryProperties consulDiscoveryProperties;
@Autowired @Autowired
private PolarisSDKContextManager polarisSDKContextManager; private PolarisSDKContextManager polarisSDKContextManager;
@ -63,12 +62,9 @@ public class ConsulContextPropertiesTest {
@Test @Test
public void testDefaultInitialization() { public void testDefaultInitialization() {
assertThat(consulContextProperties).isNotNull(); assertThat(consulDiscoveryProperties).isNotNull();
assertThat(consulContextProperties.isEnabled()).isTrue(); assertThat(consulDiscoveryProperties.isRegister()).isTrue();
assertThat(consulContextProperties.getHost()).isEqualTo("127.0.0.1"); assertThat(consulDiscoveryProperties.isEnabled()).isTrue();
assertThat(consulContextProperties.getPort()).isEqualTo(8500);
assertThat(consulContextProperties.isRegister()).isTrue();
assertThat(consulContextProperties.isDiscoveryEnabled()).isTrue();
} }
@Test @Test
@ -84,7 +80,7 @@ public class ConsulContextPropertiesTest {
} }
} }
assertThat(metadata).isNotNull(); assertThat(metadata).isNotNull();
assertThat(metadata.get(SERVICE_NAME_KEY)).isEqualTo(SERVICE_PROVIDER); assertThat(metadata.get(SERVICE_NAME_KEY)).isEqualTo("java-provider-test");
assertThat(metadata.get(INSTANCE_ID_KEY)).isEqualTo("ins-test"); assertThat(metadata.get(INSTANCE_ID_KEY)).isEqualTo("ins-test");
assertThat(metadata.get(PREFER_IP_ADDRESS_KEY)).isEqualTo("true"); assertThat(metadata.get(PREFER_IP_ADDRESS_KEY)).isEqualTo("true");
assertThat(metadata.get(IP_ADDRESS_KEY)).isEqualTo(HOST); assertThat(metadata.get(IP_ADDRESS_KEY)).isEqualTo(HOST);

@ -23,7 +23,7 @@ import java.util.Map;
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.config.PolarisContextProperties; import com.tencent.cloud.polaris.context.config.PolarisContextProperties;
import com.tencent.cloud.polaris.extend.consul.ConsulContextProperties; import com.tencent.cloud.polaris.extend.consul.ConsulDiscoveryProperties;
import com.tencent.cloud.polaris.extend.nacos.NacosContextProperties; import com.tencent.cloud.polaris.extend.nacos.NacosContextProperties;
import com.tencent.polaris.api.config.Configuration; import com.tencent.polaris.api.config.Configuration;
import com.tencent.polaris.api.config.global.APIConfig; import com.tencent.polaris.api.config.global.APIConfig;
@ -76,9 +76,8 @@ public class PolarisRegistrationTest {
PolarisContextProperties polarisContextProperties = mock(PolarisContextProperties.class); PolarisContextProperties polarisContextProperties = mock(PolarisContextProperties.class);
doReturn(testLocalPort).when(polarisContextProperties).getLocalPort(); doReturn(testLocalPort).when(polarisContextProperties).getLocalPort();
// mock ConsulContextProperties // mock ConsulDiscoveryProperties
ConsulContextProperties consulContextProperties = mock(ConsulContextProperties.class); ConsulDiscoveryProperties consulContextProperties = mock(ConsulDiscoveryProperties.class);
doReturn(true).when(consulContextProperties).isEnabled();
doReturn(true).when(consulContextProperties).isRegister(); doReturn(true).when(consulContextProperties).isRegister();
// mock NacosContextProperties // mock NacosContextProperties

@ -0,0 +1,63 @@
/*
* 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.common.tsf;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.tencent.polaris.api.utils.StringUtils;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
/**
* Condition that if Polaris enabled.
*
* @author Haotian Zhang
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Conditional(ConditionalOnTsfConsulEnabled.OnTsfEnabledCondition.class)
public @interface ConditionalOnTsfConsulEnabled {
class OnTsfEnabledCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
Environment environment = conditionContext.getEnvironment();
boolean tsfConsulEnable = false;
String tsfAppId = environment.getProperty("tsf_app_id", "");
if (StringUtils.isNotBlank(tsfAppId)) {
String tsfConsulIp = environment.getProperty("tsf_consul_ip");
String tsePolarisAddress = environment.getProperty("spring.cloud.polaris.address");
if (StringUtils.isBlank(tsePolarisAddress) && StringUtils.isNotBlank(environment.getProperty("tse_polaris_ip"))) {
tsePolarisAddress = "grpc://" + environment.getProperty("tse_polaris_ip") + ":8091";
}
tsfConsulEnable = StringUtils.isNotBlank(tsfConsulIp) && StringUtils.isBlank(tsePolarisAddress);
}
return tsfConsulEnable;
}
}
}

@ -87,16 +87,6 @@ public final class AddressUtils {
return true; return true;
} }
public static String getIpCompatible(String ip) {
if (StringUtils.isEmpty(ip)) {
return ip;
}
if (ip.contains(":") && !ip.startsWith("[") && !ip.endsWith("]")) {
return "[" + ip + "]";
}
return ip;
}
public static boolean preferIpv6() { public static boolean preferIpv6() {
if (Boolean.FALSE.equals(hasIpv6Address)) { if (Boolean.FALSE.equals(hasIpv6Address)) {
LOGGER.debug("AddressUtils.preferIpv6 hasIpv6Address = false"); LOGGER.debug("AddressUtils.preferIpv6 hasIpv6Address = false");

@ -17,12 +17,12 @@
package com.tencent.cloud.common.util.inet; package com.tencent.cloud.common.util.inet;
import com.tencent.cloud.common.tsf.ConditionalOnTsfEnabled;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.commons.util.InetUtilsProperties; import org.springframework.cloud.commons.util.InetUtilsProperties;
import org.springframework.cloud.commons.util.UtilAutoConfiguration;
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;
/** /**
@ -31,7 +31,7 @@ import org.springframework.context.annotation.Configuration;
* @author Haotian Zhang * @author Haotian Zhang
*/ */
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@ConditionalOnTsfEnabled @Import(UtilAutoConfiguration.class)
public class PolarisInetUtilsAutoConfiguration { public class PolarisInetUtilsAutoConfiguration {
@Bean @Bean

@ -71,7 +71,7 @@
<properties> <properties>
<!-- Project revision --> <!-- Project revision -->
<revision>2.0.0.0-2023.0.0-RC2</revision> <revision>2.0.0.0-2023.0.0-SNAPSHOT</revision>
<!-- Polaris SDK version --> <!-- Polaris SDK version -->
<polaris.version>2.0.0.0-SNAPSHOT</polaris.version> <polaris.version>2.0.0.0-SNAPSHOT</polaris.version>

@ -61,7 +61,7 @@ public class QuickstartCalleeController {
@Autowired @Autowired
private DataSourceProperties dataSourceProperties; private DataSourceProperties dataSourceProperties;
private boolean ifBadGateway = true; private boolean ifBadGateway = true;
private boolean ifDelay = true; private boolean ifDelay = false;
/** /**
* Get sum of two value. * Get sum of two value.

@ -17,6 +17,7 @@
package com.tencent.cloud.quickstart.caller.circuitbreaker; package com.tencent.cloud.quickstart.caller.circuitbreaker;
import com.tencent.cloud.common.metadata.MetadataContext;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -28,6 +29,8 @@ import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
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 org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.reactive.function.client.WebClient;
@ -110,7 +113,7 @@ public class CircuitBreakerController {
@GetMapping("/rest") @GetMapping("/rest")
public String circuitBreakRestTemplate() { public String circuitBreakRestTemplate() {
return circuitBreakerFactory return circuitBreakerFactory
.create("QuickstartCalleeService#/quickstart/callee/circuitBreak") .create(MetadataContext.LOCAL_NAMESPACE + "#QuickstartCalleeService#/quickstart/callee/circuitBreak#http#GET")
.run(() -> defaultRestTemplate.getForObject("/quickstart/callee/circuitBreak", String.class), .run(() -> defaultRestTemplate.getForObject("/quickstart/callee/circuitBreak", String.class),
throwable -> "trigger the refuse for service callee." throwable -> "trigger the refuse for service callee."
); );
@ -142,8 +145,13 @@ public class CircuitBreakerController {
*/ */
@GetMapping("/rest/fallbackFromPolaris") @GetMapping("/rest/fallbackFromPolaris")
public ResponseEntity<String> circuitBreakRestTemplateFallbackFromPolaris() { public ResponseEntity<String> circuitBreakRestTemplateFallbackFromPolaris() {
try {
return restTemplateFallbackFromPolaris.getForEntity("/quickstart/callee/circuitBreak", String.class); return restTemplateFallbackFromPolaris.getForEntity("/quickstart/callee/circuitBreak", String.class);
} }
catch (HttpClientErrorException | HttpServerErrorException httpClientErrorException) {
return new ResponseEntity<>(httpClientErrorException.getResponseBodyAsString(), httpClientErrorException.getStatusCode());
}
}
/** /**
* RestTemplate circuit breaker with fallback from code. * RestTemplate circuit breaker with fallback from code.
@ -151,8 +159,13 @@ public class CircuitBreakerController {
*/ */
@GetMapping("/rest/fallbackFromCode") @GetMapping("/rest/fallbackFromCode")
public ResponseEntity<String> circuitBreakRestTemplateFallbackFromCode() { public ResponseEntity<String> circuitBreakRestTemplateFallbackFromCode() {
try {
return restTemplateFallbackFromCode.getForEntity("/quickstart/callee/circuitBreak", String.class); return restTemplateFallbackFromCode.getForEntity("/quickstart/callee/circuitBreak", String.class);
} }
catch (HttpClientErrorException | HttpServerErrorException httpClientErrorException) {
return new ResponseEntity<>(httpClientErrorException.getResponseBodyAsString(), httpClientErrorException.getStatusCode());
}
}
/** /**
* Get information of callee. * Get information of callee.
@ -168,7 +181,7 @@ public class CircuitBreakerController {
.bodyToMono(String.class) .bodyToMono(String.class)
.transform(it -> .transform(it ->
reactiveCircuitBreakerFactory reactiveCircuitBreakerFactory
.create("QuickstartCalleeService#/quickstart/callee/circuitBreak") .create(MetadataContext.LOCAL_NAMESPACE + "QuickstartCalleeService#/quickstart/callee/circuitBreak#http#GET")
.run(it, throwable -> Mono.just("fallback: trigger the refuse for service callee")) .run(it, throwable -> Mono.just("fallback: trigger the refuse for service callee"))
); );
} }

@ -32,6 +32,11 @@
<artifactId>spring-cloud-starter-tencent-polaris-router</artifactId> <artifactId>spring-cloud-starter-tencent-polaris-router</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-circuitbreaker</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>

@ -17,6 +17,8 @@
package com.tencent.cloud.tsf.demo.consumer; package com.tencent.cloud.tsf.demo.consumer;
import com.tencent.cloud.polaris.circuitbreaker.resttemplate.PolarisCircuitBreaker;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.client.loadbalancer.LoadBalanced;
@ -35,6 +37,7 @@ public class ConsumerApplication {
@LoadBalanced @LoadBalanced
@Bean @Bean
@PolarisCircuitBreaker
public RestTemplate restTemplate() { public RestTemplate restTemplate() {
return new RestTemplate(); return new RestTemplate();
} }

@ -23,6 +23,7 @@ import java.util.Map;
import com.tencent.cloud.tsf.demo.consumer.proxy.ProviderDemoService; import com.tencent.cloud.tsf.demo.consumer.proxy.ProviderDemoService;
import com.tencent.cloud.tsf.demo.consumer.proxy.ProviderService; import com.tencent.cloud.tsf.demo.consumer.proxy.ProviderService;
import com.tencent.polaris.api.utils.StringUtils; import com.tencent.polaris.api.utils.StringUtils;
import com.tencent.polaris.circuitbreak.client.exception.CallAbortedException;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.tsf.core.context.TsfContext; import org.springframework.tsf.core.context.TsfContext;
@ -55,8 +56,14 @@ public class ConsumerController {
mTags.put("rest-trace-key1", "value1"); mTags.put("rest-trace-key1", "value1");
mTags.put("rest-trace-key2", "value2"); mTags.put("rest-trace-key2", "value2");
TsfContext.putTags(mTags, Tag.ControlFlag.TRANSITIVE); TsfContext.putTags(mTags, Tag.ControlFlag.TRANSITIVE);
try {
return restTemplate.getForObject("http://provider-demo/echo/" + str, String.class); return restTemplate.getForObject("http://provider-demo/echo/" + str, String.class);
} }
catch (CallAbortedException callAbortedException) {
return callAbortedException.getMessage();
}
}
@RequestMapping(value = "/echo-feign/{str}", method = RequestMethod.GET) @RequestMapping(value = "/echo-feign/{str}", method = RequestMethod.GET)
public String feignProvider(@PathVariable String str, public String feignProvider(@PathVariable String str,
@ -70,8 +77,13 @@ public class ConsumerController {
mTags.put("feign-trace-key1", "value1"); mTags.put("feign-trace-key1", "value1");
mTags.put("feign-trace-key2", "value2"); mTags.put("feign-trace-key2", "value2");
TsfContext.putTags(mTags, Tag.ControlFlag.TRANSITIVE); TsfContext.putTags(mTags, Tag.ControlFlag.TRANSITIVE);
try {
return providerDemoService.echo(str); return providerDemoService.echo(str);
} }
catch (CallAbortedException callAbortedException) {
return callAbortedException.getMessage();
}
}
@RequestMapping(value = "/echo-feign-url/{str}", method = RequestMethod.GET) @RequestMapping(value = "/echo-feign-url/{str}", method = RequestMethod.GET)
public String feignUrlProvider(@PathVariable String str, public String feignUrlProvider(@PathVariable String str,

@ -205,6 +205,11 @@
<groupId>com.tencent.polaris</groupId> <groupId>com.tencent.polaris</groupId>
<artifactId>polaris-assembly-factory</artifactId> <artifactId>polaris-assembly-factory</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.tencent.polaris</groupId>
<artifactId>event-tsf</artifactId>
</dependency>
<!-- Polaris dependencies end --> <!-- Polaris dependencies end -->
<dependency> <dependency>

@ -20,11 +20,15 @@ package com.tencent.cloud.polaris.context.config;
import java.util.List; import java.util.List;
import com.tencent.cloud.common.tsf.ConditionalOnTsfEnabled;
import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled; import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled;
import com.tencent.cloud.polaris.context.ModifyAddress; import com.tencent.cloud.polaris.context.ModifyAddress;
import com.tencent.cloud.polaris.context.PolarisConfigModifier; import com.tencent.cloud.polaris.context.PolarisConfigModifier;
import com.tencent.cloud.polaris.context.PolarisSDKContextManager; 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.extend.consul.ConsulProperties;
import com.tencent.cloud.polaris.context.config.extend.tsf.TsfCoreProperties;
import com.tencent.cloud.polaris.context.config.extend.tsf.TsfInstanceMetadataProvider;
import com.tencent.cloud.polaris.context.listener.PolarisContextApplicationEventListener; import com.tencent.cloud.polaris.context.listener.PolarisContextApplicationEventListener;
import com.tencent.polaris.api.exception.PolarisException; import com.tencent.polaris.api.exception.PolarisException;
import com.tencent.polaris.client.api.SDKContext; import com.tencent.polaris.client.api.SDKContext;
@ -64,4 +68,23 @@ public class PolarisContextAutoConfiguration {
public PolarisContextApplicationEventListener contextApplicationEventListener(PolarisSDKContextManager polarisSDKContextManager) { public PolarisContextApplicationEventListener contextApplicationEventListener(PolarisSDKContextManager polarisSDKContextManager) {
return new PolarisContextApplicationEventListener(polarisSDKContextManager); return new PolarisContextApplicationEventListener(polarisSDKContextManager);
} }
@Bean
@ConditionalOnMissingBean
public ConsulProperties consulProperties() {
return new ConsulProperties();
}
@Bean
@ConditionalOnMissingBean
public TsfCoreProperties tsfCoreProperties() {
return new TsfCoreProperties();
}
@Bean
@ConditionalOnTsfEnabled
@ConditionalOnMissingBean
public TsfInstanceMetadataProvider tsfInstanceMetadataProvider(TsfCoreProperties tsfCoreProperties) {
return new TsfInstanceMetadataProvider(tsfCoreProperties);
}
} }

@ -15,22 +15,29 @@
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*/ */
package com.tencent.cloud.polaris.context.tsf.consul; package com.tencent.cloud.polaris.context.config.extend.consul;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
/** /**
* Copy from org.springframework.cloud.consul.ConsulProperties.
*
* @author Spencer Gibb * @author Spencer Gibb
*/ */
@ConfigurationProperties(ConsulProperties.PREFIX)
@Validated @Validated
public class TsfConsulProperties { public class ConsulProperties {
/**
* Prefix for configuration properties.
*/
public static final String PREFIX = "spring.cloud.consul";
/** Consul agent hostname. Defaults to '127.0.0.1'. */ /** Consul agent hostname. Defaults to 'localhost'. */
@Value("${tsf_consul_ip:${spring.cloud.consul.host:${SPRING_CLOUD_CONSUL_HOST:localhost}}}")
@NotNull @NotNull
private String host = "localhost"; private String host = "localhost";
@ -38,22 +45,16 @@ public class TsfConsulProperties {
* Consul agent scheme (HTTP/HTTPS). If there is no scheme in address - client * Consul agent scheme (HTTP/HTTPS). If there is no scheme in address - client
* will use HTTP. * will use HTTP.
*/ */
@Value("${spring.cloud.consul.scheme:${SPRING_CLOUD_CONSUL_SCHEME:}}")
private String scheme; private String scheme;
/** Consul agent port. Defaults to '8500'. */ /** Consul agent port. Defaults to '8500'. */
@Value("${tsf_consul_port:${spring.cloud.consul.port:${SPRING_CLOUD_CONSUL_PORT:8500}}}")
@NotNull @NotNull
private int port = 8500; private int port = 8500;
/** Is spring cloud consul enabled. */ /** Is spring cloud consul enabled. */
@Value("${spring.cloud.consul.enabled:${SPRING_CLOUD_CONSUL_ENABLED:true}}") private boolean enabled = false;
private boolean enabled = true;
@Value("${tsf_consul_ttl_read_timeout:5000}") @Value("${consul.token:${CONSUL_TOKEN:${spring.cloud.consul.token:${SPRING_CLOUD_CONSUL_TOKEN:}}}}")
private int ttlReadTimeout = 5000; // default 5s
@Value("${tsf_token:${consul.token:${CONSUL_TOKEN:${spring.cloud.consul.token:${SPRING_CLOUD_CONSUL_TOKEN:}}}}}")
private String aclToken; private String aclToken;
public String getHost() { public String getHost() {
@ -88,14 +89,6 @@ public class TsfConsulProperties {
this.scheme = scheme; this.scheme = scheme;
} }
public int getTtlReadTimeout() {
return ttlReadTimeout;
}
public void setTtlReadTimeout(int ttlReadTimeout) {
this.ttlReadTimeout = ttlReadTimeout;
}
public String getAclToken() { public String getAclToken() {
return aclToken; return aclToken;
} }
@ -106,12 +99,11 @@ public class TsfConsulProperties {
@Override @Override
public String toString() { public String toString() {
return "TsfConsulProperties{" + return "ConsulProperties{" +
"host='" + host + '\'' + "host='" + host + '\'' +
", scheme='" + scheme + '\'' + ", scheme='" + scheme + '\'' +
", port=" + port + ", port=" + port +
", enabled=" + enabled + ", enabled=" + enabled +
", ttlReadTimeout=" + ttlReadTimeout +
", aclToken='" + aclToken + '\'' + ", aclToken='" + aclToken + '\'' +
'}'; '}';
} }

@ -15,10 +15,11 @@
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*/ */
package com.tencent.cloud.polaris.context.tsf.config; package com.tencent.cloud.polaris.context.config.extend.tsf;
import com.tencent.cloud.common.tsf.ConditionalOnTsfEnabled; import com.tencent.cloud.common.tsf.ConditionalOnTsfConsulEnabled;
import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration; import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration;
import com.tencent.cloud.polaris.context.config.extend.consul.ConsulProperties;
import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@ -26,18 +27,18 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
/** /**
* Core properties auto configuration. * TSF context auto configuration.
* *
* @author Haotian Zhang * @author Haotian Zhang
*/ */
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@AutoConfigureAfter(PolarisContextAutoConfiguration.class) @AutoConfigureAfter(PolarisContextAutoConfiguration.class)
@ConditionalOnTsfEnabled @ConditionalOnTsfConsulEnabled
public class TsfCorePropertiesAutoConfiguration { public class TsfContextAutoConfiguration {
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public TsfCoreProperties tsfCoreProperties() { public TsfContextConfigModifier tsfConfigModifier(TsfCoreProperties tsfCoreProperties, ConsulProperties consulProperties) {
return new TsfCoreProperties(); return new TsfContextConfigModifier(tsfCoreProperties, consulProperties);
} }
} }

@ -15,18 +15,18 @@
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*/ */
package com.tencent.cloud.polaris.context.tsf.config; package com.tencent.cloud.polaris.context.config.extend.tsf;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
/** /**
* Core properties bootstrap configuration. * TSF context bootstrap configuration.
* *
* @author Haotian Zhang * @author Haotian Zhang
*/ */
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@Import(TsfCorePropertiesAutoConfiguration.class) @Import(TsfContextAutoConfiguration.class)
public class TsfCorePropertiesBootstrapConfiguration { public class TsfContextBootstrapConfiguration {
} }

@ -0,0 +1,64 @@
/*
* 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.context.config.extend.tsf;
import com.tencent.cloud.common.constant.OrderConstant;
import com.tencent.cloud.polaris.context.PolarisConfigModifier;
import com.tencent.cloud.polaris.context.config.extend.consul.ConsulProperties;
import com.tencent.polaris.api.config.plugin.DefaultPlugins;
import com.tencent.polaris.factory.config.ConfigurationImpl;
import com.tencent.polaris.plugins.event.tsf.TsfEventReporterConfig;
/**
* Config modifier for TSF.
*
* @author Haotian Zhang
*/
public class TsfContextConfigModifier implements PolarisConfigModifier {
private final TsfCoreProperties tsfCoreProperties;
private final ConsulProperties consulProperties;
public TsfContextConfigModifier(TsfCoreProperties tsfCoreProperties, ConsulProperties consulProperties) {
this.tsfCoreProperties = tsfCoreProperties;
this.consulProperties = consulProperties;
}
@Override
public void modify(ConfigurationImpl configuration) {
configuration.getGlobal().getEventReporter().getReporters().add(DefaultPlugins.TSF_EVENT_REPORTER_TYPE);
TsfEventReporterConfig tsfEventReporterConfig = new TsfEventReporterConfig();
tsfEventReporterConfig.setEventMasterIp(tsfCoreProperties.getEventMasterIp());
tsfEventReporterConfig.setEventMasterPort(tsfCoreProperties.getEventMasterPort());
tsfEventReporterConfig.setAppId(tsfCoreProperties.getAppId());
tsfEventReporterConfig.setRegion(tsfCoreProperties.getTsfRegion());
tsfEventReporterConfig.setInstanceId(tsfCoreProperties.getInstanceId());
tsfEventReporterConfig.setTsfNamespaceId(tsfCoreProperties.getTsfNamespaceId());
tsfEventReporterConfig.setServiceName(tsfCoreProperties.getServiceName());
tsfEventReporterConfig.setToken(consulProperties.getAclToken());
configuration.getGlobal().getEventReporter()
.setPluginConfig(DefaultPlugins.TSF_EVENT_REPORTER_TYPE, tsfEventReporterConfig);
}
@Override
public int getOrder() {
return OrderConstant.Modifier.CIRCUIT_BREAKER_ORDER - 1;
}
}

@ -0,0 +1,178 @@
/*
* 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.context.config.extend.tsf;
import java.util.HashMap;
import java.util.Map;
import com.tencent.polaris.api.utils.StringUtils;
import org.apache.commons.logging.Log;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.boot.logging.DeferredLogFactory;
import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
/**
* Read TSF env.
*
* @author Haotian Zhang
*/
public final class TsfCoreEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
/**
* run before {@link ConfigDataEnvironmentPostProcessor}.
*/
public static final int ORDER = ConfigDataEnvironmentPostProcessor.ORDER - 1;
private final Log LOGGER;
private TsfCoreEnvironmentPostProcessor(DeferredLogFactory logFactory) {
this.LOGGER = logFactory.getLog(getClass());
}
@Override
public int getOrder() {
return ORDER;
}
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
String tsfAppId = environment.getProperty("tsf_app_id");
// TSF deploy
if (StringUtils.isNotBlank(tsfAppId)) {
Map<String, Object> defaultProperties = new HashMap<>();
String tsfConsulIp = environment.getProperty("tsf_consul_ip");
String tsePolarisAddress = environment.getProperty("spring.cloud.polaris.address");
if (StringUtils.isBlank(tsePolarisAddress) && StringUtils.isNotBlank(environment.getProperty("tse_polaris_ip"))) {
tsePolarisAddress = "grpc://" + environment.getProperty("tse_polaris_ip") + ":8091";
}
// tsf_prog_version
String tsfProgVersion = environment.getProperty("tsf_prog_version");
if (StringUtils.isBlank(tsfProgVersion)) {
LOGGER.error("tsf_prog_version is empty");
}
else {
defaultProperties.put("spring.cloud.polaris.discovery.version", tsfProgVersion);
}
// lossless
defaultProperties.put("spring.cloud.polaris.lossless.enabled", true);
defaultProperties.put("spring.cloud.polaris.lossless.port", environment.getProperty("tsf_sctt_extensions_port", "11134"));
// state
defaultProperties.put("spring.cloud.polaris.stat.port", environment.getProperty("tsf_sctt_extensions_port", "11134"));
boolean tsfConsulEnable = StringUtils.isNotBlank(tsfConsulIp) && StringUtils.isBlank(tsePolarisAddress);
if (tsfConsulEnable) {
// tsf_consul_port
String tsfConsulPort = environment.getProperty("tsf_consul_port");
if (StringUtils.isBlank(tsfConsulPort)) {
LOGGER.error("tsf_consul_port is empty");
}
// tsf_token
String tsfConsulToken = environment.getProperty("tsf_token");
if (StringUtils.isBlank(tsfConsulToken)) {
LOGGER.error("tsf_token is empty");
}
// tsf_instance_id
String tsfInstanceId = environment.getProperty("tsf_instance_id");
if (StringUtils.isBlank(tsfInstanceId)) {
LOGGER.error("tsf_instance_id is empty");
}
// tsf_application_id
String tsfApplicationId = environment.getProperty("tsf_application_id");
if (StringUtils.isBlank(tsfApplicationId)) {
LOGGER.error("tsf_application_id is empty");
}
// tsf_group_id
String tsfGroupId = environment.getProperty("tsf_group_id");
if (StringUtils.isBlank(tsfGroupId)) {
LOGGER.error("tsf_group_id is empty");
}
// tsf_namespace_id
String tsfNamespaceId = environment.getProperty("tsf_namespace_id");
if (StringUtils.isBlank(tsfNamespaceId)) {
LOGGER.error("tsf_namespace_id is empty");
}
else {
defaultProperties.put("spring.cloud.polaris.namespace", tsfNamespaceId);
}
// context
defaultProperties.put("spring.cloud.polaris.enabled", "true");
defaultProperties.put("spring.cloud.polaris.discovery.enabled", "false");
defaultProperties.put("spring.cloud.polaris.discovery.register", "false");
defaultProperties.put("spring.cloud.consul.enabled", "true");
defaultProperties.put("spring.cloud.consul.host", tsfConsulIp);
defaultProperties.put("spring.cloud.consul.port", tsfConsulPort);
defaultProperties.put("spring.cloud.consul.token", tsfConsulToken);
// discovery
defaultProperties.put("spring.cloud.consul.discovery.enabled", "true");
defaultProperties.put("spring.cloud.consul.discovery.register", "true");
defaultProperties.put("spring.cloud.consul.discovery.instance-id", tsfInstanceId);
defaultProperties.put("spring.cloud.polaris.discovery.instance-id", tsfInstanceId);
defaultProperties.put("spring.cloud.polaris.discovery.zero-protection.enabled", "true");
defaultProperties.put("spring.cloud.polaris.discovery.zero-protection.is-need-test-connectivity", "true");
defaultProperties.put("spring.cloud.discovery.client.health-indicator.enabled", "false");
// contract
defaultProperties.put("spring.cloud.polaris.contract.enabled", environment.getProperty("tsf.swagger.enabled", "true"));
if (StringUtils.isNotBlank(environment.getProperty("tsf.swagger.basePackage"))) {
defaultProperties.put("spring.cloud.polaris.contract.base-package", environment.getProperty("tsf.swagger.basePackage"));
}
if (StringUtils.isNotBlank(environment.getProperty("tsf.swagger.excludePath"))) {
defaultProperties.put("spring.cloud.polaris.contract.exclude-path", environment.getProperty("tsf.swagger.excludePath"));
}
defaultProperties.put("spring.cloud.polaris.contract.group", environment.getProperty("tsf.swagger.group", "polaris"));
defaultProperties.put("spring.cloud.polaris.contract.base-path", environment.getProperty("tsf.swagger.basePath", "/**"));
defaultProperties.put("spring.cloud.polaris.contract.exposure", environment.getProperty("tsf.swagger.doc.auto-startup", "true"));
defaultProperties.put("spring.cloud.polaris.contract.report.enabled", environment.getProperty("tsf.swagger.enabled", "true"));
defaultProperties.put("spring.cloud.polaris.contract.name", tsfApplicationId);
// configuration
defaultProperties.put("spring.cloud.polaris.config.enabled", "true");
defaultProperties.put("spring.cloud.polaris.config.internal-enabled", "false");
defaultProperties.put("spring.cloud.polaris.config.data-source", "consul");
defaultProperties.put("spring.cloud.polaris.config.address", "http://" + tsfConsulIp + ":" + tsfConsulPort);
defaultProperties.put("spring.cloud.polaris.config.port", tsfConsulPort);
defaultProperties.put("spring.cloud.polaris.config.token", tsfConsulToken);
defaultProperties.put("spring.cloud.polaris.config.groups[0].namespace", "config");
defaultProperties.put("spring.cloud.polaris.config.groups[0].name", "application");
defaultProperties.put("spring.cloud.polaris.config.groups[0].files[0]", tsfApplicationId + "/" + tsfGroupId + "/");
defaultProperties.put("spring.cloud.polaris.config.groups[0].files[1]", tsfNamespaceId + "/");
defaultProperties.put("spring.cloud.polaris.config.refresh-type", "refresh_context");
// router
defaultProperties.put("spring.cloud.polaris.router.rule-router.fail-over", "none");
defaultProperties.put("spring.cloud.polaris.router.namespace-router.enabled", "true");
}
MapPropertySource propertySource = new MapPropertySource("tsf-polaris-properties", defaultProperties);
environment.getPropertySources().addFirst(propertySource);
}
}
}

@ -15,11 +15,14 @@
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*/ */
package com.tencent.cloud.polaris.context.tsf.config; package com.tencent.cloud.polaris.context.config.extend.tsf;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
@ -31,14 +34,8 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("tsf") @ConfigurationProperties("tsf")
public class TsfCoreProperties { public class TsfCoreProperties {
@Value("${tse_polaris_ip:}") @Value("${tsf_app_id:}")
private String tsePolarisIp = ""; private String appId;
@Value("${tsf_consul_enable:false}")
private boolean tsfConsulEnable = false;
@Value("${tse_polaris_enable:false}")
private boolean tsePolarisEnable = false;
/** /**
* Unique service instance id. * Unique service instance id.
@ -76,6 +73,9 @@ public class TsfCoreProperties {
@Value("${tsf_namespace_id:}") @Value("${tsf_namespace_id:}")
private String tsfNamespaceId; private String tsfNamespaceId;
@Value("${spring.application.name:}")
private String serviceName;
/** /**
* tsf service consul registration tags. * tsf service consul registration tags.
* *
@ -123,28 +123,18 @@ public class TsfCoreProperties {
@Value("${tsf.discovery.scheme:http}") @Value("${tsf.discovery.scheme:http}")
private String scheme = "http"; private String scheme = "http";
public String getTsePolarisIp() { @Value("${tsf_event_master_ip:}")
return tsePolarisIp; private String eventMasterIp;
}
public void setTsePolarisIp(String tsePolarisIp) {
this.tsePolarisIp = tsePolarisIp;
}
public boolean isTsfConsulEnable() {
return tsfConsulEnable;
}
public void setTsfConsulEnable(boolean tsfConsulEnable) { @Value("${tsf_event_master_port:15200}")
this.tsfConsulEnable = tsfConsulEnable; private Integer eventMasterPort;
}
public boolean isTsePolarisEnable() { public String getAppId() {
return tsePolarisEnable; return appId;
} }
public void setTsePolarisEnable(boolean tsePolarisEnable) { public void setAppId(String appId) {
this.tsePolarisEnable = tsePolarisEnable; this.appId = appId;
} }
public String getInstanceId() { public String getInstanceId() {
@ -187,11 +177,19 @@ public class TsfCoreProperties {
this.tsfNamespaceId = tsfNamespaceId; this.tsfNamespaceId = tsfNamespaceId;
} }
public String getServiceName() {
return serviceName;
}
public void setServiceName(String serviceName) {
this.serviceName = serviceName;
}
public String getTsfRegion() { public String getTsfRegion() {
return tsfRegion; return tsfRegion;
} }
public void setTsfRegion(final String tsfRegion) { public void setTsfRegion(String tsfRegion) {
this.tsfRegion = tsfRegion; this.tsfRegion = tsfRegion;
} }
@ -199,7 +197,7 @@ public class TsfCoreProperties {
return tsfZone; return tsfZone;
} }
public void setTsfZone(final String tsfZone) { public void setTsfZone(String tsfZone) {
this.tsfZone = tsfZone; this.tsfZone = tsfZone;
} }
@ -211,6 +209,19 @@ public class TsfCoreProperties {
this.tags = tags; this.tags = tags;
} }
public List<String> getTsfTags() {
List<String> tags = new LinkedList<>(getTags());
if (StringUtils.isNotBlank(getInstanceZone())) {
tags.add(getDefaultZoneMetadataName() + "=" + getInstanceZone());
}
if (StringUtils.isNotBlank(getInstanceGroup())) {
tags.add("group=" + getInstanceGroup());
}
//store the secure flag in the tags so that clients will be able to figure out whether to use http or https automatically
tags.add("secure=" + getScheme().equalsIgnoreCase("https"));
return tags;
}
public String getInstanceZone() { public String getInstanceZone() {
return instanceZone; return instanceZone;
} }
@ -243,17 +254,32 @@ public class TsfCoreProperties {
this.scheme = scheme; this.scheme = scheme;
} }
public String getEventMasterIp() {
return eventMasterIp;
}
public void setEventMasterIp(String eventMasterIp) {
this.eventMasterIp = eventMasterIp;
}
public Integer getEventMasterPort() {
return eventMasterPort;
}
public void setEventMasterPort(Integer eventMasterPort) {
this.eventMasterPort = eventMasterPort;
}
@Override @Override
public String toString() { public String toString() {
return "TsfCoreProperties{" + return "TsfCoreProperties{" +
"tsePolarisIp='" + tsePolarisIp + '\'' + "appId='" + appId + '\'' +
", tsfConsulEnable=" + tsfConsulEnable +
", tsePolarisEnable=" + tsePolarisEnable +
", instanceId='" + instanceId + '\'' + ", instanceId='" + instanceId + '\'' +
", tsfApplicationId='" + tsfApplicationId + '\'' + ", tsfApplicationId='" + tsfApplicationId + '\'' +
", tsfGroupId='" + tsfGroupId + '\'' + ", tsfGroupId='" + tsfGroupId + '\'' +
", tsfProgVersion='" + tsfProgVersion + '\'' + ", tsfProgVersion='" + tsfProgVersion + '\'' +
", tsfNamespaceId='" + tsfNamespaceId + '\'' + ", tsfNamespaceId='" + tsfNamespaceId + '\'' +
", serviceName='" + serviceName + '\'' +
", tsfRegion='" + tsfRegion + '\'' + ", tsfRegion='" + tsfRegion + '\'' +
", tsfZone='" + tsfZone + '\'' + ", tsfZone='" + tsfZone + '\'' +
", tags=" + tags + ", tags=" + tags +
@ -261,6 +287,8 @@ public class TsfCoreProperties {
", instanceGroup='" + instanceGroup + '\'' + ", instanceGroup='" + instanceGroup + '\'' +
", defaultZoneMetadataName='" + defaultZoneMetadataName + '\'' + ", defaultZoneMetadataName='" + defaultZoneMetadataName + '\'' +
", scheme='" + scheme + '\'' + ", scheme='" + scheme + '\'' +
", eventMasterIp='" + eventMasterIp + '\'' +
", eventMasterPort=" + eventMasterPort +
'}'; '}';
} }
} }

@ -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.context.tsf.metadata; package com.tencent.cloud.polaris.context.config.extend.tsf;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -25,14 +25,9 @@ import com.tencent.cloud.common.constant.WarmupCons;
import com.tencent.cloud.common.spi.InstanceMetadataProvider; import com.tencent.cloud.common.spi.InstanceMetadataProvider;
import com.tencent.cloud.common.util.JacksonUtils; import com.tencent.cloud.common.util.JacksonUtils;
import com.tencent.cloud.common.util.inet.PolarisInetUtils; import com.tencent.cloud.common.util.inet.PolarisInetUtils;
import com.tencent.cloud.polaris.context.tsf.TsfUtils;
import com.tencent.cloud.polaris.context.tsf.config.TsfCoreProperties;
import com.tencent.polaris.api.utils.StringUtils; import com.tencent.polaris.api.utils.StringUtils;
import com.tencent.polaris.metadata.core.constant.TsfMetadataConstants; import com.tencent.polaris.metadata.core.constant.TsfMetadataConstants;
import static com.tencent.cloud.polaris.context.tsf.TsfUtils.TSF_ADDRESS_IPV4;
import static com.tencent.cloud.polaris.context.tsf.TsfUtils.TSF_ADDRESS_IPV6;
/** /**
* InstanceMetadataProvider for TSF. * InstanceMetadataProvider for TSF.
@ -63,14 +58,14 @@ public class TsfInstanceMetadataProvider implements InstanceMetadataProvider {
// 处理预热相关的参数 // 处理预热相关的参数
put(WarmupCons.TSF_START_TIME, String.valueOf(System.currentTimeMillis())); put(WarmupCons.TSF_START_TIME, String.valueOf(System.currentTimeMillis()));
put(TsfMetadataConstants.TSF_SDK_VERSION, SdkVersion.get()); put(TsfMetadataConstants.TSF_SDK_VERSION, SdkVersion.get());
put(TsfMetadataConstants.TSF_TAGS, JacksonUtils.serialize2Json(TsfUtils.createTags(tsfCoreProperties))); put(TsfMetadataConstants.TSF_TAGS, JacksonUtils.serialize2Json(tsfCoreProperties.getTsfTags()));
String ipv4Address = PolarisInetUtils.getIpString(false); String ipv4Address = PolarisInetUtils.getIpString(false);
if (StringUtils.isNotBlank(ipv4Address)) { if (StringUtils.isNotBlank(ipv4Address)) {
put(TSF_ADDRESS_IPV4, ipv4Address); put(TsfMetadataConstants.TSF_ADDRESS_IPV4, ipv4Address);
} }
String ipv6Address = PolarisInetUtils.getIpString(true); String ipv6Address = PolarisInetUtils.getIpString(true);
if (StringUtils.isNotBlank(ipv6Address)) { if (StringUtils.isNotBlank(ipv6Address)) {
put(TSF_ADDRESS_IPV6, ipv6Address); put(TsfMetadataConstants.TSF_ADDRESS_IPV6, ipv6Address);
} }
}}; }};
} }

@ -1,80 +0,0 @@
/*
* 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.context.tsf;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import com.tencent.cloud.common.util.inet.PolarisInetUtils;
import com.tencent.cloud.polaris.context.tsf.config.TsfCoreProperties;
import org.springframework.util.StringUtils;
/**
*
*
* @author Haotian Zhang
*/
public final class TsfUtils {
/**
* IPV4.
*/
public static String TSF_ADDRESS_IPV4 = "TSF_ADDRESS_IPV4";
/**
* IPV6.
*/
public static String TSF_ADDRESS_IPV6 = "TSF_ADDRESS_IPV6";
private TsfUtils() {
}
public static List<String> createTags(TsfCoreProperties properties) {
List<String> tags = new LinkedList<>(properties.getTags());
if (StringUtils.hasText(properties.getInstanceZone())) {
tags.add(properties.getDefaultZoneMetadataName() + "=" + properties.getInstanceZone());
}
if (StringUtils.hasText(properties.getInstanceGroup())) {
tags.add("group=" + properties.getInstanceGroup());
}
//store the secure flag in the tags so that clients will be able to figure out whether to use http or https automatically
tags.add("secure=" + properties.getScheme().equalsIgnoreCase("https"));
return tags;
}
public static Map<String, String> appendMetaIpAddress(Map<String, String> meta) {
if (meta == null) {
return null;
}
String ipv4Address = PolarisInetUtils.getIpString(false);
if (ipv4Address != null) {
meta.put(TSF_ADDRESS_IPV4, ipv4Address);
}
String ipv6Address = PolarisInetUtils.getIpString(true);
if (ipv6Address != null) {
meta.put(TSF_ADDRESS_IPV6, ipv6Address);
}
return meta;
}
}

@ -1,42 +0,0 @@
/*
* 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.context.tsf.consul;
import com.tencent.cloud.common.tsf.ConditionalOnTsfEnabled;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableConfigurationProperties
@ConditionalOnTsfEnabled
public class TsfConsulAutoConfiguration {
static {
// 默认关闭对 discovery clientconsul的健康探测避免 consul 故障时,影响监控探测
System.setProperty("spring.cloud.discovery.client.health-indicator.enabled", "false");
}
@Bean
@ConditionalOnMissingBean
public TsfConsulProperties tsfConsulProperties() {
return new TsfConsulProperties();
}
}

@ -1,27 +0,0 @@
/*
* 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.context.tsf.consul;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration(proxyBeanMethods = false)
@Import({TsfConsulAutoConfiguration.class})
public class TsfConsulBootstrapConfiguration {
}

@ -1,138 +0,0 @@
/*
* 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.context.tsf.env;
import java.util.HashMap;
import java.util.Map;
import com.tencent.polaris.api.utils.StringUtils;
import org.apache.commons.logging.Log;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.boot.logging.DeferredLogFactory;
import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
/**
* Read TSF env.
*
* @author Haotian Zhang
*/
public final class TsfCoreEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
/**
* run before {@link ConfigDataEnvironmentPostProcessor}.
*/
public static final int ORDER = ConfigDataEnvironmentPostProcessor.ORDER - 1;
private final Log LOGGER;
private TsfCoreEnvironmentPostProcessor(DeferredLogFactory logFactory) {
this.LOGGER = logFactory.getLog(getClass());
}
@Override
public int getOrder() {
return ORDER;
}
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
String tsfAppId = environment.getProperty("tsf_app_id");
if (StringUtils.isNotBlank(tsfAppId)) {
Map<String, Object> defaultProperties = new HashMap<>();
// enable polaris as default
defaultProperties.put("spring.cloud.polaris.enabled", "true");
// tsf_application_id
String tsfApplicationId = environment.getProperty("tsf_application_id");
if (StringUtils.isBlank(tsfApplicationId)) {
LOGGER.error("tsf_application_id is empty");
}
// tsf_group_id
String tsfGroupId = environment.getProperty("tsf_group_id");
if (StringUtils.isBlank(tsfGroupId)) {
LOGGER.error("tsf_group_id is empty");
}
// tsf_namespace_id
String tsfNamespaceId = environment.getProperty("tsf_namespace_id");
if (StringUtils.isBlank(tsfNamespaceId)) {
LOGGER.error("tsf_namespace_id is empty");
}
else {
defaultProperties.put("spring.cloud.polaris.namespace", tsfNamespaceId);
}
// tsf_consul_ip
String tsfConsulIp = environment.getProperty("tsf_consul_ip");
if (StringUtils.isBlank(tsfConsulIp)) {
LOGGER.error("tsf_consul_ip is empty");
}
// tsf_consul_port
String tsfConsulPort = environment.getProperty("tsf_consul_port");
if (StringUtils.isBlank(tsfConsulPort)) {
LOGGER.error("tsf_consul_port is empty");
}
// tsf_token
String tsfConsulToken = environment.getProperty("tsf_token");
if (StringUtils.isBlank(tsfConsulToken)) {
LOGGER.error("tsf_token is empty");
}
// tse_polaris_enable
String tsePolarisEnable = environment.getProperty("tse_polaris_enable", "false");
if (StringUtils.equals(tsePolarisEnable, "true")) {
defaultProperties.put("spring.cloud.polaris.config.enabled", "true");
}
else {
defaultProperties.put("spring.cloud.polaris.contract.report.enabled", "false");
defaultProperties.put("spring.cloud.polaris.config.enabled", "true");
defaultProperties.put("spring.cloud.polaris.config.internal-enabled", "false");
defaultProperties.put("spring.cloud.polaris.config.data-source", "consul");
defaultProperties.put("spring.cloud.polaris.config.address", "http://" + tsfConsulIp + ":" + tsfConsulPort);
defaultProperties.put("spring.cloud.polaris.config.port", tsfConsulPort);
defaultProperties.put("spring.cloud.polaris.config.token", tsfConsulToken);
defaultProperties.put("spring.cloud.polaris.config.groups[0].namespace", "config");
defaultProperties.put("spring.cloud.polaris.config.groups[0].name", "application");
defaultProperties.put("spring.cloud.polaris.config.groups[0].files[0]", tsfApplicationId + "/" + tsfGroupId + "/");
defaultProperties.put("spring.cloud.polaris.config.groups[0].files[1]", tsfNamespaceId + "/");
}
// tse_polaris_ip
defaultProperties.put("spring.cloud.polaris.address", "grpc://" + environment.getProperty("tse_polaris_ip", "") + ":8091");
// tsf_sctt_extensions_port
defaultProperties.put("spring.cloud.polaris.stat.port", environment.getProperty("tsf_sctt_extensions_port", "11134"));
// rule based router fail over type
defaultProperties.put("spring.cloud.polaris.router.rule-router.fail-over", "none");
// namespace affinity router
defaultProperties.put("spring.cloud.polaris.router.namespace-router.enabled", "true");
MapPropertySource propertySource = new MapPropertySource("tsf-polaris-properties", defaultProperties);
environment.getPropertySources().addFirst(propertySource);
}
}
}

@ -1,43 +0,0 @@
/*
* 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.context.tsf.metadata;
import com.tencent.cloud.common.spi.InstanceMetadataProvider;
import com.tencent.cloud.common.tsf.ConditionalOnTsfEnabled;
import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration;
import com.tencent.cloud.polaris.context.tsf.config.TsfCoreProperties;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Auto configuration for instanceMetadataProvider for TSF.
*
* @author Hoatian Zhang
*/
@Configuration(proxyBeanMethods = false)
@AutoConfigureAfter(PolarisContextAutoConfiguration.class)
@ConditionalOnTsfEnabled
public class TsfInstanceMetadataAutoConfiguration {
@Bean
public InstanceMetadataProvider tsfInstanceMetadataProvider(TsfCoreProperties tsfCoreProperties) {
return new TsfInstanceMetadataProvider(tsfCoreProperties);
}
}

@ -1,8 +1,7 @@
org.springframework.cloud.bootstrap.BootstrapConfiguration=\ org.springframework.cloud.bootstrap.BootstrapConfiguration=\
com.tencent.cloud.polaris.context.config.PolarisContextBootstrapAutoConfiguration,\ com.tencent.cloud.polaris.context.config.PolarisContextBootstrapAutoConfiguration,\
com.tencent.cloud.polaris.context.tsf.config.TsfCorePropertiesBootstrapConfiguration,\ com.tencent.cloud.polaris.context.config.extend.tsf.TsfContextBootstrapConfiguration
com.tencent.cloud.polaris.context.tsf.consul.TsfConsulBootstrapConfiguration
org.springframework.context.ApplicationListener=\ org.springframework.context.ApplicationListener=\
com.tencent.cloud.polaris.context.logging.PolarisLoggingApplicationListener com.tencent.cloud.polaris.context.logging.PolarisLoggingApplicationListener
org.springframework.boot.env.EnvironmentPostProcessor=\ org.springframework.boot.env.EnvironmentPostProcessor=\
com.tencent.cloud.polaris.context.tsf.env.TsfCoreEnvironmentPostProcessor com.tencent.cloud.polaris.context.config.extend.tsf.TsfCoreEnvironmentPostProcessor

@ -1,5 +1,3 @@
com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration
com.tencent.cloud.polaris.context.config.PolarisContextPostConfiguration com.tencent.cloud.polaris.context.config.PolarisContextPostConfiguration
com.tencent.cloud.polaris.context.tsf.config.TsfCorePropertiesAutoConfiguration com.tencent.cloud.polaris.context.config.extend.tsf.TsfContextAutoConfiguration
com.tencent.cloud.polaris.context.tsf.consul.TsfConsulAutoConfiguration
com.tencent.cloud.polaris.context.tsf.metadata.TsfInstanceMetadataAutoConfiguration

@ -20,6 +20,7 @@ package com.tencent.cloud.polaris.context;
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.client.api.SDKContext;
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;
import org.junit.platform.commons.util.StringUtils; import org.junit.platform.commons.util.StringUtils;
@ -48,6 +49,11 @@ public class PolarisContextGetHostTest {
@Autowired @Autowired
private PolarisContextProperties polarisContextProperties; private PolarisContextProperties polarisContextProperties;
@BeforeEach
public void setUp() {
PolarisSDKContextManager.innerDestroy();
}
@Test @Test
public void testGetConfigHost() { public void testGetConfigHost() {
String bindIP = polarisSDKContextManager.getSDKContext().getConfig().getGlobal().getAPI().getBindIP(); String bindIP = polarisSDKContextManager.getSDKContext().getConfig().getGlobal().getAPI().getBindIP();

@ -0,0 +1,72 @@
/*
* 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.context.config.extend.consul;
import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Test for {@link ConsulPropertiesTest}.
*
* @author Haotian Zhang
*/
@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = ConsulPropertiesTest.TestApplication.class)
@ActiveProfiles("test")
public class ConsulPropertiesTest {
@Autowired
private ConsulProperties consulProperties;
@BeforeEach
public void setUp() {
PolarisSDKContextManager.innerDestroy();
}
@AfterEach
public void tearDown() {
PolarisSDKContextManager.innerDestroy();
}
@Test
public void testDefaultInitialization() {
assertThat(consulProperties).isNotNull();
assertThat(consulProperties.isEnabled()).isFalse();
assertThat(consulProperties.getHost()).isEqualTo("localhost");
assertThat(consulProperties.getPort()).isEqualTo(8500);
}
@SpringBootApplication
protected static class TestApplication {
static {
PolarisSDKContextManager.innerDestroy();
}
}
}
Loading…
Cancel
Save