feat:add spring cloud 2020.0.x support

pull/78/head
skyehtzhang 2 years ago
parent 9f5bc3b0b7
commit 2781270c16

@ -5,9 +5,9 @@ name: Test with Junit
on:
push:
branches: [ main ]
branches: [ 2020.0 ]
pull_request:
branches: [ main ]
branches: [ 2020.0 ]
jobs:
build:

@ -1,43 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-build</artifactId>
<version>2.3.4.RELEASE</version>
<relativePath/>
</parent>
<modelVersion>4.0.0</modelVersion>
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-build</artifactId>
<version>3.0.4</version>
<relativePath/>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent</artifactId>
<packaging>pom</packaging>
<version>${revision}</version>
<name>Spring Cloud Tencent</name>
<description>Spring Cloud Tencent</description>
<url>https://github.com/Tencent/spring-cloud-tencent/tree/main</url>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent</artifactId>
<packaging>pom</packaging>
<version>${revision}</version>
<name>Spring Cloud Tencent</name>
<description>Spring Cloud Tencent</description>
<url>https://github.com/Tencent/spring-cloud-tencent/tree/main</url>
<organization>
<name>Tencent</name>
<url>https://opensource.tencent.com/</url>
</organization>
<organization>
<name>Tencent</name>
<url>https://opensource.tencent.com/</url>
</organization>
<licenses>
<license>
<name>The BSD 3-Clause License (BSD3)</name>
<url>https://raw.githubusercontent.com/Tencent/spring-cloud-tencent/main/LICENSE</url>
<distribution>repo</distribution>
</license>
</licenses>
<licenses>
<license>
<name>The BSD 3-Clause License (BSD3)</name>
<url>https://raw.githubusercontent.com/Tencent/spring-cloud-tencent/main/LICENSE</url>
<distribution>repo</distribution>
</license>
</licenses>
<scm>
<url>https://github.com/Tencent/spring-cloud-tencent</url>
<connection>scm:git:git@github.com:Tencent/spring-cloud-tencent.git</connection>
<developerConnection>scm:git:git@github.com:Tencent/spring-cloud-tencent.git</developerConnection>
</scm>
<scm>
<url>https://github.com/Tencent/spring-cloud-tencent</url>
<connection>scm:git:git@github.com:Tencent/spring-cloud-tencent.git</connection>
<developerConnection>scm:git:git@github.com:Tencent/spring-cloud-tencent.git</developerConnection>
</scm>
<modules>
<modules>
<module>spring-cloud-tencent-polaris-context</module>
<module>spring-cloud-tencent-commons</module>
<module>spring-cloud-starter-tencent-metadata-transfer</module>
@ -48,7 +48,7 @@
<module>spring-cloud-tencent-dependencies</module>
<module>spring-cloud-tencent-examples</module>
<module>spring-cloud-tencent-coverage</module>
<module>spring-cloud-starter-tencent-polaris-config</module>
<module>spring-cloud-starter-tencent-polaris-config</module>
</modules>
<developers>
@ -77,10 +77,10 @@
<properties>
<!-- Project revision -->
<revision>1.2.0-Hoxton.SR9-SNAPSHOT</revision>
<revision>1.2.0-2020.0.5-SNAPSHOT</revision>
<!-- Spring Cloud -->
<spring.cloud.version>Hoxton.SR9</spring.cloud.version>
<spring.cloud.version>2020.0.5</spring.cloud.version>
<!-- Dependencies -->
<logback.version>1.2.7</logback.version>
@ -266,31 +266,31 @@
</executions>
</plugin>
</plugins>
</build>
</build>
<distributionManagement>
<snapshotRepository>
<id>nexus-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</snapshotRepository>
<repository>
<id>nexus-releases</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
</profile>
</profiles>
<distributionManagement>
<snapshotRepository>
<id>nexus-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</snapshotRepository>
<repository>
<id>nexus-releases</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
</profile>
</profiles>
<repositories>
<repository>
<id>nexus-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<repositories>
<repository>
<id>nexus-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
</project>

@ -21,12 +21,6 @@
</dependency>
<!-- Spring Cloud Tencent dependencies end -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
@ -47,7 +41,7 @@
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
<scope>test</scope>
</dependency>

@ -20,9 +20,7 @@ package com.tencent.cloud.metadata.config;
import java.util.List;
import java.util.Map;
import com.netflix.zuul.ZuulFilter;
import com.tencent.cloud.metadata.core.filter.gateway.Metadata2HeaderScgFilter;
import com.tencent.cloud.metadata.core.filter.gateway.Metadata2HeaderZuulFilter;
import com.tencent.cloud.metadata.core.interceptor.Metadata2HeaderFeignInterceptor;
import com.tencent.cloud.metadata.core.interceptor.Metadata2HeaderRestTemplateInterceptor;
@ -46,20 +44,6 @@ import org.springframework.web.client.RestTemplate;
@Configuration
public class MetadataTransferAutoConfiguration {
/**
* Create when gateway application is Zuul.
*/
@Configuration
@ConditionalOnClass(name = "com.netflix.zuul.http.ZuulServlet")
static class MetadataTransferZuulFilterConfig {
@Bean
public ZuulFilter metadata2HeaderZuulFilter() {
return new Metadata2HeaderZuulFilter();
}
}
/**
* Create when gateway application is SCG.
*/
@ -106,35 +90,29 @@ public class MetadataTransferAutoConfiguration {
BeanPostProcessor metadata2HeaderRestTemplatePostProcessor(
Metadata2HeaderRestTemplateInterceptor metadata2HeaderRestTemplateInterceptor) {
// Coping with multiple bean injection scenarios
Map<String, RestTemplate> beans = this.context
.getBeansOfType(RestTemplate.class);
Map<String, RestTemplate> beans = this.context.getBeansOfType(RestTemplate.class);
// If the restTemplate has been created when the
// MetadataRestTemplatePostProcessor Bean
// is initialized, then manually set the interceptor.
if (!CollectionUtils.isEmpty(beans)) {
for (RestTemplate restTemplate : beans.values()) {
List<ClientHttpRequestInterceptor> interceptors = restTemplate
.getInterceptors();
List<ClientHttpRequestInterceptor> interceptors = restTemplate.getInterceptors();
// Avoid setting interceptor repeatedly.
if (null != interceptors && !interceptors
.contains(metadata2HeaderRestTemplateInterceptor)) {
if (null != interceptors && !interceptors.contains(metadata2HeaderRestTemplateInterceptor)) {
interceptors.add(metadata2HeaderRestTemplateInterceptor);
restTemplate.setInterceptors(interceptors);
}
}
}
return new Metadata2HeaderRestTemplatePostProcessor(
metadata2HeaderRestTemplateInterceptor);
return new Metadata2HeaderRestTemplatePostProcessor(metadata2HeaderRestTemplateInterceptor);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
}
public static class Metadata2HeaderRestTemplatePostProcessor
implements BeanPostProcessor {
public static class Metadata2HeaderRestTemplatePostProcessor implements BeanPostProcessor {
private Metadata2HeaderRestTemplateInterceptor metadata2HeaderRestTemplateInterceptor;
@ -152,11 +130,9 @@ public class MetadataTransferAutoConfiguration {
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (bean instanceof RestTemplate) {
RestTemplate restTemplate = (RestTemplate) bean;
List<ClientHttpRequestInterceptor> interceptors = restTemplate
.getInterceptors();
List<ClientHttpRequestInterceptor> interceptors = restTemplate.getInterceptors();
// Avoid setting interceptor repeatedly.
if (null != interceptors && !interceptors
.contains(metadata2HeaderRestTemplateInterceptor)) {
if (null != interceptors && !interceptors.contains(metadata2HeaderRestTemplateInterceptor)) {
interceptors.add(this.metadata2HeaderRestTemplateInterceptor);
restTemplate.setInterceptors(interceptors);
}

@ -34,7 +34,7 @@ import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.util.CollectionUtils;
import org.springframework.web.server.ServerWebExchange;
import static org.springframework.cloud.gateway.filter.LoadBalancerClientFilter.LOAD_BALANCER_CLIENT_FILTER_ORDER;
import static org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter.LOAD_BALANCER_CLIENT_FILTER_ORDER;
/**
* Scg filter used for writing metadata in HTTP request header.
@ -43,8 +43,7 @@ import static org.springframework.cloud.gateway.filter.LoadBalancerClientFilter.
*/
public class Metadata2HeaderScgFilter implements GlobalFilter, Ordered {
private static final int METADATA_SCG_FILTER_ORDER = LOAD_BALANCER_CLIENT_FILTER_ORDER
+ 1;
private static final int METADATA_SCG_FILTER_ORDER = LOAD_BALANCER_CLIENT_FILTER_ORDER + 1;
@Override
public int getOrder() {
@ -57,20 +56,17 @@ public class Metadata2HeaderScgFilter implements GlobalFilter, Ordered {
ServerHttpRequest.Builder builder = exchange.getRequest().mutate();
// get metadata of current thread
MetadataContext metadataContext = exchange
.getAttribute(MetadataConstant.HeaderName.METADATA_CONTEXT);
MetadataContext metadataContext = exchange.getAttribute(MetadataConstant.HeaderName.METADATA_CONTEXT);
// add new metadata and cover old
if (metadataContext == null) {
metadataContext = MetadataContextHolder.get();
}
Map<String, String> customMetadata = metadataContext
.getAllTransitiveCustomMetadata();
Map<String, String> customMetadata = metadataContext.getAllTransitiveCustomMetadata();
if (!CollectionUtils.isEmpty(customMetadata)) {
String metadataStr = JacksonUtils.serialize2Json(customMetadata);
try {
builder.header(MetadataConstant.HeaderName.CUSTOM_METADATA,
URLEncoder.encode(metadataStr, "UTF-8"));
builder.header(MetadataConstant.HeaderName.CUSTOM_METADATA, URLEncoder.encode(metadataStr, "UTF-8"));
}
catch (UnsupportedEncodingException e) {
builder.header(MetadataConstant.HeaderName.CUSTOM_METADATA, metadataStr);

@ -1,84 +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.metadata.core.filter.gateway;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Map;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.tencent.cloud.common.constant.MetadataConstant;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.util.JacksonUtils;
import org.springframework.util.CollectionUtils;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.RIBBON_ROUTING_FILTER_ORDER;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.ROUTE_TYPE;
/**
* Zuul filter used for writing metadata in HTTP request header.
*
* @author Haotian Zhang
*/
public class Metadata2HeaderZuulFilter extends ZuulFilter {
@Override
public String filterType() {
return ROUTE_TYPE;
}
@Override
public int filterOrder() {
return RIBBON_ROUTING_FILTER_ORDER - 1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {
// get request context
RequestContext requestContext = RequestContext.getCurrentContext();
// get metadata of current thread
MetadataContext metadataContext = MetadataContextHolder.get();
// add new metadata and cover old
Map<String, String> customMetadata = metadataContext
.getAllTransitiveCustomMetadata();
if (!CollectionUtils.isEmpty(customMetadata)) {
String metadataStr = JacksonUtils.serialize2Json(customMetadata);
try {
requestContext.addZuulRequestHeader(
MetadataConstant.HeaderName.CUSTOM_METADATA,
URLEncoder.encode(metadataStr, "UTF-8"));
}
catch (UnsupportedEncodingException e) {
requestContext.addZuulRequestHeader(
MetadataConstant.HeaderName.CUSTOM_METADATA, metadataStr);
}
}
return null;
}
}

@ -43,8 +43,7 @@ import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUST
*/
public class Metadata2HeaderFeignInterceptor implements RequestInterceptor, Ordered {
private static final Logger LOG = LoggerFactory
.getLogger(Metadata2HeaderFeignInterceptor.class);
private static final Logger LOG = LoggerFactory.getLogger(Metadata2HeaderFeignInterceptor.class);
@Override
public int getOrder() {
@ -57,27 +56,22 @@ public class Metadata2HeaderFeignInterceptor implements RequestInterceptor, Orde
MetadataContext metadataContext = MetadataContextHolder.get();
// add new metadata and cover old
if (!CollectionUtils.isEmpty(requestTemplate.headers()) && !CollectionUtils
.isEmpty(requestTemplate.headers().get(CUSTOM_METADATA))) {
for (String headerMetadataStr : requestTemplate.headers()
.get(CUSTOM_METADATA)) {
Map<String, String> headerMetadataMap = JacksonUtils
.deserialize2Map(headerMetadataStr);
if (!CollectionUtils.isEmpty(requestTemplate.headers())
&& !CollectionUtils.isEmpty(requestTemplate.headers().get(CUSTOM_METADATA))) {
for (String headerMetadataStr : requestTemplate.headers().get(CUSTOM_METADATA)) {
Map<String, String> headerMetadataMap = JacksonUtils.deserialize2Map(headerMetadataStr);
for (String key : headerMetadataMap.keySet()) {
metadataContext.putTransitiveCustomMetadata(key,
headerMetadataMap.get(key));
metadataContext.putTransitiveCustomMetadata(key, headerMetadataMap.get(key));
}
}
}
Map<String, String> customMetadata = metadataContext
.getAllTransitiveCustomMetadata();
Map<String, String> customMetadata = metadataContext.getAllTransitiveCustomMetadata();
if (!CollectionUtils.isEmpty(customMetadata)) {
String metadataStr = JacksonUtils.serialize2Json(customMetadata);
requestTemplate.removeHeader(CUSTOM_METADATA);
try {
requestTemplate.header(CUSTOM_METADATA,
URLEncoder.encode(metadataStr, "UTF-8"));
requestTemplate.header(CUSTOM_METADATA, URLEncoder.encode(metadataStr, "UTF-8"));
}
catch (UnsupportedEncodingException e) {
LOG.error("Set header failed.", e);

@ -26,6 +26,7 @@ import com.tencent.cloud.common.constant.MetadataConstant;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.util.JacksonUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.core.Ordered;
import org.springframework.http.HttpRequest;
@ -33,7 +34,6 @@ import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
/**
* Interceptor used for adding the metadata in http headers from context when web client
@ -41,8 +41,7 @@ import org.springframework.util.StringUtils;
*
* @author Haotian Zhang
*/
public class Metadata2HeaderRestTemplateInterceptor
implements ClientHttpRequestInterceptor, Ordered {
public class Metadata2HeaderRestTemplateInterceptor implements ClientHttpRequestInterceptor, Ordered {
@Override
public int getOrder() {
@ -56,18 +55,14 @@ public class Metadata2HeaderRestTemplateInterceptor
MetadataContext metadataContext = MetadataContextHolder.get();
// add new metadata and cover old
String metadataStr = httpRequest.getHeaders()
.getFirst(MetadataConstant.HeaderName.CUSTOM_METADATA);
if (!StringUtils.isEmpty(metadataStr)) {
Map<String, String> headerMetadataMap = JacksonUtils
.deserialize2Map(metadataStr);
String metadataStr = httpRequest.getHeaders().getFirst(MetadataConstant.HeaderName.CUSTOM_METADATA);
if (!StringUtils.isNotBlank(metadataStr)) {
Map<String, String> headerMetadataMap = JacksonUtils.deserialize2Map(metadataStr);
for (String key : headerMetadataMap.keySet()) {
metadataContext.putTransitiveCustomMetadata(key,
headerMetadataMap.get(key));
metadataContext.putTransitiveCustomMetadata(key, headerMetadataMap.get(key));
}
}
Map<String, String> customMetadata = metadataContext
.getAllTransitiveCustomMetadata();
Map<String, String> customMetadata = metadataContext.getAllTransitiveCustomMetadata();
if (!CollectionUtils.isEmpty(customMetadata)) {
metadataStr = JacksonUtils.serialize2Json(customMetadata);
try {
@ -75,8 +70,7 @@ public class Metadata2HeaderRestTemplateInterceptor
URLEncoder.encode(metadataStr, "UTF-8"));
}
catch (UnsupportedEncodingException e) {
httpRequest.getHeaders().set(MetadataConstant.HeaderName.CUSTOM_METADATA,
metadataStr);
httpRequest.getHeaders().set(MetadataConstant.HeaderName.CUSTOM_METADATA, metadataStr);
}
}
return clientHttpRequestExecution.execute(httpRequest, bytes);

@ -17,7 +17,6 @@
package com.tencent.cloud.metadata.config;
import com.tencent.cloud.metadata.core.filter.gateway.Metadata2HeaderZuulFilter;
import com.tencent.cloud.metadata.core.interceptor.Metadata2HeaderFeignInterceptor;
import com.tencent.cloud.metadata.core.interceptor.Metadata2HeaderRestTemplateInterceptor;
import org.assertj.core.api.Assertions;
@ -41,26 +40,18 @@ public class MetadataTransferAutoConfigurationTest {
*/
@Test
public void test1() {
this.applicationContextRunner
.withConfiguration(
AutoConfigurations.of(MetadataTransferAutoConfiguration.class))
this.applicationContextRunner.withConfiguration(AutoConfigurations.of(MetadataTransferAutoConfiguration.class))
.run(context -> {
Assertions.assertThat(context).hasSingleBean(
MetadataTransferAutoConfiguration.MetadataTransferFeignInterceptorConfig.class);
Assertions.assertThat(context).hasSingleBean(Metadata2HeaderFeignInterceptor.class);
Assertions.assertThat(context)
.hasSingleBean(Metadata2HeaderFeignInterceptor.class);
Assertions.assertThat(context).hasSingleBean(
MetadataTransferAutoConfiguration.MetadataTransferRestTemplateConfig.class);
Assertions.assertThat(context)
.hasSingleBean(Metadata2HeaderRestTemplateInterceptor.class);
.hasSingleBean(MetadataTransferAutoConfiguration.MetadataTransferRestTemplateConfig.class);
Assertions.assertThat(context).hasSingleBean(Metadata2HeaderRestTemplateInterceptor.class);
Assertions.assertThat(context).hasSingleBean(
MetadataTransferAutoConfiguration.MetadataTransferRestTemplateConfig.Metadata2HeaderRestTemplatePostProcessor.class);
Assertions.assertThat(context).hasSingleBean(
MetadataTransferAutoConfiguration.MetadataTransferZuulFilterConfig.class);
Assertions.assertThat(context)
.hasSingleBean(Metadata2HeaderZuulFilter.class);
Assertions.assertThat(context).hasSingleBean(
MetadataTransferAutoConfiguration.MetadataTransferScgFilterConfig.class);
.hasSingleBean(MetadataTransferAutoConfiguration.MetadataTransferScgFilterConfig.class);
Assertions.assertThat(context).hasSingleBean(GlobalFilter.class);
});
}

@ -50,10 +50,8 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
* @author Haotian Zhang
*/
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = DEFINED_PORT,
classes = Metadata2HeaderFeignInterceptorTest.TestApplication.class,
properties = { "server.port=8081",
"spring.config.location = classpath:application-test.yml" })
@SpringBootTest(webEnvironment = DEFINED_PORT, classes = Metadata2HeaderFeignInterceptorTest.TestApplication.class,
properties = { "server.port=8081", "spring.config.location = classpath:application-test.yml" })
public class Metadata2HeaderFeignInterceptorTest {
@Autowired
@ -65,21 +63,12 @@ public class Metadata2HeaderFeignInterceptorTest {
@Test
public void test1() {
String metadata = testFeign.test();
Assertions.assertThat(metadata)
.isEqualTo("{\"a\":\"11\",\"b\":\"22\",\"c\":\"33\"}{}");
Assertions.assertThat(metadataLocalProperties.getContent().get("a"))
.isEqualTo("1");
Assertions.assertThat(metadataLocalProperties.getContent().get("b"))
.isEqualTo("2");
Assertions
.assertThat(MetadataContextHolder.get().getTransitiveCustomMetadata("a"))
.isEqualTo("11");
Assertions
.assertThat(MetadataContextHolder.get().getTransitiveCustomMetadata("b"))
.isEqualTo("22");
Assertions
.assertThat(MetadataContextHolder.get().getTransitiveCustomMetadata("c"))
.isEqualTo("33");
Assertions.assertThat(metadata).isEqualTo("{\"a\":\"11\",\"b\":\"22\",\"c\":\"33\"}{}");
Assertions.assertThat(metadataLocalProperties.getContent().get("a")).isEqualTo("1");
Assertions.assertThat(metadataLocalProperties.getContent().get("b")).isEqualTo("2");
Assertions.assertThat(MetadataContextHolder.get().getTransitiveCustomMetadata("a")).isEqualTo("11");
Assertions.assertThat(MetadataContextHolder.get().getTransitiveCustomMetadata("b")).isEqualTo("22");
Assertions.assertThat(MetadataContextHolder.get().getTransitiveCustomMetadata("c")).isEqualTo("33");
}
@SpringBootApplication
@ -88,20 +77,17 @@ public class Metadata2HeaderFeignInterceptorTest {
protected static class TestApplication {
@RequestMapping("/test")
public String test(
@RequestHeader(MetadataConstant.HeaderName.CUSTOM_METADATA) String customMetadataStr)
public String test(@RequestHeader(MetadataConstant.HeaderName.CUSTOM_METADATA) String customMetadataStr)
throws UnsupportedEncodingException {
String systemMetadataStr = JacksonUtils
.serialize2Json(MetadataContextHolder.get().getAllSystemMetadata());
String systemMetadataStr = JacksonUtils.serialize2Json(MetadataContextHolder.get().getAllSystemMetadata());
return URLDecoder.decode(customMetadataStr, "UTF-8") + systemMetadataStr;
}
@FeignClient(name = "test-feign", url = "http://localhost:8081")
public interface TestFeign {
@RequestMapping(value = "/test",
headers = { MetadataConstant.HeaderName.CUSTOM_METADATA
+ "={\"a\":\"11" + "\",\"b\":\"22\",\"c\":\"33\"}" })
@RequestMapping(value = "/test", headers = {
MetadataConstant.HeaderName.CUSTOM_METADATA + "={\"a\":\"11" + "\",\"b\":\"22\",\"c\":\"33\"}" })
String test();
}

@ -68,28 +68,17 @@ public class Metadata2HeaderRestTemplateInterceptorTest {
@Test
public void test1() {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.set(MetadataConstant.HeaderName.CUSTOM_METADATA,
"{\"a\":\"11\",\"b\":\"22\",\"c\":\"33\"}");
httpHeaders.set(MetadataConstant.HeaderName.CUSTOM_METADATA, "{\"a\":\"11\",\"b\":\"22\",\"c\":\"33\"}");
HttpEntity<String> httpEntity = new HttpEntity<>(httpHeaders);
String metadata = restTemplate
.exchange("http://localhost:" + localServerPort + "/test", HttpMethod.GET,
httpEntity, String.class)
.exchange("http://localhost:" + localServerPort + "/test", HttpMethod.GET, httpEntity, String.class)
.getBody();
Assertions.assertThat(metadata)
.isEqualTo("{\"a\":\"11\",\"b\":\"22\",\"c\":\"33\"}{}");
Assertions.assertThat(metadataLocalProperties.getContent().get("a"))
.isEqualTo("1");
Assertions.assertThat(metadataLocalProperties.getContent().get("b"))
.isEqualTo("2");
Assertions
.assertThat(MetadataContextHolder.get().getTransitiveCustomMetadata("a"))
.isEqualTo("11");
Assertions
.assertThat(MetadataContextHolder.get().getTransitiveCustomMetadata("b"))
.isEqualTo("22");
Assertions
.assertThat(MetadataContextHolder.get().getTransitiveCustomMetadata("c"))
.isEqualTo("33");
Assertions.assertThat(metadata).isEqualTo("{\"a\":\"11\",\"b\":\"22\",\"c\":\"33\"}{}");
Assertions.assertThat(metadataLocalProperties.getContent().get("a")).isEqualTo("1");
Assertions.assertThat(metadataLocalProperties.getContent().get("b")).isEqualTo("2");
Assertions.assertThat(MetadataContextHolder.get().getTransitiveCustomMetadata("a")).isEqualTo("11");
Assertions.assertThat(MetadataContextHolder.get().getTransitiveCustomMetadata("b")).isEqualTo("22");
Assertions.assertThat(MetadataContextHolder.get().getTransitiveCustomMetadata("c")).isEqualTo("33");
}
@SpringBootApplication
@ -102,11 +91,9 @@ public class Metadata2HeaderRestTemplateInterceptorTest {
}
@RequestMapping("/test")
public String test(
@RequestHeader(MetadataConstant.HeaderName.CUSTOM_METADATA) String customMetadataStr)
public String test(@RequestHeader(MetadataConstant.HeaderName.CUSTOM_METADATA) String customMetadataStr)
throws UnsupportedEncodingException {
String systemMetadataStr = JacksonUtils
.serialize2Json(MetadataContextHolder.get().getAllSystemMetadata());
String systemMetadataStr = JacksonUtils.serialize2Json(MetadataContextHolder.get().getAllSystemMetadata());
return URLDecoder.decode(customMetadataStr, "UTF-8") + systemMetadataStr;
}

@ -4,7 +4,6 @@ spring:
autoconfigure:
exclude:
- org.springframework.cloud.gateway.config.GatewayAutoConfiguration
- org.springframework.cloud.netflix.zuul.ZuulServerAutoConfiguration
cloud:
tencent:
metadata:

@ -44,12 +44,6 @@
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>

@ -30,8 +30,8 @@ import org.springframework.context.annotation.Configuration;
*
* @author lepdou 2022-03-29
*/
@ConditionalOnProperty(value = "spring.cloud.polaris.circuitbreaker.enabled",
havingValue = "true", matchIfMissing = true)
@ConditionalOnProperty(value = "spring.cloud.polaris.circuitbreaker.enabled", havingValue = "true",
matchIfMissing = true)
@Configuration(proxyBeanMethods = false)
public class PolarisCircuitBreakerBootstrapConfiguration {

@ -39,8 +39,8 @@ import static org.springframework.core.Ordered.HIGHEST_PRECEDENCE;
*
* @author Haotian Zhang
*/
@ConditionalOnProperty(value = "spring.cloud.polaris.circuitbreaker.enabled",
havingValue = "true", matchIfMissing = true)
@ConditionalOnProperty(value = "spring.cloud.polaris.circuitbreaker.enabled", havingValue = "true",
matchIfMissing = true)
@Configuration(proxyBeanMethods = false)
@AutoConfigureAfter(PolarisContextConfiguration.class)
@AutoConfigureBefore(FeignAutoConfiguration.class)
@ -53,8 +53,7 @@ public class PolarisFeignClientAutoConfiguration {
@Bean
@Order(HIGHEST_PRECEDENCE)
public PolarisFeignBeanPostProcessor polarisFeignBeanPostProcessor(
ConsumerAPI consumerAPI) {
public PolarisFeignBeanPostProcessor polarisFeignBeanPostProcessor(ConsumerAPI consumerAPI) {
return new PolarisFeignBeanPostProcessor(consumerAPI);
}

@ -24,19 +24,17 @@ import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.cloud.client.loadbalancer.LoadBalancerProperties;
import org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient;
import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory;
import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.cloud.openfeign.loadbalancer.RetryableFeignBlockingLoadBalancerClient;
/**
* Wrap Spring Bean and decorating proxy for Feign Client.
*
* @author Haotian Zhang
*/
public class PolarisFeignBeanPostProcessor
implements BeanPostProcessor, BeanFactoryAware {
public class PolarisFeignBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware {
private final ConsumerAPI consumerAPI;
@ -47,24 +45,18 @@ public class PolarisFeignBeanPostProcessor
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return wrapper(bean);
}
private Object wrapper(Object bean) {
if (isNeedWrap(bean)) {
if (bean instanceof LoadBalancerFeignClient) {
LoadBalancerFeignClient client = ((LoadBalancerFeignClient) bean);
return new PolarisLoadBalancerFeignClient(
createPolarisFeignClient(client.getDelegate()), factory(),
clientFactory());
}
if (bean instanceof FeignBlockingLoadBalancerClient) {
FeignBlockingLoadBalancerClient client = (FeignBlockingLoadBalancerClient) bean;
return new PolarisFeignBlockingLoadBalancerClient(
createPolarisFeignClient(client.getDelegate()),
factory.getBean(BlockingLoadBalancerClient.class));
if (bean instanceof RetryableFeignBlockingLoadBalancerClient) {
RetryableFeignBlockingLoadBalancerClient client = (RetryableFeignBlockingLoadBalancerClient) bean;
return new PolarisFeignBlockingLoadBalancerClient(createPolarisFeignClient(client.getDelegate()),
factory.getBean(BlockingLoadBalancerClient.class),
factory.getBean(LoadBalancerProperties.class),
factory.getBean(LoadBalancerClientFactory.class));
}
return createPolarisFeignClient((Client) bean);
}
@ -73,8 +65,7 @@ public class PolarisFeignBeanPostProcessor
private boolean isNeedWrap(Object bean) {
return bean instanceof Client && !(bean instanceof PolarisFeignClient)
&& !(bean instanceof PolarisFeignBlockingLoadBalancerClient)
&& !(bean instanceof PolarisLoadBalancerFeignClient);
&& !(bean instanceof PolarisFeignBlockingLoadBalancerClient);
}
private PolarisFeignClient createPolarisFeignClient(Client delegate) {
@ -86,12 +77,4 @@ public class PolarisFeignBeanPostProcessor
this.factory = beanFactory;
}
CachingSpringLoadBalancerFactory factory() {
return this.factory.getBean(CachingSpringLoadBalancerFactory.class);
}
SpringClientFactory clientFactory() {
return this.factory.getBean(SpringClientFactory.class);
}
}

@ -19,7 +19,9 @@ package com.tencent.cloud.polaris.circuitbreaker.feign;
import feign.Client;
import org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerProperties;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient;
/**
@ -27,12 +29,11 @@ import org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalance
*
* @author Haotian Zhang
*/
public class PolarisFeignBlockingLoadBalancerClient
extends FeignBlockingLoadBalancerClient {
public class PolarisFeignBlockingLoadBalancerClient extends FeignBlockingLoadBalancerClient {
public PolarisFeignBlockingLoadBalancerClient(Client delegate,
BlockingLoadBalancerClient loadBalancerClient) {
super(delegate, loadBalancerClient);
public PolarisFeignBlockingLoadBalancerClient(Client delegate, LoadBalancerClient loadBalancerClient,
LoadBalancerProperties properties, LoadBalancerClientFactory loadBalancerClientFactory) {
super(delegate, loadBalancerClient, properties, loadBalancerClientFactory);
}
}

@ -75,21 +75,17 @@ public class PolarisFeignClient implements Client {
ServiceCallResult resultRequest = new ServiceCallResult();
MetadataContext metadataContext = MetadataContextHolder.get();
String namespace = metadataContext
.getSystemMetadata(SystemMetadataKey.PEER_NAMESPACE);
String namespace = metadataContext.getSystemMetadata(SystemMetadataKey.PEER_NAMESPACE);
resultRequest.setNamespace(namespace);
String serviceName = metadataContext
.getSystemMetadata(SystemMetadataKey.PEER_SERVICE);
String serviceName = metadataContext.getSystemMetadata(SystemMetadataKey.PEER_SERVICE);
resultRequest.setService(serviceName);
String method = metadataContext.getSystemMetadata(SystemMetadataKey.PEER_PATH);
resultRequest.setMethod(method);
resultRequest.setRetStatus(RetStatus.RetSuccess);
String sourceNamespace = MetadataContext.LOCAL_NAMESPACE;
String sourceService = MetadataContext.LOCAL_SERVICE;
if (StringUtils.isNotBlank(sourceNamespace)
&& StringUtils.isNotBlank(sourceService)) {
resultRequest
.setCallerService(new ServiceKey(sourceNamespace, sourceService));
if (StringUtils.isNotBlank(sourceNamespace) && StringUtils.isNotBlank(sourceService)) {
resultRequest.setCallerService(new ServiceKey(sourceNamespace, sourceService));
}
URI uri = URI.create(request.url());
resultRequest.setHost(uri.getHost());

@ -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.circuitbreaker.feign;
import feign.Client;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory;
import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient;
/**
* Wrap for {@link LoadBalancerFeignClient}.
*
* @author Haotian Zhang
*/
public class PolarisLoadBalancerFeignClient extends LoadBalancerFeignClient {
public PolarisLoadBalancerFeignClient(Client delegate,
CachingSpringLoadBalancerFactory lbClientFactory,
SpringClientFactory clientFactory) {
super(delegate, lbClientFactory, clientFactory);
}
}

@ -45,8 +45,7 @@ public class PolarisFeignClientTest {
@Test
public void testPolarisFeignBeanPostProcessor() {
final PolarisFeignBeanPostProcessor postProcessor = springCtx
.getBean(PolarisFeignBeanPostProcessor.class);
final PolarisFeignBeanPostProcessor postProcessor = springCtx.getBean(PolarisFeignBeanPostProcessor.class);
Assertions.assertNotNull(postProcessor, "PolarisFeignBeanPostProcessor");
}
@ -56,9 +55,6 @@ public class PolarisFeignClientTest {
if (client instanceof PolarisFeignClient) {
return;
}
if (client instanceof PolarisLoadBalancerFeignClient) {
return;
}
if (client instanceof PolarisFeignBlockingLoadBalancerClient) {
return;
}

@ -37,8 +37,7 @@ public class TestPolarisFeignApp {
SpringApplication.run(TestPolarisFeignApp.class);
}
@FeignClient(name = "feign-service-polaris",
fallback = TestPolarisServiceFallback.class)
@FeignClient(name = "feign-service-polaris", fallback = TestPolarisServiceFallback.class)
public interface TestPolarisService {
/**

@ -48,8 +48,7 @@ public class ConfigurationModifier implements PolarisConfigModifier {
}
// override polaris config server address
List<String> addresses = AddressUtils
.parseAddressList(polarisConfigProperties.getAddress());
List<String> addresses = AddressUtils.parseAddressList(polarisConfigProperties.getAddress());
configuration.getConfigFile().getServerConnector().setAddresses(addresses);
}

@ -28,22 +28,20 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* polaris config module auto configuration at init application context phase.
* polaris config module auto configuration at init application context phase.
*
* @author lepdou 2022-03-28
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(value = "spring.cloud.polaris.config.enabled",
matchIfMissing = true)
@ConditionalOnProperty(value = "spring.cloud.polaris.config.enabled", matchIfMissing = true)
public class PolarisConfigAutoConfiguration {
@Bean
public PolarisPropertySourceAutoRefresher polarisPropertySourceAutoRefresher(
PolarisConfigProperties polarisConfigProperties,
PolarisPropertySourceManager polarisPropertySourceManager,
PolarisConfigProperties polarisConfigProperties, PolarisPropertySourceManager polarisPropertySourceManager,
ContextRefresher contextRefresher) {
return new PolarisPropertySourceAutoRefresher(polarisConfigProperties,
polarisPropertySourceManager, contextRefresher);
return new PolarisPropertySourceAutoRefresher(polarisConfigProperties, polarisPropertySourceManager,
contextRefresher);
}
}

@ -37,8 +37,7 @@ import org.springframework.context.annotation.Import;
* @author lepdou 2022-03-10
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(value = "spring.cloud.polaris.config.enabled",
matchIfMissing = true)
@ConditionalOnProperty(value = "spring.cloud.polaris.config.enabled", matchIfMissing = true)
@Import(PolarisContextConfiguration.class)
public class PolarisConfigBootstrapAutoConfiguration {
@ -58,13 +57,10 @@ public class PolarisConfigBootstrapAutoConfiguration {
}
@Bean
public PolarisConfigFileLocator polarisConfigFileLocator(
PolarisConfigProperties polarisConfigProperties,
PolarisContextProperties polarisContextProperties,
ConfigFileService configFileService,
public PolarisConfigFileLocator polarisConfigFileLocator(PolarisConfigProperties polarisConfigProperties,
PolarisContextProperties polarisContextProperties, ConfigFileService configFileService,
PolarisPropertySourceManager polarisPropertySourceManager) {
return new PolarisConfigFileLocator(polarisConfigProperties,
polarisContextProperties, configFileService,
return new PolarisConfigFileLocator(polarisConfigProperties, polarisContextProperties, configFileService,
polarisPropertySourceManager);
}

@ -49,8 +49,7 @@ import org.springframework.util.StringUtils;
@Order(0)
public class PolarisConfigFileLocator implements PropertySourceLocator {
private static final Logger LOGGER = LoggerFactory
.getLogger(PolarisConfigFileLocator.class);
private static final Logger LOGGER = LoggerFactory.getLogger(PolarisConfigFileLocator.class);
private static final String POLARIS_CONFIG_PROPERTY_SOURCE_NAME = "polaris-config";
@ -63,8 +62,7 @@ public class PolarisConfigFileLocator implements PropertySourceLocator {
private final PolarisPropertySourceManager polarisPropertySourceManager;
public PolarisConfigFileLocator(PolarisConfigProperties polarisConfigProperties,
PolarisContextProperties polarisContextProperties,
ConfigFileService configFileService,
PolarisContextProperties polarisContextProperties, ConfigFileService configFileService,
PolarisPropertySourceManager polarisPropertySourceManager) {
this.polarisConfigProperties = polarisConfigProperties;
this.polarisContextProperties = polarisContextProperties;
@ -95,8 +93,7 @@ public class PolarisConfigFileLocator implements PropertySourceLocator {
String group = configFileGroup.getName();
if (StringUtils.isEmpty(group)) {
throw new IllegalArgumentException(
"polaris config group name cannot be empty.");
throw new IllegalArgumentException("polaris config group name cannot be empty.");
}
List<String> files = configFileGroup.getFiles();
@ -105,8 +102,7 @@ public class PolarisConfigFileLocator implements PropertySourceLocator {
}
for (String fileName : files) {
PolarisPropertySource polarisPropertySource = loadPolarisPropertySource(
namespace, group, fileName);
PolarisPropertySource polarisPropertySource = loadPolarisPropertySource(namespace, group, fileName);
compositePropertySource.addPropertySource(polarisPropertySource);
@ -119,27 +115,21 @@ public class PolarisConfigFileLocator implements PropertySourceLocator {
}
}
private PolarisPropertySource loadPolarisPropertySource(String namespace,
String group, String fileName) {
private PolarisPropertySource loadPolarisPropertySource(String namespace, String group, String fileName) {
ConfigKVFile configKVFile;
// unknown extension is resolved as properties file
if (ConfigFileFormat.isPropertyFile(fileName)
|| ConfigFileFormat.isUnknownFile(fileName)) {
configKVFile = configFileService.getConfigPropertiesFile(namespace, group,
fileName);
if (ConfigFileFormat.isPropertyFile(fileName) || ConfigFileFormat.isUnknownFile(fileName)) {
configKVFile = configFileService.getConfigPropertiesFile(namespace, group, fileName);
}
else if (ConfigFileFormat.isYamlFile(fileName)) {
configKVFile = configFileService.getConfigYamlFile(namespace, group,
fileName);
configKVFile = configFileService.getConfigYamlFile(namespace, group, fileName);
}
else {
LOGGER.warn(
"[SCT Config] Unsupported config file. namespace = {}, group = {}, fileName = {}",
namespace, group, fileName);
LOGGER.warn("[SCT Config] 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");
throw new IllegalStateException("Only configuration files in the format of properties / yaml / yaml"
+ " can be injected into the spring context");
}
Map<String, Object> map = new ConcurrentHashMap<>();

@ -39,8 +39,8 @@ public class PolarisPropertySource extends MapPropertySource {
private final ConfigKVFile configKVFile;
public PolarisPropertySource(String namespace, String group, String fileName,
ConfigKVFile configKVFile, Map<String, Object> source) {
public PolarisPropertySource(String namespace, String group, String fileName, ConfigKVFile configKVFile,
Map<String, Object> source) {
super(namespace + "-" + group + "-" + fileName, source);
this.namespace = namespace;
@ -71,8 +71,8 @@ public class PolarisPropertySource extends MapPropertySource {
@Override
public String toString() {
return "PolarisPropertySource{" + "namespace='" + namespace + '\'' + ", group='"
+ group + '\'' + ", fileName='" + fileName + '\'' + '}';
return "PolarisPropertySource{" + "namespace='" + namespace + '\'' + ", group='" + group + '\'' + ", fileName='"
+ fileName + '\'' + '}';
}
}

@ -46,8 +46,7 @@ import org.springframework.util.CollectionUtils;
public class PolarisPropertySourceAutoRefresher
implements ApplicationListener<ApplicationReadyEvent>, ApplicationContextAware {
private static final Logger LOGGER = LoggerFactory
.getLogger(PolarisPropertySourceAutoRefresher.class);
private static final Logger LOGGER = LoggerFactory.getLogger(PolarisPropertySourceAutoRefresher.class);
private final PolarisConfigProperties polarisConfigProperties;
@ -59,18 +58,15 @@ public class PolarisPropertySourceAutoRefresher
private final AtomicBoolean registered = new AtomicBoolean(false);
public PolarisPropertySourceAutoRefresher(
PolarisConfigProperties polarisConfigProperties,
PolarisPropertySourceManager polarisPropertySourceManager,
ContextRefresher contextRefresher) {
public PolarisPropertySourceAutoRefresher(PolarisConfigProperties polarisConfigProperties,
PolarisPropertySourceManager polarisPropertySourceManager, ContextRefresher contextRefresher) {
this.polarisConfigProperties = polarisConfigProperties;
this.polarisPropertySourceManager = polarisPropertySourceManager;
this.contextRefresher = contextRefresher;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@ -84,8 +80,7 @@ public class PolarisPropertySourceAutoRefresher
return;
}
List<PolarisPropertySource> polarisPropertySources = polarisPropertySourceManager
.getAllPropertySources();
List<PolarisPropertySource> polarisPropertySources = polarisPropertySourceManager.getAllPropertySources();
if (CollectionUtils.isEmpty(polarisPropertySources)) {
return;
}
@ -96,45 +91,38 @@ public class PolarisPropertySourceAutoRefresher
// register polaris config publish event
for (PolarisPropertySource polarisPropertySource : polarisPropertySources) {
polarisPropertySource.getConfigKVFile()
.addChangeListener(new ConfigKVFileChangeListener() {
@Override
public void onChange(
ConfigKVFileChangeEvent configKVFileChangeEvent) {
LOGGER.info(
"[SCT Config] received polaris config change event and will refresh spring context."
+ "namespace = {}, group = {}, fileName = {}",
polarisPropertySource.getNamespace(),
polarisPropertySource.getGroup(),
polarisPropertySource.getFileName());
Map<String, Object> source = polarisPropertySource
.getSource();
for (String changedKey : configKVFileChangeEvent
.changedKeys()) {
ConfigPropertyChangeInfo configPropertyChangeInfo = configKVFileChangeEvent
.getChangeInfo(changedKey);
LOGGER.info("[SCT Config] changed property = {}",
configPropertyChangeInfo);
switch (configPropertyChangeInfo.getChangeType()) {
case MODIFIED:
case ADDED:
source.put(changedKey,
configPropertyChangeInfo.getNewValue());
break;
case DELETED:
source.remove(changedKey);
break;
}
}
// rebuild beans with @RefreshScope annotation
contextRefresher.refresh();
polarisPropertySource.getConfigKVFile().addChangeListener(new ConfigKVFileChangeListener() {
@Override
public void onChange(ConfigKVFileChangeEvent configKVFileChangeEvent) {
LOGGER.info(
"[SCT Config] received polaris config change event and will refresh spring context."
+ "namespace = {}, group = {}, fileName = {}",
polarisPropertySource.getNamespace(), polarisPropertySource.getGroup(),
polarisPropertySource.getFileName());
Map<String, Object> source = polarisPropertySource.getSource();
for (String changedKey : configKVFileChangeEvent.changedKeys()) {
ConfigPropertyChangeInfo configPropertyChangeInfo = configKVFileChangeEvent
.getChangeInfo(changedKey);
LOGGER.info("[SCT Config] changed property = {}", configPropertyChangeInfo);
switch (configPropertyChangeInfo.getChangeType()) {
case MODIFIED:
case ADDED:
source.put(changedKey, configPropertyChangeInfo.getNewValue());
break;
case DELETED:
source.remove(changedKey);
break;
}
});
}
// rebuild beans with @RefreshScope annotation
contextRefresher.refresh();
}
});
}
}

@ -33,8 +33,7 @@ public class PolarisPropertySourceManager {
private final Map<String, PolarisPropertySource> polarisPropertySources = new ConcurrentHashMap<>();
public void addPropertySource(PolarisPropertySource polarisPropertySource) {
polarisPropertySources.putIfAbsent(polarisPropertySource.getPropertySourceName(),
polarisPropertySource);
polarisPropertySources.putIfAbsent(polarisPropertySource.getPropertySourceName(), polarisPropertySource);
}
public List<PolarisPropertySource> getAllPropertySources() {

@ -15,70 +15,71 @@
<dependencies>
<!-- Spring Cloud Tencent dependencies start -->
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-polaris-context</artifactId>
</dependency>
<!-- Spring Cloud Tencent dependencies end -->
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-polaris-context</artifactId>
</dependency>
<!-- Spring Cloud Tencent dependencies end -->
<!-- Polaris dependencies start -->
<dependency>
<groupId>com.tencent.polaris</groupId>
<artifactId>polaris-discovery-factory</artifactId>
</dependency>
<!-- Polaris dependencies start -->
<dependency>
<groupId>com.tencent.polaris</groupId>
<artifactId>polaris-discovery-factory</artifactId>
</dependency>
<dependency>
<groupId>com.tencent.polaris</groupId>
<artifactId>polaris-test-common</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.tencent.polaris</groupId>
<artifactId>polaris-test-common</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.tencent.polaris</groupId>
<artifactId>polaris-test-mock-discovery</artifactId>
<scope>test</scope>
</dependency>
<!-- Polaris dependencies end -->
<dependency>
<groupId>com.tencent.polaris</groupId>
<artifactId>polaris-test-mock-discovery</artifactId>
<scope>test</scope>
</dependency>
<!-- Polaris dependencies end -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

@ -102,16 +102,13 @@ public class PolarisDiscoveryProperties {
@PostConstruct
public void init() {
if (StringUtils.isEmpty(this.getNamespace())) {
this.setNamespace(environment
.resolvePlaceholders("${spring.cloud.polaris.discovery.namespace:}"));
this.setNamespace(environment.resolvePlaceholders("${spring.cloud.polaris.discovery.namespace:}"));
}
if (StringUtils.isEmpty(this.getService())) {
this.setService(environment
.resolvePlaceholders("${spring.cloud.polaris.discovery.service:}"));
this.setService(environment.resolvePlaceholders("${spring.cloud.polaris.discovery.service:}"));
}
if (StringUtils.isEmpty(this.getToken())) {
this.setToken(environment
.resolvePlaceholders("${spring.cloud.polaris.discovery.token:}"));
this.setToken(environment.resolvePlaceholders("${spring.cloud.polaris.discovery.token:}"));
}
}
@ -200,12 +197,10 @@ public class PolarisDiscoveryProperties {
@Override
public String toString() {
return "PolarisProperties{" + "token='" + token + '\'' + ", namespace='"
+ namespace + '\'' + ", service='" + service + '\'' + ", weight=" + weight
+ ", version='" + version + '\'' + ", protocol='" + protocol + '\''
+ ", port=" + port + '\'' + ", registerEnabled=" + registerEnabled
+ ", heartbeatEnabled=" + heartbeatEnabled + ", healthCheckUrl="
+ healthCheckUrl + ", environment=" + environment + '}';
return "PolarisProperties{" + "token='" + token + '\'' + ", namespace='" + namespace + '\'' + ", service='"
+ service + '\'' + ", weight=" + weight + ", version='" + version + '\'' + ", protocol='" + protocol
+ '\'' + ", port=" + port + '\'' + ", registerEnabled=" + registerEnabled + ", heartbeatEnabled="
+ heartbeatEnabled + ", healthCheckUrl=" + healthCheckUrl + ", environment=" + environment + '}';
}
}

@ -31,8 +31,7 @@ import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@ConditionalOnDiscoveryEnabled
@ConditionalOnProperty(value = "spring.cloud.polaris.discovery.enabled",
matchIfMissing = true)
@ConditionalOnProperty(value = "spring.cloud.polaris.discovery.enabled", matchIfMissing = true)
public @interface ConditionalOnPolarisDiscoveryEnabled {
}

@ -39,8 +39,7 @@ import org.springframework.context.annotation.Import;
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnPolarisDiscoveryEnabled
@Import({ PolarisDiscoveryClientConfiguration.class,
PolarisReactiveDiscoveryClientConfiguration.class,
@Import({ PolarisDiscoveryClientConfiguration.class, PolarisReactiveDiscoveryClientConfiguration.class,
ConsulContextProperties.class })
public class PolarisDiscoveryAutoConfiguration {
@ -52,15 +51,13 @@ public class PolarisDiscoveryAutoConfiguration {
@Bean(name = "polarisProvider")
@ConditionalOnMissingBean
public ProviderAPI polarisProvider(SDKContext polarisContext)
throws PolarisException {
public ProviderAPI polarisProvider(SDKContext polarisContext) throws PolarisException {
return DiscoveryAPIFactory.createProviderAPIByContext(polarisContext);
}
@Bean(name = "polarisConsumer")
@ConditionalOnMissingBean
public ConsumerAPI polarisConsumer(SDKContext polarisContext)
throws PolarisException {
public ConsumerAPI polarisConsumer(SDKContext polarisContext) throws PolarisException {
return DiscoveryAPIFactory.createConsumerAPIByContext(polarisContext);
}
@ -72,8 +69,7 @@ public class PolarisDiscoveryAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public PolarisServiceDiscovery polarisServiceDiscovery(
PolarisDiscoveryHandler polarisDiscoveryHandler) {
public PolarisServiceDiscovery polarisServiceDiscovery(PolarisDiscoveryHandler polarisDiscoveryHandler) {
return new PolarisServiceDiscovery(polarisDiscoveryHandler);
}

@ -33,14 +33,12 @@ import org.springframework.context.annotation.Configuration;
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnBlockingDiscoveryEnabled
@AutoConfigureBefore({ SimpleDiscoveryClientAutoConfiguration.class,
CommonsClientAutoConfiguration.class })
@AutoConfigureBefore({ SimpleDiscoveryClientAutoConfiguration.class, CommonsClientAutoConfiguration.class })
@AutoConfigureAfter(PolarisDiscoveryAutoConfiguration.class)
public class PolarisDiscoveryClientConfiguration {
@Bean
public DiscoveryClient polarisDiscoveryClient(
PolarisServiceDiscovery polarisServiceDiscovery) {
public DiscoveryClient polarisDiscoveryClient(PolarisServiceDiscovery polarisServiceDiscovery) {
return new PolarisDiscoveryClient(polarisServiceDiscovery);
}

@ -64,13 +64,11 @@ public class PolarisDiscoveryHandler {
GetInstancesRequest getInstancesRequest = new GetInstancesRequest();
getInstancesRequest.setNamespace(namespace);
getInstancesRequest.setService(service);
String method = MetadataContextHolder.get()
.getSystemMetadata(SystemMetadataKey.PEER_PATH);
String method = MetadataContextHolder.get().getSystemMetadata(SystemMetadataKey.PEER_PATH);
getInstancesRequest.setMethod(method);
String localNamespace = MetadataContext.LOCAL_NAMESPACE;
String localService = MetadataContext.LOCAL_SERVICE;
Map<String, String> allTransitiveCustomMetadata = MetadataContextHolder.get()
.getAllTransitiveCustomMetadata();
Map<String, String> allTransitiveCustomMetadata = MetadataContextHolder.get().getAllTransitiveCustomMetadata();
if (StringUtils.isNotBlank(localNamespace) || StringUtils.isNotBlank(localService)
|| null != allTransitiveCustomMetadata) {
ServiceInfo sourceService = new ServiceInfo();

@ -49,8 +49,7 @@ public class PolarisServiceDiscovery {
*/
public List<ServiceInstance> getInstances(String serviceId) throws PolarisException {
List<ServiceInstance> instances = new ArrayList<>();
InstancesResponse filteredInstances = polarisDiscoveryHandler
.getFilteredInstances(serviceId);
InstancesResponse filteredInstances = polarisDiscoveryHandler.getFilteredInstances(serviceId);
ServiceInstances serviceInstances = filteredInstances.toServiceInstances();
for (Instance instance : serviceInstances.getInstances()) {
instances.add(new PolarisServiceInstance(instance));
@ -64,8 +63,8 @@ public class PolarisServiceDiscovery {
* @throws PolarisException polarisException
*/
public List<String> getServices() throws PolarisException {
return polarisDiscoveryHandler.GetServices().getServices().stream()
.map(ServiceInfo::getService).collect(Collectors.toList());
return polarisDiscoveryHandler.GetServices().getServices().stream().map(ServiceInfo::getService)
.collect(Collectors.toList());
}
}

@ -38,13 +38,11 @@ import org.springframework.cloud.client.discovery.ReactiveDiscoveryClient;
*/
public class PolarisReactiveDiscoveryClient implements ReactiveDiscoveryClient {
private static final Logger log = LoggerFactory
.getLogger(PolarisReactiveDiscoveryClient.class);
private static final Logger log = LoggerFactory.getLogger(PolarisReactiveDiscoveryClient.class);
private PolarisServiceDiscovery polarisServiceDiscovery;
public PolarisReactiveDiscoveryClient(
PolarisServiceDiscovery polarisServiceDiscovery) {
public PolarisReactiveDiscoveryClient(PolarisServiceDiscovery polarisServiceDiscovery) {
this.polarisServiceDiscovery = polarisServiceDiscovery;
}

@ -100,37 +100,29 @@ public class ConsulContextProperties {
@Override
public void modify(ConfigurationImpl configuration) {
if (consulContextProperties != null && consulContextProperties.enabled
&& consulContextProperties.discoveryEnabled
&& consulContextProperties.register) {
if (CollectionUtils
.isEmpty(configuration.getGlobal().getServerConnectors())) {
&& consulContextProperties.discoveryEnabled && consulContextProperties.register) {
if (CollectionUtils.isEmpty(configuration.getGlobal().getServerConnectors())) {
configuration.getGlobal().setServerConnectors(new ArrayList<>());
}
configuration.getGlobal().getServerConnectors()
.add(configuration.getGlobal().getServerConnector());
configuration.getGlobal().getServerConnectors().add(configuration.getGlobal().getServerConnector());
ServerConnectorConfigImpl serverConnectorConfig = new ServerConnectorConfigImpl();
serverConnectorConfig.setAddresses(
Collections.singletonList(consulContextProperties.host + ":"
+ consulContextProperties.port));
Collections.singletonList(consulContextProperties.host + ":" + consulContextProperties.port));
serverConnectorConfig.setProtocol(DefaultPlugins.SERVER_CONNECTOR_CONSUL);
Map<String, String> metadata = serverConnectorConfig.getMetadata();
if (StringUtils.isNotBlank(consulContextProperties.serviceName)) {
metadata.put(MetadataMapKey.SERVICE_NAME_KEY,
consulContextProperties.serviceName);
metadata.put(MetadataMapKey.SERVICE_NAME_KEY, consulContextProperties.serviceName);
}
if (StringUtils.isNotBlank(consulContextProperties.instanceId)) {
metadata.put(MetadataMapKey.INSTANCE_ID_KEY,
consulContextProperties.instanceId);
metadata.put(MetadataMapKey.INSTANCE_ID_KEY, consulContextProperties.instanceId);
}
if (consulContextProperties.preferIpAddress
&& StringUtils.isNotBlank(consulContextProperties.ipAddress)) {
metadata.put(MetadataMapKey.PREFER_IP_ADDRESS_KEY,
String.valueOf(consulContextProperties.preferIpAddress));
metadata.put(MetadataMapKey.IP_ADDRESS_KEY,
consulContextProperties.ipAddress);
metadata.put(MetadataMapKey.IP_ADDRESS_KEY, consulContextProperties.ipAddress);
}
configuration.getGlobal().getServerConnectors()
.add(serverConnectorConfig);
configuration.getGlobal().getServerConnectors().add(serverConnectorConfig);
}
}

@ -31,17 +31,14 @@ import org.springframework.util.StringUtils;
*
* @author Haotian Zhang, Andrew Shan, Jie Cheng
*/
public class PolarisAutoServiceRegistration
extends AbstractAutoServiceRegistration<Registration> {
public class PolarisAutoServiceRegistration extends AbstractAutoServiceRegistration<Registration> {
private static final Logger log = LoggerFactory
.getLogger(PolarisAutoServiceRegistration.class);
private static final Logger log = LoggerFactory.getLogger(PolarisAutoServiceRegistration.class);
private final PolarisRegistration registration;
public PolarisAutoServiceRegistration(ServiceRegistry<Registration> serviceRegistry,
AutoServiceRegistrationProperties autoServiceRegistrationProperties,
PolarisRegistration registration) {
AutoServiceRegistrationProperties autoServiceRegistrationProperties, PolarisRegistration registration) {
super(serviceRegistry, autoServiceRegistrationProperties);
this.registration = registration;
}

@ -41,8 +41,7 @@ public class PolarisRegistration implements Registration, ServiceInstance {
private final SDKContext polarisContext;
public PolarisRegistration(PolarisDiscoveryProperties polarisDiscoveryProperties,
SDKContext context) {
public PolarisRegistration(PolarisDiscoveryProperties polarisDiscoveryProperties, SDKContext context) {
this.polarisDiscoveryProperties = polarisDiscoveryProperties;
this.polarisContext = context;
}
@ -68,8 +67,7 @@ public class PolarisRegistration implements Registration, ServiceInstance {
@Override
public boolean isSecure() {
return StringUtils.equalsIgnoreCase(polarisDiscoveryProperties.getProtocol(),
"https");
return StringUtils.equalsIgnoreCase(polarisDiscoveryProperties.getProtocol(), "https");
}
@Override
@ -88,8 +86,8 @@ public class PolarisRegistration implements Registration, ServiceInstance {
@Override
public String toString() {
return "PolarisRegistration{" + "polarisDiscoveryProperties="
+ polarisDiscoveryProperties + ", polarisContext=" + polarisContext + '}';
return "PolarisRegistration{" + "polarisDiscoveryProperties=" + polarisDiscoveryProperties + ", polarisContext="
+ polarisContext + '}';
}
}

@ -34,14 +34,13 @@ import com.tencent.polaris.api.rpc.InstanceHeartbeatRequest;
import com.tencent.polaris.api.rpc.InstanceRegisterRequest;
import com.tencent.polaris.api.rpc.InstancesResponse;
import com.tencent.polaris.client.util.NamedThreadFactory;
import org.apache.logging.log4j.util.Strings;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
import org.springframework.util.StringUtils;
import static org.springframework.util.ReflectionUtils.rethrowRuntimeException;
@ -52,8 +51,7 @@ import static org.springframework.util.ReflectionUtils.rethrowRuntimeException;
*/
public class PolarisServiceRegistry implements ServiceRegistry<Registration> {
private static final Logger log = LoggerFactory
.getLogger(PolarisServiceRegistry.class);
private static final Logger log = LoggerFactory.getLogger(PolarisServiceRegistry.class);
private static final int ttl = 5;
@ -66,14 +64,13 @@ public class PolarisServiceRegistry implements ServiceRegistry<Registration> {
private final ScheduledExecutorService heartbeatExecutor;
public PolarisServiceRegistry(PolarisDiscoveryProperties polarisDiscoveryProperties,
PolarisDiscoveryHandler polarisDiscoveryHandler,
MetadataLocalProperties metadataLocalProperties) {
PolarisDiscoveryHandler polarisDiscoveryHandler, MetadataLocalProperties metadataLocalProperties) {
this.polarisDiscoveryProperties = polarisDiscoveryProperties;
this.polarisDiscoveryHandler = polarisDiscoveryHandler;
this.metadataLocalProperties = metadataLocalProperties;
if (polarisDiscoveryProperties.isHeartbeatEnabled()) {
ScheduledThreadPoolExecutor heartbeatExecutor = new ScheduledThreadPoolExecutor(
0, new NamedThreadFactory("spring-cloud-heartbeat"));
ScheduledThreadPoolExecutor heartbeatExecutor = new ScheduledThreadPoolExecutor(0,
new NamedThreadFactory("spring-cloud-heartbeat"));
heartbeatExecutor.setMaximumPoolSize(1);
this.heartbeatExecutor = heartbeatExecutor;
}
@ -85,7 +82,7 @@ public class PolarisServiceRegistry implements ServiceRegistry<Registration> {
@Override
public void register(Registration registration) {
if (StringUtils.isEmpty(registration.getServiceId())) {
if (StringUtils.isBlank(registration.getServiceId())) {
log.warn("No service to register for polaris client...");
return;
}
@ -105,10 +102,9 @@ public class PolarisServiceRegistry implements ServiceRegistry<Registration> {
try {
ProviderAPI providerClient = polarisDiscoveryHandler.getProviderAPI();
providerClient.register(instanceRegisterRequest);
log.info("polaris registry, {} {} {}:{} {} register finished",
polarisDiscoveryProperties.getNamespace(),
registration.getServiceId(), registration.getHost(),
registration.getPort(), metadataLocalProperties.getContent());
log.info("polaris registry, {} {} {}:{} {} register finished", polarisDiscoveryProperties.getNamespace(),
registration.getServiceId(), registration.getHost(), registration.getPort(),
metadataLocalProperties.getContent());
if (null != heartbeatExecutor) {
InstanceHeartbeatRequest heartbeatRequest = new InstanceHeartbeatRequest();
@ -118,8 +114,7 @@ public class PolarisServiceRegistry implements ServiceRegistry<Registration> {
}
}
catch (Exception e) {
log.error("polaris registry, {} register failed...{},",
registration.getServiceId(), registration, e);
log.error("polaris registry, {} register failed...{},", registration.getServiceId(), registration, e);
rethrowRuntimeException(e);
}
}
@ -146,8 +141,7 @@ public class PolarisServiceRegistry implements ServiceRegistry<Registration> {
providerClient.deRegister(deRegisterRequest);
}
catch (Exception e) {
log.error("ERR_POLARIS_DEREGISTER, de-register failed...{},", registration,
e);
log.error("ERR_POLARIS_DEREGISTER, de-register failed...{},", registration, e);
}
finally {
if (null != heartbeatExecutor) {
@ -170,8 +164,7 @@ public class PolarisServiceRegistry implements ServiceRegistry<Registration> {
@Override
public Object getStatus(Registration registration) {
String serviceName = registration.getServiceId();
InstancesResponse instancesResponse = polarisDiscoveryHandler
.getInstances(serviceName);
InstancesResponse instancesResponse = polarisDiscoveryHandler.getInstances(serviceName);
Instance[] instances = instancesResponse.getInstances();
if (null == instances || instances.length == 0) {
return null;
@ -192,25 +185,22 @@ public class PolarisServiceRegistry implements ServiceRegistry<Registration> {
public void heartbeat(InstanceHeartbeatRequest heartbeatRequest) {
heartbeatExecutor.scheduleWithFixedDelay(() -> {
try {
String healthCheckEndpoint = polarisDiscoveryProperties
.getHealthCheckUrl();
String healthCheckEndpoint = polarisDiscoveryProperties.getHealthCheckUrl();
// First determine whether health-check-url is configured.
// If configured, the service instance health check needs to be executed
// first.
// If the health check passes, the heartbeat will be reported.
// If it does not pass, the heartbeat will not be reported.
if (Strings.isNotEmpty(healthCheckEndpoint)) {
if (StringUtils.isNotBlank(healthCheckEndpoint)) {
if (!healthCheckEndpoint.startsWith("/")) {
healthCheckEndpoint = "/" + healthCheckEndpoint;
}
String healthCheckUrl = String.format("http://%s:%s%s",
heartbeatRequest.getHost(), heartbeatRequest.getPort(),
healthCheckEndpoint);
String healthCheckUrl = String.format("http://%s:%s%s", heartbeatRequest.getHost(),
heartbeatRequest.getPort(), healthCheckEndpoint);
if (!OkHttpUtil.get(healthCheckUrl, null)) {
log.error(
"backend service health check failed. health check endpoint = {}",
log.error("backend service health check failed. health check endpoint = {}",
healthCheckEndpoint);
return;
}

@ -43,37 +43,29 @@ import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties
@ConditionalOnPolarisDiscoveryEnabled
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled",
matchIfMissing = true)
@AutoConfigureAfter({ AutoServiceRegistrationConfiguration.class,
AutoServiceRegistrationAutoConfiguration.class,
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
@AutoConfigureAfter({ AutoServiceRegistrationConfiguration.class, AutoServiceRegistrationAutoConfiguration.class,
PolarisDiscoveryAutoConfiguration.class })
public class PolarisServiceRegistryAutoConfiguration {
@Bean
public PolarisServiceRegistry polarisServiceRegistry(
PolarisDiscoveryProperties polarisDiscoveryProperties,
PolarisDiscoveryHandler polarisDiscoveryHandler,
MetadataLocalProperties metadataLocalProperties) {
return new PolarisServiceRegistry(polarisDiscoveryProperties,
polarisDiscoveryHandler, metadataLocalProperties);
public PolarisServiceRegistry polarisServiceRegistry(PolarisDiscoveryProperties polarisDiscoveryProperties,
PolarisDiscoveryHandler polarisDiscoveryHandler, MetadataLocalProperties metadataLocalProperties) {
return new PolarisServiceRegistry(polarisDiscoveryProperties, polarisDiscoveryHandler, metadataLocalProperties);
}
@Bean
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
public PolarisRegistration polarisRegistration(
PolarisDiscoveryProperties polarisDiscoveryProperties, SDKContext context) {
public PolarisRegistration polarisRegistration(PolarisDiscoveryProperties polarisDiscoveryProperties,
SDKContext context) {
return new PolarisRegistration(polarisDiscoveryProperties, context);
}
@Bean
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
public PolarisAutoServiceRegistration polarisAutoServiceRegistration(
PolarisServiceRegistry registry,
AutoServiceRegistrationProperties autoServiceRegistrationProperties,
PolarisRegistration registration) {
return new PolarisAutoServiceRegistration(registry,
autoServiceRegistrationProperties, registration);
public PolarisAutoServiceRegistration polarisAutoServiceRegistration(PolarisServiceRegistry registry,
AutoServiceRegistrationProperties autoServiceRegistrationProperties, PolarisRegistration registration) {
return new PolarisAutoServiceRegistration(registry, autoServiceRegistrationProperties, registration);
}
}

@ -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.ribbon;
import com.tencent.cloud.polaris.discovery.ConditionalOnPolarisDiscoveryEnabled;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration;
import org.springframework.cloud.netflix.ribbon.RibbonClients;
import org.springframework.context.annotation.Configuration;
/**
* Autoconfiguration of ribbon of Polaris.
*
* @author Haotian Zhang, Andrew Shan, Jie Cheng
*/
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties
@ConditionalOnPolarisDiscoveryEnabled
@AutoConfigureAfter(RibbonAutoConfiguration.class)
@RibbonClients(defaultConfiguration = PolarisRibbonServerListConfiguration.class)
public class PolarisDiscoveryRibbonAutoConfiguration {
}

@ -1,47 +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.ribbon;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerList;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryHandler;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Configuration of server list.
*
* @author Haotian Zhang, Andrew Shan, Jie Cheng
*/
@Configuration
public class PolarisRibbonServerListConfiguration {
@Bean
@ConditionalOnMissingBean
public ServerList<Server> ribbonServerList(
PolarisDiscoveryHandler polarisDiscoveryHandler,
IClientConfig iClientConfig) {
PolarisServerList serverList = new PolarisServerList(polarisDiscoveryHandler);
serverList.initWithNiwsConfig(iClientConfig);
return serverList;
}
}

@ -1,77 +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.ribbon;
import java.util.ArrayList;
import java.util.List;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractServerList;
import com.netflix.loadbalancer.Server;
import com.tencent.cloud.common.pojo.PolarisServer;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryHandler;
import com.tencent.polaris.api.pojo.Instance;
import com.tencent.polaris.api.pojo.ServiceInstances;
import com.tencent.polaris.api.rpc.InstancesResponse;
/**
* Server list of Polaris.
*
* @author Haotian Zhang, Andrew Shan, Jie Cheng
*/
public class PolarisServerList extends AbstractServerList<Server> {
private String serviceId;
private PolarisDiscoveryHandler polarisDiscoveryHandler;
public PolarisServerList(PolarisDiscoveryHandler polarisDiscoveryHandler) {
this.polarisDiscoveryHandler = polarisDiscoveryHandler;
}
@Override
public List<Server> getInitialListOfServers() {
return getServers();
}
@Override
public List<Server> getUpdatedListOfServers() {
return getServers();
}
private List<Server> getServers() {
InstancesResponse filteredInstances = polarisDiscoveryHandler
.getFilteredInstances(serviceId);
ServiceInstances serviceInstances = filteredInstances.toServiceInstances();
List<Server> polarisServers = new ArrayList<>();
for (Instance instance : serviceInstances.getInstances()) {
polarisServers.add(new PolarisServer(serviceInstances, instance));
}
return polarisServers;
}
public String getServiceId() {
return serviceId;
}
@Override
public void initWithNiwsConfig(IClientConfig iClientConfig) {
this.serviceId = iClientConfig.getClientName();
}
}

@ -20,7 +20,6 @@ package com.tencent.cloud.polaris.util;
import java.util.Map;
import java.util.Objects;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
@ -39,12 +38,6 @@ public final class OkHttpUtil {
*/
public final static Logger logger = LoggerFactory.getLogger(OkHttpUtil.class);
/**
* JSON format.
*/
public static final MediaType MEDIA_TYPE_JSON = MediaType
.parse("application/json; charset=utf-8");
/**
* client.
*/
@ -69,8 +62,7 @@ public final class OkHttpUtil {
if (response.isSuccessful() && Objects.nonNull(response.body())) {
String result = response.body().string();
logger.debug("exec get request, url: {} successresponse data: {}", url,
result);
logger.debug("exec get request, url: {} successresponse data: {}", url, result);
return true;
}
}
@ -85,8 +77,7 @@ public final class OkHttpUtil {
* @param builder builder
* @param headers headers
*/
private static void buildHeader(Request.Builder builder,
Map<String, String> headers) {
private static void buildHeader(Request.Builder builder, Map<String, String> headers) {
if (Objects.nonNull(headers) && headers.size() > 0) {
headers.forEach((k, v) -> {
if (Objects.nonNull(k) && Objects.nonNull(v)) {

@ -1,4 +1,3 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.tencent.cloud.polaris.discovery.PolarisDiscoveryAutoConfiguration,\
com.tencent.cloud.polaris.ribbon.PolarisDiscoveryRibbonAutoConfiguration,\
com.tencent.cloud.polaris.registry.PolarisServiceRegistryAutoConfiguration

@ -47,12 +47,10 @@ public class PolarisDiscoveryAutoConfigurationTest {
private static NamingServer namingServer;
private WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(PolarisContextConfiguration.class,
PolarisDiscoveryAutoConfiguration.class,
PolarisDiscoveryClientConfiguration.class,
PolarisContextConfiguration.class))
.withPropertyValues("spring.application.name=" + SERVICE_PROVIDER)
.withPropertyValues("server.port=" + PORT)
.withConfiguration(
AutoConfigurations.of(PolarisContextConfiguration.class, PolarisDiscoveryAutoConfiguration.class,
PolarisDiscoveryClientConfiguration.class, PolarisContextConfiguration.class))
.withPropertyValues("spring.application.name=" + SERVICE_PROVIDER).withPropertyValues("server.port=" + PORT)
.withPropertyValues("spring.cloud.polaris.address=grpc://127.0.0.1:10081");
@BeforeClass

@ -44,10 +44,8 @@ public class PolarisDiscoveryClientConfigurationTest {
private WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(PolarisContextConfiguration.class,
PolarisDiscoveryClientConfiguration.class,
PolarisContextConfiguration.class))
.withPropertyValues("spring.application.name=" + SERVICE_PROVIDER)
.withPropertyValues("server.port=" + PORT)
PolarisDiscoveryClientConfiguration.class, PolarisContextConfiguration.class))
.withPropertyValues("spring.application.name=" + SERVICE_PROVIDER).withPropertyValues("server.port=" + PORT)
.withPropertyValues("spring.cloud.polaris.address=grpc://127.0.0.1:10081");
@BeforeClass
@ -64,16 +62,13 @@ public class PolarisDiscoveryClientConfigurationTest {
@Test
public void testDefaultInitialization() {
this.contextRunner.run(context -> assertThat(context)
.hasSingleBean(PolarisDiscoveryClient.class));
this.contextRunner.run(context -> assertThat(context).hasSingleBean(PolarisDiscoveryClient.class));
}
@Test
public void testDiscoveryBlockingDisabled() {
this.contextRunner
.withPropertyValues("spring.cloud.discovery.blocking.enabled=false")
.run(context -> assertThat(context)
.doesNotHaveBean(PolarisDiscoveryClient.class));
this.contextRunner.withPropertyValues("spring.cloud.discovery.blocking.enabled=false")
.run(context -> assertThat(context).doesNotHaveBean(PolarisDiscoveryClient.class));
}
@Configuration

@ -65,8 +65,7 @@ public class PolarisDiscoveryClientTest {
@Test
public void testGetServices() {
when(polarisServiceDiscovery.getServices())
.thenReturn(singletonList(SERVICE_PROVIDER));
when(polarisServiceDiscovery.getServices()).thenReturn(singletonList(SERVICE_PROVIDER));
List<String> services = client.getServices();

@ -52,14 +52,11 @@ public class PolarisServiceDiscoveryTest {
private WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(PolarisContextConfiguration.class,
PolarisServiceDiscoveryTest.PolarisPropertiesConfiguration.class,
PolarisDiscoveryClientConfiguration.class,
PolarisDiscoveryAutoConfiguration.class,
PolarisDiscoveryClientConfiguration.class, PolarisDiscoveryAutoConfiguration.class,
PolarisContextConfiguration.class))
.withPropertyValues("spring.application.name=" + SERVICE_PROVIDER)
.withPropertyValues("server.port=" + PORT)
.withPropertyValues("spring.application.name=" + SERVICE_PROVIDER).withPropertyValues("server.port=" + PORT)
.withPropertyValues("spring.cloud.polaris.address=grpc://127.0.0.1:10081")
.withPropertyValues(
"spring.cloud.polaris.discovery.namespace=" + NAMESPACE_TEST)
.withPropertyValues("spring.cloud.polaris.discovery.namespace=" + NAMESPACE_TEST)
.withPropertyValues("spring.cloud.polaris.discovery.token=xxxxxx");
@BeforeClass
@ -72,8 +69,7 @@ public class PolarisServiceDiscoveryTest {
instanceParameter.setIsolated(false);
instanceParameter.setWeight(100);
ServiceKey serviceKey = new ServiceKey(NAMESPACE_TEST, SERVICE_PROVIDER);
namingServer.getNamingService().batchAddInstances(serviceKey, PORT, 3,
instanceParameter);
namingServer.getNamingService().batchAddInstances(serviceKey, PORT, 3, instanceParameter);
}
@AfterClass
@ -86,10 +82,8 @@ public class PolarisServiceDiscoveryTest {
@Test
public void testGetInstances() {
this.contextRunner.run(context -> {
PolarisServiceDiscovery polarisServiceDiscovery = context
.getBean(PolarisServiceDiscovery.class);
List<ServiceInstance> serviceInstances = polarisServiceDiscovery
.getInstances(SERVICE_PROVIDER);
PolarisServiceDiscovery polarisServiceDiscovery = context.getBean(PolarisServiceDiscovery.class);
List<ServiceInstance> serviceInstances = polarisServiceDiscovery.getInstances(SERVICE_PROVIDER);
assertThat(serviceInstances.isEmpty()).isFalse();
assertThat(serviceInstances).hasSize(3);
assertThat(serviceInstances.get(0).getPort()).isEqualTo(PORT);
@ -101,8 +95,7 @@ public class PolarisServiceDiscoveryTest {
@Test
public void testGetServices() throws PolarisException {
this.contextRunner.run(context -> {
PolarisServiceDiscovery polarisServiceDiscovery = context
.getBean(PolarisServiceDiscovery.class);
PolarisServiceDiscovery polarisServiceDiscovery = context.getBean(PolarisServiceDiscovery.class);
List<String> services = polarisServiceDiscovery.getServices();
assertThat(services.size()).isEqualTo(1);
});

@ -45,11 +45,9 @@ public class PolarisReactiveDiscoveryClientConfigurationTest {
private WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(PolarisContextConfiguration.class,
PolarisReactiveDiscoveryClientConfiguration.class,
PolarisDiscoveryClientConfiguration.class,
PolarisReactiveDiscoveryClientConfiguration.class, PolarisDiscoveryClientConfiguration.class,
PolarisContextConfiguration.class))
.withPropertyValues("spring.application.name=" + SERVICE_PROVIDER)
.withPropertyValues("server.port=" + PORT)
.withPropertyValues("spring.application.name=" + SERVICE_PROVIDER).withPropertyValues("server.port=" + PORT)
.withPropertyValues("spring.cloud.polaris.address=grpc://127.0.0.1:10081");
@BeforeClass
@ -66,8 +64,7 @@ public class PolarisReactiveDiscoveryClientConfigurationTest {
@Test
public void testDefaultInitialization() {
this.contextRunner.run(context -> assertThat(context)
.hasSingleBean(PolarisReactiveDiscoveryClient.class));
this.contextRunner.run(context -> assertThat(context).hasSingleBean(PolarisReactiveDiscoveryClient.class));
}
@Configuration

@ -57,8 +57,7 @@ public class PolarisReactiveDiscoveryClientTest {
@Test
public void testGetInstances() throws PolarisException {
when(serviceDiscovery.getInstances(SERVICE_PROVIDER))
.thenReturn(singletonList(serviceInstance));
when(serviceDiscovery.getInstances(SERVICE_PROVIDER)).thenReturn(singletonList(serviceInstance));
Flux<ServiceInstance> instances = this.client.getInstances(SERVICE_PROVIDER);
@ -68,14 +67,11 @@ public class PolarisReactiveDiscoveryClientTest {
@Test
public void testGetServices() throws PolarisException {
when(serviceDiscovery.getServices())
.thenReturn(Arrays.asList(SERVICE_PROVIDER + 1, SERVICE_PROVIDER + 2));
when(serviceDiscovery.getServices()).thenReturn(Arrays.asList(SERVICE_PROVIDER + 1, SERVICE_PROVIDER + 2));
Flux<String> services = this.client.getServices();
StepVerifier.create(services)
.expectNext(SERVICE_PROVIDER + 1, SERVICE_PROVIDER + 2).expectComplete()
.verify();
StepVerifier.create(services).expectNext(SERVICE_PROVIDER + 1, SERVICE_PROVIDER + 2).expectComplete().verify();
}
}

@ -47,10 +47,8 @@ public class PolarisServiceRegistryAutoConfigurationTest {
private WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(PolarisContextConfiguration.class,
PolarisServiceRegistryAutoConfiguration.class,
PolarisDiscoveryClientConfiguration.class))
.withPropertyValues("spring.application.name=" + SERVICE_PROVIDER)
.withPropertyValues("server.port=" + PORT)
PolarisServiceRegistryAutoConfiguration.class, PolarisDiscoveryClientConfiguration.class))
.withPropertyValues("spring.application.name=" + SERVICE_PROVIDER).withPropertyValues("server.port=" + PORT)
.withPropertyValues("spring.cloud.polaris.address=grpc://127.0.0.1:10081");
@BeforeClass
@ -69,8 +67,7 @@ public class PolarisServiceRegistryAutoConfigurationTest {
public void testDefaultInitialization() {
this.contextRunner.run(context -> {
assertThat(context).hasSingleBean(PolarisDiscoveryAutoConfiguration.class);
assertThat(context)
.hasSingleBean(AutoServiceRegistrationAutoConfiguration.class);
assertThat(context).hasSingleBean(AutoServiceRegistrationAutoConfiguration.class);
});
}

@ -50,15 +50,12 @@ public class PolarisServiceRegistryTest {
private static NamingServer namingServer;
private WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(PolarisContextConfiguration.class,
PolarisPropertiesConfiguration.class,
PolarisDiscoveryClientConfiguration.class,
PolarisDiscoveryAutoConfiguration.class))
.withPropertyValues("spring.application.name=" + SERVICE_PROVIDER)
.withPropertyValues("server.port=" + PORT)
.withConfiguration(
AutoConfigurations.of(PolarisContextConfiguration.class, PolarisPropertiesConfiguration.class,
PolarisDiscoveryClientConfiguration.class, PolarisDiscoveryAutoConfiguration.class))
.withPropertyValues("spring.application.name=" + SERVICE_PROVIDER).withPropertyValues("server.port=" + PORT)
.withPropertyValues("spring.cloud.polaris.address=grpc://127.0.0.1:10081")
.withPropertyValues(
"spring.cloud.polaris.discovery.namespace=" + NAMESPACE_TEST)
.withPropertyValues("spring.cloud.polaris.discovery.namespace=" + NAMESPACE_TEST)
.withPropertyValues("spring.cloud.polaris.discovery.token=xxxxxx");
@BeforeClass
@ -66,8 +63,7 @@ public class PolarisServiceRegistryTest {
namingServer = NamingServer.startNamingServer(10081);
// add service
namingServer.getNamingService()
.addService(new ServiceKey(NAMESPACE_TEST, SERVICE_PROVIDER));
namingServer.getNamingService().addService(new ServiceKey(NAMESPACE_TEST, SERVICE_PROVIDER));
}
@AfterClass
@ -80,8 +76,7 @@ public class PolarisServiceRegistryTest {
@Test
public void testRegister() {
this.contextRunner.run(context -> {
PolarisServiceRegistry registry = context
.getBean(PolarisServiceRegistry.class);
PolarisServiceRegistry registry = context.getBean(PolarisServiceRegistry.class);
PolarisRegistration registration = Mockito.mock(PolarisRegistration.class);
when(registration.getHost()).thenReturn("127.0.0.1");
when(registration.getPort()).thenReturn(PORT);

@ -1,92 +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.ribbon;
import com.netflix.client.config.DefaultClientConfigImpl;
import com.netflix.client.config.IClientConfig;
import com.tencent.cloud.polaris.context.PolarisContextConfiguration;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryClientConfiguration;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryHandler;
import org.junit.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST;
import static com.tencent.polaris.test.common.Consts.PORT;
import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Test for {@link PolarisRibbonServerListConfiguration}
*
* @author Haotian Zhang
*/
public class PolarisRibbonServerListConfigurationTest {
private WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(PolarisRibbonClientTest.class,
PolarisDiscoveryClientConfiguration.class,
PolarisContextConfiguration.class))
.withPropertyValues("spring.application.name=" + SERVICE_PROVIDER)
.withPropertyValues("server.port=" + PORT)
.withPropertyValues("spring.cloud.polaris.address=grpc://127.0.0.1:10081")
.withPropertyValues(
"spring.cloud.polaris.discovery.namespace=" + NAMESPACE_TEST)
.withPropertyValues("spring.cloud.polaris.discovery.token=xxxxxx");
@Test
public void testProperties() {
this.contextRunner.run(context -> {
PolarisDiscoveryHandler discoveryHandler = context
.getBean(PolarisDiscoveryHandler.class);
PolarisServerList serverList = new PolarisServerList(discoveryHandler);
IClientConfig iClientConfig = context.getBean(IClientConfig.class);
serverList.initWithNiwsConfig(iClientConfig);
assertThat(serverList.getServiceId()).isEqualTo(SERVICE_PROVIDER);
});
}
@Configuration
@EnableAutoConfiguration
@EnableDiscoveryClient
static class PolarisRibbonClientTest {
@Bean
IClientConfig iClientConfig() {
DefaultClientConfigImpl config = new DefaultClientConfigImpl();
config.setClientName(SERVICE_PROVIDER);
return config;
}
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
}
}

@ -1,146 +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.ribbon;
import java.util.List;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.Server;
import com.tencent.cloud.polaris.context.PolarisContextConfiguration;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryAutoConfiguration;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryClientConfiguration;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryHandler;
import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.test.mock.discovery.NamingServer;
import com.tencent.polaris.test.mock.discovery.NamingService;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.Configuration;
import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST;
import static com.tencent.polaris.test.common.Consts.PORT;
import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
* Test for {@link PolarisServerList}
*
* @author Haotian Zhang
*/
public class PolarisServerListTest {
private static NamingServer namingServer;
private WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(PolarisContextConfiguration.class,
PolarisServerListTest.PolarisPropertiesConfiguration.class,
PolarisDiscoveryClientConfiguration.class,
PolarisDiscoveryAutoConfiguration.class,
PolarisContextConfiguration.class))
.withPropertyValues("spring.application.name=" + SERVICE_PROVIDER)
.withPropertyValues("server.port=" + PORT)
.withPropertyValues("spring.cloud.polaris.address=grpc://127.0.0.1:10081")
.withPropertyValues(
"spring.cloud.polaris.discovery.namespace=" + NAMESPACE_TEST)
.withPropertyValues("spring.cloud.polaris.discovery.token=xxxxxx");
@BeforeClass
public static void beforeClass() throws Exception {
namingServer = NamingServer.startNamingServer(10081);
// add service
namingServer.getNamingService()
.addService(new ServiceKey(NAMESPACE_TEST, SERVICE_PROVIDER));
}
@AfterClass
public static void afterClass() throws Exception {
if (null != namingServer) {
namingServer.terminate();
}
}
/**
* Test {@link PolarisServerList#getInitialListOfServers()} with empty server list.
*/
@Test
@SuppressWarnings("unchecked")
public void test1() {
this.contextRunner.run(context -> {
// mock
IClientConfig iClientConfig = mock(IClientConfig.class);
when(iClientConfig.getClientName()).thenReturn(SERVICE_PROVIDER);
PolarisDiscoveryHandler polarisDiscoveryHandler = context
.getBean(PolarisDiscoveryHandler.class);
PolarisServerList serverList = new PolarisServerList(polarisDiscoveryHandler);
serverList.initWithNiwsConfig(iClientConfig);
List<Server> servers = serverList.getInitialListOfServers();
assertThat(servers).isEmpty();
});
}
/**
* Test {@link PolarisServerList#getUpdatedListOfServers()} with server list of size
* 3.
*/
@Test
@SuppressWarnings("unchecked")
public void test2() {
this.contextRunner.run(context -> {
// mock
IClientConfig iClientConfig = mock(IClientConfig.class);
when(iClientConfig.getClientName()).thenReturn(SERVICE_PROVIDER);
PolarisDiscoveryHandler polarisDiscoveryHandler = context
.getBean(PolarisDiscoveryHandler.class);
PolarisServerList serverList = new PolarisServerList(polarisDiscoveryHandler);
serverList.initWithNiwsConfig(iClientConfig);
// add service with 3 instances
NamingService.InstanceParameter instanceParameter = new NamingService.InstanceParameter();
instanceParameter.setHealthy(true);
instanceParameter.setIsolated(false);
instanceParameter.setWeight(100);
ServiceKey serviceKey = new ServiceKey(NAMESPACE_TEST, SERVICE_PROVIDER);
namingServer.getNamingService().batchAddInstances(serviceKey, PORT, 3,
instanceParameter);
List<Server> servers = serverList.getUpdatedListOfServers();
assertThat(servers).hasSize(3);
assertThat(servers.get(0).getPort()).isEqualTo(PORT);
assertThat(servers.get(1).getPort()).isEqualTo(PORT + 1);
assertThat(servers.get(2).getPort()).isEqualTo(PORT + 2);
});
}
@Configuration
@EnableAutoConfiguration
@EnableDiscoveryClient
static class PolarisPropertiesConfiguration {
}
}

@ -58,12 +58,6 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>

@ -41,8 +41,7 @@ import static javax.servlet.DispatcherType.REQUEST;
* @author Haotian Zhang
*/
@Configuration
@ConditionalOnProperty(name = "spring.cloud.polaris.ratelimit.enabled",
matchIfMissing = true)
@ConditionalOnProperty(name = "spring.cloud.polaris.ratelimit.enabled", matchIfMissing = true)
public class RateLimitConfiguration {
@Bean

@ -48,8 +48,7 @@ import org.springframework.web.server.WebFilterChain;
*/
public class QuotaCheckReactiveFilter implements WebFilter, Ordered {
private static final Logger LOG = LoggerFactory
.getLogger(QuotaCheckReactiveFilter.class);
private static final Logger LOG = LoggerFactory.getLogger(QuotaCheckReactiveFilter.class);
private final LimitAPI limitAPI;
@ -74,14 +73,14 @@ public class QuotaCheckReactiveFilter implements WebFilter, Ordered {
}
try {
QuotaResponse quotaResponse = QuotaCheckUtils.getQuota(limitAPI,
localNamespace, localService, 1, labels, null);
QuotaResponse quotaResponse = QuotaCheckUtils.getQuota(limitAPI, localNamespace, localService, 1, labels,
null);
if (quotaResponse.getCode() == QuotaResultCode.QuotaResultLimited) {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.TOO_MANY_REQUESTS);
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
DataBuffer dataBuffer = response.bufferFactory().allocateBuffer().write(
(RateLimitConstant.QUOTA_LIMITED_INFO + quotaResponse.getInfo())
DataBuffer dataBuffer = response.bufferFactory().allocateBuffer()
.write((RateLimitConstant.QUOTA_LIMITED_INFO + quotaResponse.getInfo())
.getBytes(StandardCharsets.UTF_8));
return response.writeWith(Mono.just(dataBuffer));
}

@ -50,8 +50,7 @@ import static org.springframework.http.HttpStatus.TOO_MANY_REQUESTS;
@Order(RateLimitConstant.FILTER_ORDER)
public class QuotaCheckServletFilter extends OncePerRequestFilter {
private static final Logger LOG = LoggerFactory
.getLogger(QuotaCheckServletFilter.class);
private static final Logger LOG = LoggerFactory.getLogger(QuotaCheckServletFilter.class);
private final LimitAPI limitAPI;
@ -60,8 +59,7 @@ public class QuotaCheckServletFilter extends OncePerRequestFilter {
}
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String localNamespace = MetadataContext.LOCAL_NAMESPACE;
String localService = MetadataContext.LOCAL_SERVICE;
@ -73,8 +71,8 @@ public class QuotaCheckServletFilter extends OncePerRequestFilter {
}
try {
QuotaResponse quotaResponse = QuotaCheckUtils.getQuota(limitAPI,
localNamespace, localService, 1, labels, null);
QuotaResponse quotaResponse = QuotaCheckUtils.getQuota(limitAPI, localNamespace, localService, 1, labels,
null);
if (quotaResponse.getCode() == QuotaResultCode.QuotaResultLimited) {
response.setStatus(TOO_MANY_REQUESTS.value());
response.getWriter().write(RateLimitConstant.QUOTA_LIMITED_INFO);

@ -37,8 +37,8 @@ public final class QuotaCheckUtils {
private QuotaCheckUtils() {
}
public static QuotaResponse getQuota(LimitAPI limitAPI, String namespace,
String service, int count, Map<String, String> labels, String method) {
public static QuotaResponse getQuota(LimitAPI limitAPI, String namespace, String service, int count,
Map<String, String> labels, String method) {
// build quota request
QuotaRequest quotaRequest = new QuotaRequest();
quotaRequest.setNamespace(namespace);
@ -51,10 +51,8 @@ public final class QuotaCheckUtils {
return limitAPI.getQuota(quotaRequest);
}
catch (Throwable throwable) {
LOG.error("fail to invoke getQuota of LimitAPI with QuotaRequest[{}].",
quotaRequest, throwable);
return new QuotaResponse(new QuotaResult(QuotaResult.Code.QuotaResultOk, 0,
"get quota failed"));
LOG.error("fail to invoke getQuota of LimitAPI with QuotaRequest[{}].", quotaRequest, throwable);
return new QuotaResponse(new QuotaResult(QuotaResult.Code.QuotaResultOk, 0, "get quota failed"));
}
}

@ -57,8 +57,7 @@ import static org.mockito.Mockito.when;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
classes = { CalleeControllerTests.Config.class, TestController.class },
properties = { "spring.application.name=java_provider_test",
"spring.cloud.polaris.discovery.namespace=Test",
properties = { "spring.application.name=java_provider_test", "spring.cloud.polaris.discovery.namespace=Test",
"spring.cloud.polaris.address=grpc://127.0.0.1:10081" })
public class CalleeControllerTests {
@ -83,8 +82,7 @@ public class CalleeControllerTests {
instanceParameter.setIsolated(false);
instanceParameter.setWeight(100);
ServiceKey serviceKey = new ServiceKey(NAMESPACE_TEST, SERVICE_PROVIDER);
namingServer.getNamingService().batchAddInstances(serviceKey, PORT, 3,
instanceParameter);
namingServer.getNamingService().batchAddInstances(serviceKey, PORT, 3, instanceParameter);
}
@AfterClass
@ -111,10 +109,8 @@ public class CalleeControllerTests {
try {
if (i > 9) {
QuotaResponse quotaResponse = mock(QuotaResponse.class);
when(quotaResponse.getCode())
.thenReturn(QuotaResultCode.QuotaResultLimited);
when(quotaResponse.getInfo())
.thenReturn("Testing rate limit after 10 times success.");
when(quotaResponse.getCode()).thenReturn(QuotaResultCode.QuotaResultLimited);
when(quotaResponse.getInfo()).thenReturn("Testing rate limit after 10 times success.");
when(limitAPI.getQuota(any())).thenReturn(quotaResponse);
}
String result = restTemplate.getForObject(url, String.class);

@ -21,29 +21,29 @@
</dependency>
<!-- Spring Cloud Tencent dependencies end -->
<!-- Polaris dependencies start -->
<dependency>
<groupId>com.tencent.polaris</groupId>
<artifactId>polaris-router-factory</artifactId>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
<!-- Polaris dependencies start -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
<groupId>com.tencent.polaris</groupId>
<artifactId>polaris-router-factory</artifactId>
</dependency>
<dependency>
<groupId>com.tencent.polaris</groupId>
<artifactId>polaris-test-common</artifactId>
<artifactId>polaris-test-common</artifactId>
<scope>test</scope>
</dependency>
<!-- Polaris dependencies end -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

@ -21,17 +21,10 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.DynamicServerListLoadBalancer;
import com.netflix.loadbalancer.IPing;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.PollingServerListUpdater;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerList;
import com.tencent.cloud.common.constant.MetadataConstant.SystemMetadataKey;
import com.tencent.cloud.common.constant.MetadataConstant;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.pojo.PolarisServer;
import com.tencent.cloud.common.pojo.PolarisServiceInstance;
import com.tencent.polaris.api.pojo.DefaultInstance;
import com.tencent.polaris.api.pojo.DefaultServiceInstances;
import com.tencent.polaris.api.pojo.Instance;
@ -42,70 +35,68 @@ import com.tencent.polaris.router.api.core.RouterAPI;
import com.tencent.polaris.router.api.rpc.ProcessRoutersRequest;
import com.tencent.polaris.router.api.rpc.ProcessRoutersResponse;
import org.apache.commons.lang.StringUtils;
import reactor.core.publisher.Flux;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.Request;
import org.springframework.cloud.loadbalancer.core.DelegatingServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.util.CollectionUtils;
/**
* Routing load balancer of polaris.
* Service instance list supplier of Polaris.
*
* @author Haotian Zhang
*/
public class PolarisRoutingLoadBalancer extends DynamicServerListLoadBalancer<Server> {
public class PolarisRouterServiceInstanceListSupplier extends DelegatingServiceInstanceListSupplier {
private final RouterAPI routerAPI;
public PolarisRoutingLoadBalancer(IClientConfig config, IRule rule, IPing ping,
ServerList<Server> serverList, RouterAPI routerAPI) {
super(config, rule, ping, serverList, null, new PollingServerListUpdater());
public PolarisRouterServiceInstanceListSupplier(ServiceInstanceListSupplier delegate, RouterAPI routerAPI) {
super(delegate);
this.routerAPI = routerAPI;
}
@Override
public List<Server> getReachableServers() {
List<Server> allServers = super.getAllServers();
public Flux<List<ServiceInstance>> get() {
return getDelegate().get().map(this::chooseInstances);
}
@Override
public Flux<List<ServiceInstance>> get(Request request) {
return super.get(request);
}
public List<ServiceInstance> chooseInstances(List<ServiceInstance> allServers) {
if (CollectionUtils.isEmpty(allServers)) {
return allServers;
}
ServiceInstances serviceInstances = null;
if (allServers.get(0) instanceof PolarisServer) {
serviceInstances = ((PolarisServer) allServers.get(0)).getServiceInstances();
String serviceName = allServers.get(0).getServiceId();
if (StringUtils.isBlank(serviceName)) {
throw new IllegalStateException(
"PolarisRoutingLoadBalancer only Server with AppName or ServiceIdForDiscovery attribute");
}
else {
String serviceName;
// notice the difference between different service registries
if (StringUtils.isNotBlank(allServers.get(0).getMetaInfo().getServiceIdForDiscovery())) {
serviceName = allServers.get(0).getMetaInfo().getServiceIdForDiscovery();
}
else {
serviceName = allServers.get(0).getMetaInfo().getAppName();
}
if (StringUtils.isBlank(serviceName)) {
throw new IllegalStateException(
"PolarisRoutingLoadBalancer only Server with AppName or ServiceIdForDiscovery attribute");
}
ServiceKey serviceKey = new ServiceKey(MetadataContext.LOCAL_NAMESPACE, serviceName);
List<Instance> instances = new ArrayList<>(8);
for (Server server : allServers) {
DefaultInstance instance = new DefaultInstance();
instance.setNamespace(MetadataContext.LOCAL_NAMESPACE);
instance.setService(serviceName);
instance.setHealthy(server.isAlive());
instance.setProtocol(server.getScheme());
instance.setId(server.getId());
instance.setHost(server.getHost());
instance.setPort(server.getPort());
instance.setZone(server.getZone());
instance.setWeight(100);
instances.add(instance);
}
serviceInstances = new DefaultServiceInstances(serviceKey, instances);
ServiceKey serviceKey = new ServiceKey(MetadataContext.LOCAL_NAMESPACE, serviceName);
List<Instance> instances = new ArrayList<>(8);
for (ServiceInstance server : allServers) {
DefaultInstance instance = new DefaultInstance();
instance.setNamespace(MetadataContext.LOCAL_NAMESPACE);
instance.setService(serviceName);
instance.setProtocol(server.getScheme());
instance.setId(server.getInstanceId());
instance.setHost(server.getHost());
instance.setPort(server.getPort());
instance.setWeight(100);
instances.add(instance);
}
serviceInstances = new DefaultServiceInstances(serviceKey, instances);
ProcessRoutersRequest processRoutersRequest = new ProcessRoutersRequest();
processRoutersRequest.setDstInstances(serviceInstances);
String srcNamespace = MetadataContext.LOCAL_NAMESPACE;
String srcService = MetadataContext.LOCAL_SERVICE;
Map<String, String> transitiveCustomMetadata = MetadataContextHolder.get().getAllTransitiveCustomMetadata();
String method = MetadataContextHolder.get().getSystemMetadata(SystemMetadataKey.PEER_PATH);
String method = MetadataContextHolder.get().getSystemMetadata(MetadataConstant.SystemMetadataKey.PEER_PATH);
processRoutersRequest.setMethod(method);
if (StringUtils.isNotBlank(srcNamespace) && StringUtils.isNotBlank(srcService)) {
ServiceInfo serviceInfo = new ServiceInfo();
@ -114,20 +105,13 @@ public class PolarisRoutingLoadBalancer extends DynamicServerListLoadBalancer<Se
serviceInfo.setMetadata(transitiveCustomMetadata);
processRoutersRequest.setSourceService(serviceInfo);
}
ProcessRoutersResponse processRoutersResponse = routerAPI
.processRouters(processRoutersRequest);
ServiceInstances filteredServiceInstances = processRoutersResponse
.getServiceInstances();
List<Server> filteredInstances = new ArrayList<>();
ProcessRoutersResponse processRoutersResponse = routerAPI.processRouters(processRoutersRequest);
ServiceInstances filteredServiceInstances = processRoutersResponse.getServiceInstances();
List<ServiceInstance> filteredInstances = new ArrayList<>();
for (Instance instance : filteredServiceInstances.getInstances()) {
filteredInstances.add(new PolarisServer(serviceInstances, instance));
filteredInstances.add(new PolarisServiceInstance(instance));
}
return filteredInstances;
}
@Override
public List<Server> getAllServers() {
return getReachableServers();
}
}

@ -0,0 +1,115 @@
/*
* 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.router;
import java.util.List;
import java.util.stream.Collectors;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.pojo.PolarisServiceInstance;
import com.tencent.cloud.polaris.router.config.PolarisLoadBalancerProperties;
import com.tencent.polaris.api.pojo.DefaultServiceInstances;
import com.tencent.polaris.api.pojo.Instance;
import com.tencent.polaris.api.pojo.ServiceInstances;
import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.api.rpc.Criteria;
import com.tencent.polaris.router.api.core.RouterAPI;
import com.tencent.polaris.router.api.rpc.ProcessLoadBalanceRequest;
import com.tencent.polaris.router.api.rpc.ProcessLoadBalanceResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.core.publisher.Mono;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.DefaultResponse;
import org.springframework.cloud.client.loadbalancer.EmptyResponse;
import org.springframework.cloud.client.loadbalancer.Request;
import org.springframework.cloud.client.loadbalancer.Response;
import org.springframework.cloud.loadbalancer.core.NoopServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer;
import org.springframework.cloud.loadbalancer.core.RoundRobinLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
/**
* Loadbalancer of Polaris.
*
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
*/
public class PolarisRoutingLoadbalancer extends RoundRobinLoadBalancer implements ReactorServiceInstanceLoadBalancer {
private static final Logger log = LoggerFactory.getLogger(PolarisRoutingLoadbalancer.class);
private final String serviceId;
private final PolarisLoadBalancerProperties loadBalancerProperties;
private final RouterAPI routerAPI;
private ObjectProvider<ServiceInstanceListSupplier> supplierObjectProvider;
public PolarisRoutingLoadbalancer(String serviceId,
ObjectProvider<ServiceInstanceListSupplier> supplierObjectProvider,
PolarisLoadBalancerProperties loadBalancerProperties, RouterAPI routerAPI) {
super(supplierObjectProvider, serviceId);
this.serviceId = serviceId;
this.supplierObjectProvider = supplierObjectProvider;
this.loadBalancerProperties = loadBalancerProperties;
this.routerAPI = routerAPI;
}
private static ServiceInstances convertToPolarisServiceInstances(List<ServiceInstance> serviceInstances) {
ServiceKey serviceKey = new ServiceKey(MetadataContext.LOCAL_NAMESPACE, serviceInstances.get(0).getServiceId());
List<Instance> polarisInstances = serviceInstances.stream()
.map(serviceInstance -> ((PolarisServiceInstance) serviceInstance).getPolarisInstance())
.collect(Collectors.toList());
return new DefaultServiceInstances(serviceKey, polarisInstances);
}
@Override
public Mono<Response<ServiceInstance>> choose(Request request) {
if (!loadBalancerProperties.getLoadbalancerEnabled()) {
return super.choose(request);
}
ServiceInstanceListSupplier supplier = supplierObjectProvider
.getIfAvailable(NoopServiceInstanceListSupplier::new);
return supplier.get().next().map(this::getInstanceResponse);
}
private Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> serviceInstances) {
if (serviceInstances.isEmpty()) {
log.warn("No servers available for service: " + this.serviceId);
return new EmptyResponse();
}
ProcessLoadBalanceRequest request = new ProcessLoadBalanceRequest();
request.setDstInstances(convertToPolarisServiceInstances(serviceInstances));
request.setLbPolicy(loadBalancerProperties.getStrategy());
request.setCriteria(new Criteria());
try {
ProcessLoadBalanceResponse response = routerAPI.processLoadBalance(request);
return new DefaultResponse(new PolarisServiceInstance(response.getTargetInstance()));
}
catch (Exception e) {
log.warn("PolarisRoutingLoadbalancer error", e);
return new EmptyResponse();
}
}
}

@ -26,28 +26,27 @@ import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration;
import org.springframework.cloud.netflix.ribbon.RibbonClients;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients;
import org.springframework.cloud.loadbalancer.config.LoadBalancerAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Auto-configuration Ribbon for Polaris.
* Autoconfiguration of loadbalancer of Polaris.
*
* @author Haotian Zhang
* @author Haotian Zhang, Andrew Shan, Jie Cheng
*/
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties
@ConditionalOnProperty(value = "spring.cloud.polaris.loadbalancer.enabled",
matchIfMissing = true)
@AutoConfigureAfter(RibbonAutoConfiguration.class)
@RibbonClients(defaultConfiguration = PolarisRibbonClientConfiguration.class)
public class PolarisRibbonAutoConfiguration {
@ConditionalOnProperty(value = "spring.cloud.polaris.loadbalancer.enabled", matchIfMissing = true)
@AutoConfigureAfter(LoadBalancerAutoConfiguration.class)
@LoadBalancerClients(defaultConfiguration = PolarisLoadBalancerClientConfiguration.class)
public class PolarisLoadBalancerAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public PolarisRibbonProperties polarisRibbonProperties() {
return new PolarisRibbonProperties();
public PolarisLoadBalancerProperties polarisLoadBalancerProperties() {
return new PolarisLoadBalancerProperties();
}
@Bean(name = "polarisRoute")

@ -0,0 +1,102 @@
/*
* 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.router.config;
import com.tencent.cloud.polaris.router.PolarisRouterServiceInstanceListSupplier;
import com.tencent.cloud.polaris.router.PolarisRoutingLoadbalancer;
import com.tencent.polaris.router.api.core.RouterAPI;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.client.ConditionalOnBlockingDiscoveryEnabled;
import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;
import org.springframework.cloud.client.ConditionalOnReactiveDiscoveryEnabled;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.discovery.ReactiveDiscoveryClient;
import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.Environment;
/**
* Configuration of loadbalancer client.
*
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnDiscoveryEnabled
public class PolarisLoadBalancerClientConfiguration {
/**
* Order of reactive discovery service instance supplier.
*/
private static final int REACTIVE_SERVICE_INSTANCE_SUPPLIER_ORDER = 193827465;
@Bean
@ConditionalOnMissingBean
public ReactorLoadBalancer<ServiceInstance> polarisLoadBalancer(Environment environment,
LoadBalancerClientFactory loadBalancerClientFactory, PolarisLoadBalancerProperties loadBalancerProperties,
RouterAPI routerAPI) {
String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
return new PolarisRoutingLoadbalancer(name,
loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class),
loadBalancerProperties, routerAPI);
}
@Configuration
@ConditionalOnReactiveDiscoveryEnabled
@Order(REACTIVE_SERVICE_INSTANCE_SUPPLIER_ORDER)
static class PolarisReactiveSupportConfiguration {
@Bean
@ConditionalOnBean(ReactiveDiscoveryClient.class)
@ConditionalOnMissingBean
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations", havingValue = "polaris")
public ServiceInstanceListSupplier polarisRouterDiscoveryClientServiceInstanceListSupplier(RouterAPI routerAPI,
ConfigurableApplicationContext context) {
return new PolarisRouterServiceInstanceListSupplier(
ServiceInstanceListSupplier.builder().withDiscoveryClient().build(context), routerAPI);
}
}
@Configuration
@ConditionalOnBlockingDiscoveryEnabled
@Order(REACTIVE_SERVICE_INSTANCE_SUPPLIER_ORDER + 1)
static class PolarisBlockingSupportConfiguration {
@Bean
@ConditionalOnBean(DiscoveryClient.class)
@ConditionalOnMissingBean
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations", havingValue = "polaris")
public ServiceInstanceListSupplier polarisRouterDiscoveryClientServiceInstanceListSupplier(RouterAPI routerAPI,
ConfigurableApplicationContext context) {
return new PolarisRouterServiceInstanceListSupplier(
ServiceInstanceListSupplier.builder().withBlockingDiscoveryClient().build(context), routerAPI);
}
}
}

@ -21,12 +21,12 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* Properties of Ribbon.
* Properties of loadbalancer.
*
* @author Haotian Zhang
*/
@ConfigurationProperties("spring.cloud.polaris.ribbon")
public class PolarisRibbonProperties {
public class PolarisLoadBalancerProperties {
/**
* If load-balance enabled.
@ -58,8 +58,8 @@ public class PolarisRibbonProperties {
@Override
public String toString() {
return "PolarisRibbonProperties{" + "loadbalancerEnabled=" + loadbalancerEnabled
+ ", strategy='" + strategy + '\'' + '}';
return "PolarisRibbonProperties{" + "loadbalancerEnabled=" + loadbalancerEnabled + ", strategy='" + strategy
+ '\'' + '}';
}
}

@ -1,63 +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.router.config;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.IPing;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerList;
import com.tencent.cloud.polaris.router.PolarisRoutingLoadBalancer;
import com.tencent.cloud.polaris.router.rule.PolarisLoadBalanceRule;
import com.tencent.cloud.polaris.router.rule.PolarisWeightedRandomRule;
import com.tencent.polaris.router.api.core.RouterAPI;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Configuration of ribbon client of Polaris.
*
* @author Haotian Zhang
*/
@Configuration
public class PolarisRibbonClientConfiguration {
@Bean
@ConditionalOnMissingBean
public IRule polarisRibbonRule(PolarisRibbonProperties polarisRibbonProperties) {
switch (PolarisLoadBalanceRule
.fromStrategy(polarisRibbonProperties.getStrategy())) {
case WEIGHTED_RANDOM_RULE:
default:
return new PolarisWeightedRandomRule();
}
}
@Bean
@ConditionalOnMissingBean
public ILoadBalancer polarisRoutingLoadBalancer(IClientConfig iClientConfig,
IRule iRule, IPing iPing, ServerList<Server> serverList,
RouterAPI polarisRouter) {
return new PolarisRoutingLoadBalancer(iClientConfig, iRule, iPing, serverList,
polarisRouter);
}
}

@ -1,52 +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.router.rule;
import java.util.Arrays;
/**
* Load balance rule.
*
* @author Haotian Zhang
*/
public enum PolarisLoadBalanceRule {
/**
* Weighted random load balance rule.
*/
WEIGHTED_RANDOM_RULE("weighted_random");
/**
* Load balance strategy.
*/
final String policy;
PolarisLoadBalanceRule(String strategy) {
this.policy = strategy;
}
public static PolarisLoadBalanceRule fromStrategy(String strategy) {
return Arrays.stream(values()).filter(t -> t.getPolicy().equals(strategy))
.findAny().orElse(WEIGHTED_RANDOM_RULE);
}
public String getPolicy() {
return policy;
}
}

@ -1,73 +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.router.rule;
import java.util.List;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.Server;
import com.tencent.cloud.common.pojo.PolarisServer;
import com.tencent.polaris.api.config.consumer.LoadBalanceConfig;
import com.tencent.polaris.api.pojo.Instance;
import com.tencent.polaris.router.api.core.RouterAPI;
import com.tencent.polaris.router.api.rpc.ProcessLoadBalanceRequest;
import com.tencent.polaris.router.api.rpc.ProcessLoadBalanceResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
/**
* Weighted random load balance strategy.
*
* @author Haotian Zhang
*/
public class PolarisWeightedRandomRule extends AbstractLoadBalancerRule {
private static final String POLICY = LoadBalanceConfig.LOAD_BALANCE_WEIGHTED_RANDOM;
@Autowired
private RouterAPI polarisRouter;
@Override
public void initWithNiwsConfig(IClientConfig clientConfig) {
}
@Override
public Server choose(Object key) {
List<Server> allServers = getLoadBalancer().getReachableServers();
if (CollectionUtils.isEmpty(allServers)) {
return null;
}
Server server = allServers.get(0);
if (!(server instanceof PolarisServer)) {
throw new IllegalStateException(
"PolarisDiscoveryRule only support PolarisServer instances");
}
PolarisServer polarisServer = (PolarisServer) server;
ProcessLoadBalanceRequest request = new ProcessLoadBalanceRequest();
request.setDstInstances(polarisServer.getServiceInstances());
request.setLbPolicy(POLICY);
ProcessLoadBalanceResponse processLoadBalanceResponse = polarisRouter
.processLoadBalance(request);
Instance targetInstance = processLoadBalanceResponse.getTargetInstance();
return new PolarisServer(polarisServer.getServiceInstances(), targetInstance);
}
}

@ -1,2 +1,2 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.tencent.cloud.polaris.router.config.PolarisRibbonAutoConfiguration
com.tencent.cloud.polaris.router.config.PolarisLoadBalancerAutoConfiguration

@ -1,62 +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.router.config;
import com.tencent.cloud.polaris.context.PolarisContextConfiguration;
import com.tencent.polaris.router.api.core.RouterAPI;
import org.junit.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Configuration;
import static com.tencent.polaris.test.common.Consts.PORT;
import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Test for {@link PolarisRibbonAutoConfiguration}
*
* @author Haotian Zhang
*/
public class PolarisRibbonAutoConfigurationTest {
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(PolarisRibbonTest.class,
PolarisRibbonAutoConfiguration.class,
PolarisContextConfiguration.class))
.withPropertyValues("spring.application.name=" + SERVICE_PROVIDER)
.withPropertyValues("server.port=" + PORT)
.withPropertyValues("spring.cloud.polaris.address=grpc://127.0.0.1:10081");
@Test
public void testDefaultInitialization() {
this.contextRunner.run(context -> {
assertThat(context).hasSingleBean(RouterAPI.class);
assertThat(context).hasSingleBean(PolarisRibbonProperties.class);
});
}
@Configuration
@EnableAutoConfiguration
static class PolarisRibbonTest {
}
}

@ -0,0 +1,88 @@
/*
* 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.router.config;
import com.tencent.cloud.polaris.context.PolarisContextConfiguration;
import com.tencent.cloud.polaris.router.PolarisRouterServiceInstanceListSupplier;
import com.tencent.polaris.router.api.core.RouterAPI;
import org.junit.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Configuration;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Test for {@link PolarisLoadBalancerAutoConfiguration}
*
* @author Haotian Zhang
*/
public class PolarisRouterAutoConfigurationTest {
private final ApplicationContextRunner blockingContextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(PolarisLoadBalancerTest.class, PolarisContextConfiguration.class,
PolarisLoadBalancerAutoConfiguration.class,
PolarisLoadBalancerClientConfiguration.PolarisBlockingSupportConfiguration.class))
.withPropertyValues("spring.cloud.loadbalancer.configurations=polaris");
private final ApplicationContextRunner noPolarisContextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(PolarisLoadBalancerTest.class, PolarisContextConfiguration.class,
PolarisLoadBalancerAutoConfiguration.class,
PolarisLoadBalancerClientConfiguration.PolarisBlockingSupportConfiguration.class));
/**
* Test for BlockingDiscovery.
*/
@Test
public void test1() {
this.blockingContextRunner.run(context -> {
assertThat(context).hasSingleBean(RouterAPI.class);
assertThat(context).hasSingleBean(PolarisLoadBalancerProperties.class);
assertThat(context)
.doesNotHaveBean(PolarisLoadBalancerClientConfiguration.PolarisReactiveSupportConfiguration.class);
assertThat(context)
.hasSingleBean(PolarisLoadBalancerClientConfiguration.PolarisBlockingSupportConfiguration.class);
assertThat(context).doesNotHaveBean(PolarisRouterServiceInstanceListSupplier.class);
});
}
/**
* Test for no Polaris.
*/
@Test
public void test2() {
this.noPolarisContextRunner.run(context -> {
assertThat(context).hasSingleBean(RouterAPI.class);
assertThat(context).hasSingleBean(PolarisLoadBalancerProperties.class);
assertThat(context)
.doesNotHaveBean(PolarisLoadBalancerClientConfiguration.PolarisReactiveSupportConfiguration.class);
assertThat(context)
.hasSingleBean(PolarisLoadBalancerClientConfiguration.PolarisBlockingSupportConfiguration.class);
assertThat(context).doesNotHaveBean(PolarisRouterServiceInstanceListSupplier.class);
});
}
@Configuration
@EnableAutoConfiguration
static class PolarisLoadBalancerTest {
}
}

@ -66,8 +66,8 @@
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<optional>true</optional>
</dependency>

@ -61,8 +61,7 @@ public final class MetadataConstant {
/**
* Order of MetadataFirstFeignInterceptor.
*/
public static int METADATA_FIRST_FEIGN_INTERCEPTOR_ORDER = Ordered.HIGHEST_PRECEDENCE
+ 1;
public static int METADATA_FIRST_FEIGN_INTERCEPTOR_ORDER = Ordered.HIGHEST_PRECEDENCE + 1;
/**
* Order of Metadata2HeaderInterceptor.

@ -93,8 +93,7 @@ public class MetadataContext {
@Override
public String toString() {
return "MetadataContext{" + "transitiveCustomMetadata="
+ JacksonUtils.serialize2Json(transitiveCustomMetadata)
return "MetadataContext{" + "transitiveCustomMetadata=" + JacksonUtils.serialize2Json(transitiveCustomMetadata)
+ ", systemMetadata=" + JacksonUtils.serialize2Json(systemMetadata) + '}';
}

@ -49,13 +49,12 @@ public final class MetadataContextHolder {
if (null == METADATA_CONTEXT.get()) {
MetadataContext metadataContext = new MetadataContext();
if (metadataLocalProperties == null) {
metadataLocalProperties = (MetadataLocalProperties) ApplicationContextAwareUtils
.getApplicationContext().getBean("metadataLocalProperties");
metadataLocalProperties = (MetadataLocalProperties) ApplicationContextAwareUtils.getApplicationContext()
.getBean("metadataLocalProperties");
}
// init custom metadata and load local metadata
Map<String, String> transitiveMetadataMap = getTransitiveMetadataMap(
metadataLocalProperties.getContent(),
Map<String, String> transitiveMetadataMap = getTransitiveMetadataMap(metadataLocalProperties.getContent(),
metadataLocalProperties.getTransitive());
metadataContext.putAllTransitiveCustomMetadata(transitiveMetadataMap);
@ -70,8 +69,8 @@ public final class MetadataContextHolder {
* @param transitiveMetadataKeyList transitive metadata name list
* @return result
*/
private static Map<String, String> getTransitiveMetadataMap(
Map<String, String> source, List<String> transitiveMetadataKeyList) {
private static Map<String, String> getTransitiveMetadataMap(Map<String, String> source,
List<String> transitiveMetadataKeyList) {
Map<String, String> result = new HashMap<>();
for (String key : transitiveMetadataKeyList) {
if (source.containsKey(key)) {
@ -94,8 +93,7 @@ public final class MetadataContextHolder {
* @param customMetadataMap custom metadata collection
* @param systemMetadataMap system metadata collection
*/
public static void init(Map<String, String> customMetadataMap,
Map<String, String> systemMetadataMap) {
public static void init(Map<String, String> customMetadataMap, Map<String, String> systemMetadataMap) {
// Init ThreadLocal.
MetadataContextHolder.remove();
MetadataContext metadataContext = MetadataContextHolder.get();

@ -17,10 +17,8 @@
package com.tencent.cloud.common.metadata.config;
import com.netflix.zuul.ZuulFilter;
import com.tencent.cloud.common.constant.MetadataConstant;
import com.tencent.cloud.common.metadata.filter.gateway.MetadataFirstScgFilter;
import com.tencent.cloud.common.metadata.filter.gateway.MetadataFirstZuulFilter;
import com.tencent.cloud.common.metadata.filter.web.MetadataReactiveFilter;
import com.tencent.cloud.common.metadata.filter.web.MetadataServletFilter;
import com.tencent.cloud.common.metadata.interceptor.feign.MetadataFirstFeignInterceptor;
@ -67,10 +65,8 @@ public class MetadataAutoConfiguration {
MetadataServletFilter metadataServletFilter) {
FilterRegistrationBean<MetadataServletFilter> filterRegistrationBean = new FilterRegistrationBean<>(
metadataServletFilter);
filterRegistrationBean.setDispatcherTypes(ASYNC, ERROR, FORWARD, INCLUDE,
REQUEST);
filterRegistrationBean
.setOrder(MetadataConstant.OrderConstant.WEB_FILTER_ORDER);
filterRegistrationBean.setDispatcherTypes(ASYNC, ERROR, FORWARD, INCLUDE, REQUEST);
filterRegistrationBean.setOrder(MetadataConstant.OrderConstant.WEB_FILTER_ORDER);
return filterRegistrationBean;
}
@ -109,20 +105,6 @@ public class MetadataAutoConfiguration {
}
/**
* Create when gateway application is Zuul.
*/
@Configuration
@ConditionalOnClass(name = "com.netflix.zuul.http.ZuulServlet")
static class MetadataZuulFilterConfig {
@Bean
public ZuulFilter metadataFirstZuulFilter() {
return new MetadataFirstZuulFilter();
}
}
/**
* Create when gateway application is SCG.
*/

@ -55,23 +55,19 @@ public class MetadataFirstScgFilter implements GlobalFilter, Ordered {
Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);
// get metadata of current thread
MetadataContext metadataContext = exchange
.getAttribute(MetadataConstant.HeaderName.METADATA_CONTEXT);
MetadataContext metadataContext = exchange.getAttribute(MetadataConstant.HeaderName.METADATA_CONTEXT);
if (metadataContext == null) {
metadataContext = MetadataContextHolder.get();
}
// TODO The peer namespace is temporarily the same as the local namespace
metadataContext.putSystemMetadata(
MetadataConstant.SystemMetadataKey.PEER_NAMESPACE,
metadataContext.putSystemMetadata(MetadataConstant.SystemMetadataKey.PEER_NAMESPACE,
MetadataContext.LOCAL_NAMESPACE);
metadataContext.putSystemMetadata(MetadataConstant.SystemMetadataKey.PEER_SERVICE,
route.getId());
metadataContext.putSystemMetadata(MetadataConstant.SystemMetadataKey.PEER_SERVICE, route.getId());
metadataContext.putSystemMetadata(MetadataConstant.SystemMetadataKey.PEER_PATH,
exchange.getRequest().getURI().getPath());
exchange.getAttributes().put(MetadataConstant.HeaderName.METADATA_CONTEXT,
metadataContext);
exchange.getAttributes().put(MetadataConstant.HeaderName.METADATA_CONTEXT, metadataContext);
return chain.filter(exchange);
}

@ -1,70 +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.common.metadata.filter.gateway;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.tencent.cloud.common.constant.MetadataConstant;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_DECORATION_FILTER_ORDER;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.REQUEST_URI_KEY;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.SERVICE_ID_KEY;
/**
* Zuul output first filter used for setting peer info in context.
*
* @author Haotian Zhang
*/
public class MetadataFirstZuulFilter extends ZuulFilter {
@Override
public String filterType() {
return PRE_TYPE;
}
@Override
public int filterOrder() {
return PRE_DECORATION_FILTER_ORDER + 1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {
// get request context
RequestContext requestContext = RequestContext.getCurrentContext();
// TODO The peer namespace is temporarily the same as the local namespace
MetadataContextHolder.get().putSystemMetadata(
MetadataConstant.SystemMetadataKey.PEER_NAMESPACE,
MetadataContext.LOCAL_NAMESPACE);
MetadataContextHolder.get().putSystemMetadata(
MetadataConstant.SystemMetadataKey.PEER_SERVICE,
(String) requestContext.get(SERVICE_ID_KEY));
MetadataContextHolder.get().putSystemMetadata(
MetadataConstant.SystemMetadataKey.PEER_PATH,
(String) requestContext.get(REQUEST_URI_KEY));
return null;
}
}

@ -44,8 +44,7 @@ import org.springframework.web.server.WebFilterChain;
*/
public class MetadataReactiveFilter implements WebFilter, Ordered {
private static final Logger LOG = LoggerFactory
.getLogger(MetadataReactiveFilter.class);
private static final Logger LOG = LoggerFactory.getLogger(MetadataReactiveFilter.class);
@Override
public int getOrder() {
@ -53,13 +52,11 @@ public class MetadataReactiveFilter implements WebFilter, Ordered {
}
@Override
public Mono<Void> filter(ServerWebExchange serverWebExchange,
WebFilterChain webFilterChain) {
public Mono<Void> filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) {
// Get metadata string from http header.
ServerHttpRequest serverHttpRequest = serverWebExchange.getRequest();
HttpHeaders httpHeaders = serverHttpRequest.getHeaders();
String customMetadataStr = httpHeaders
.getFirst(MetadataConstant.HeaderName.CUSTOM_METADATA);
String customMetadataStr = httpHeaders.getFirst(MetadataConstant.HeaderName.CUSTOM_METADATA);
try {
if (StringUtils.hasText(customMetadataStr)) {
customMetadataStr = URLDecoder.decode(customMetadataStr, "UTF-8");
@ -71,18 +68,15 @@ public class MetadataReactiveFilter implements WebFilter, Ordered {
LOG.debug("Get upstream metadata string: {}", customMetadataStr);
// create custom metadata.
Map<String, String> upstreamCustomMetadataMap = JacksonUtils
.deserialize2Map(customMetadataStr);
Map<String, String> upstreamCustomMetadataMap = JacksonUtils.deserialize2Map(customMetadataStr);
MetadataContextHolder.init(upstreamCustomMetadataMap, null);
// Save to ServerWebExchange.
serverWebExchange.getAttributes().put(
MetadataConstant.HeaderName.METADATA_CONTEXT,
serverWebExchange.getAttributes().put(MetadataConstant.HeaderName.METADATA_CONTEXT,
MetadataContextHolder.get());
return webFilterChain.filter(serverWebExchange)
.doOnError(throwable -> LOG.error("handle metadata[{}] error.",
MetadataContextHolder.get(), throwable))
.doOnError(throwable -> LOG.error("handle metadata[{}] error.", MetadataContextHolder.get(), throwable))
.doFinally((type) -> MetadataContextHolder.remove());
}

@ -46,16 +46,13 @@ import org.springframework.web.filter.OncePerRequestFilter;
@Order(MetadataConstant.OrderConstant.WEB_FILTER_ORDER)
public class MetadataServletFilter extends OncePerRequestFilter {
private static final Logger LOG = LoggerFactory
.getLogger(MetadataServletFilter.class);
private static final Logger LOG = LoggerFactory.getLogger(MetadataServletFilter.class);
@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse, FilterChain filterChain)
throws ServletException, IOException {
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
FilterChain filterChain) throws ServletException, IOException {
// Get custom metadata string from http header.
String customMetadataStr = httpServletRequest
.getHeader(MetadataConstant.HeaderName.CUSTOM_METADATA);
String customMetadataStr = httpServletRequest.getHeader(MetadataConstant.HeaderName.CUSTOM_METADATA);
try {
if (StringUtils.hasText(customMetadataStr)) {
customMetadataStr = URLDecoder.decode(customMetadataStr, "UTF-8");
@ -67,8 +64,7 @@ public class MetadataServletFilter extends OncePerRequestFilter {
LOG.debug("Get upstream metadata string: {}", customMetadataStr);
// create custom metadata.
Map<String, String> upstreamCustomMetadataMap = JacksonUtils
.deserialize2Map(customMetadataStr);
Map<String, String> upstreamCustomMetadataMap = JacksonUtils.deserialize2Map(customMetadataStr);
try {
MetadataContextHolder.init(upstreamCustomMetadataMap, null);

@ -43,13 +43,11 @@ public class MetadataFirstFeignInterceptor implements RequestInterceptor, Ordere
MetadataContext metadataContext = MetadataContextHolder.get();
// TODO The peer namespace is temporarily the same as the local namespace
metadataContext.putSystemMetadata(
MetadataConstant.SystemMetadataKey.PEER_NAMESPACE,
metadataContext.putSystemMetadata(MetadataConstant.SystemMetadataKey.PEER_NAMESPACE,
MetadataContext.LOCAL_NAMESPACE);
metadataContext.putSystemMetadata(MetadataConstant.SystemMetadataKey.PEER_SERVICE,
requestTemplate.feignTarget().name());
metadataContext.putSystemMetadata(MetadataConstant.SystemMetadataKey.PEER_PATH,
requestTemplate.path());
metadataContext.putSystemMetadata(MetadataConstant.SystemMetadataKey.PEER_PATH, requestTemplate.path());
}
}

@ -1,111 +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.common.pojo;
import java.util.Map;
import java.util.Objects;
import com.netflix.loadbalancer.Server;
import com.tencent.polaris.api.pojo.Instance;
import com.tencent.polaris.api.pojo.ServiceInstances;
import org.apache.commons.lang.StringUtils;
/**
* Polaris' implementation of {@link Server}.
*
* @author Haotian Zhang
*/
public class PolarisServer extends Server {
private final ServiceInstances serviceInstances;
private final Instance instance;
private final MetaInfo metaInfo;
public PolarisServer(ServiceInstances serviceInstances, Instance instance) {
super(instance.getHost(), instance.getPort());
if (StringUtils.equalsIgnoreCase(instance.getProtocol(), "https")) {
setSchemea("https");
}
else {
setSchemea("http");
}
this.serviceInstances = serviceInstances;
this.instance = instance;
this.metaInfo = new MetaInfo() {
@Override
public String getAppName() {
return instance.getService();
}
@Override
public String getServerGroup() {
return null;
}
@Override
public String getServiceIdForDiscovery() {
return instance.getService();
}
@Override
public String getInstanceId() {
return instance.getId();
}
};
}
public Instance getInstance() {
return instance;
}
@Override
public MetaInfo getMetaInfo() {
return metaInfo;
}
public Map<String, String> getMetadata() {
return instance.getMetadata();
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (!super.equals(o)) {
return false;
}
PolarisServer that = (PolarisServer) o;
return Objects.equals(instance, that.instance);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), instance);
}
public ServiceInstances getServiceInstances() {
return serviceInstances;
}
}

@ -50,6 +50,10 @@ public class PolarisServiceInstance implements ServiceInstance {
}
}
public Instance getPolarisInstance() {
return instance;
}
@Override
public String getInstanceId() {
return ServiceInstance.super.getInstanceId();

@ -40,8 +40,7 @@ public class ApplicationContextAwareUtils implements ApplicationContextAware {
return applicationContext;
}
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ApplicationContextAwareUtils.applicationContext = applicationContext;
}

@ -74,9 +74,7 @@ public final class JacksonUtils {
return new HashMap<>();
}
catch (JsonProcessingException e) {
LOG.error(
"Json to map failed. check if the format of the json string[{}] is correct.",
jsonStr, e);
LOG.error("Json to map failed. check if the format of the json string[{}] is correct.", jsonStr, e);
throw new RuntimeException("Json to map failed.", e);
}
}

@ -31,8 +31,7 @@ public final class ReflectionUtils {
}
public static Object getFieldValue(Object instance, String fieldName) {
Field field = org.springframework.util.ReflectionUtils
.findField(instance.getClass(), fieldName);
Field field = org.springframework.util.ReflectionUtils.findField(instance.getClass(), fieldName);
field.setAccessible(true);
try {

@ -18,7 +18,6 @@
package com.tencent.cloud.common.metadata.config;
import com.tencent.cloud.common.metadata.filter.gateway.MetadataFirstScgFilter;
import com.tencent.cloud.common.metadata.filter.gateway.MetadataFirstZuulFilter;
import com.tencent.cloud.common.metadata.filter.web.MetadataReactiveFilter;
import com.tencent.cloud.common.metadata.filter.web.MetadataServletFilter;
import com.tencent.cloud.common.metadata.interceptor.feign.MetadataFirstFeignInterceptor;
@ -48,31 +47,21 @@ public class MetadataAutoConfigurationTest {
*/
@Test
public void test1() {
this.applicationContextRunner
.withConfiguration(AutoConfigurations.of(MetadataAutoConfiguration.class))
this.applicationContextRunner.withConfiguration(AutoConfigurations.of(MetadataAutoConfiguration.class))
.run(context -> {
Assertions.assertThat(context).hasSingleBean(MetadataLocalProperties.class);
Assertions.assertThat(context)
.hasSingleBean(MetadataLocalProperties.class);
Assertions.assertThat(context).doesNotHaveBean(
MetadataAutoConfiguration.MetadataServletFilterConfig.class);
.doesNotHaveBean(MetadataAutoConfiguration.MetadataServletFilterConfig.class);
Assertions.assertThat(context).doesNotHaveBean(MetadataServletFilter.class);
Assertions.assertThat(context)
.doesNotHaveBean(MetadataServletFilter.class);
Assertions.assertThat(context).doesNotHaveBean(
MetadataAutoConfiguration.MetadataReactiveFilterConfig.class);
.doesNotHaveBean(MetadataAutoConfiguration.MetadataReactiveFilterConfig.class);
Assertions.assertThat(context).doesNotHaveBean(MetadataReactiveFilter.class);
Assertions.assertThat(context)
.doesNotHaveBean(MetadataReactiveFilter.class);
Assertions.assertThat(context).hasSingleBean(
MetadataAutoConfiguration.MetadataFeignInterceptorConfig.class);
.hasSingleBean(MetadataAutoConfiguration.MetadataFeignInterceptorConfig.class);
Assertions.assertThat(context).hasSingleBean(MetadataFirstFeignInterceptor.class);
Assertions.assertThat(context)
.hasSingleBean(MetadataFirstFeignInterceptor.class);
Assertions.assertThat(context).hasSingleBean(
MetadataAutoConfiguration.MetadataZuulFilterConfig.class);
Assertions.assertThat(context)
.hasSingleBean(MetadataFirstZuulFilter.class);
Assertions.assertThat(context).hasSingleBean(
MetadataAutoConfiguration.MetadataScgFilterConfig.class);
Assertions.assertThat(context)
.hasSingleBean(MetadataFirstScgFilter.class);
.hasSingleBean(MetadataAutoConfiguration.MetadataScgFilterConfig.class);
Assertions.assertThat(context).hasSingleBean(MetadataFirstScgFilter.class);
});
}
@ -81,31 +70,21 @@ public class MetadataAutoConfigurationTest {
*/
@Test
public void test2() {
this.webApplicationContextRunner
.withConfiguration(AutoConfigurations.of(MetadataAutoConfiguration.class))
this.webApplicationContextRunner.withConfiguration(AutoConfigurations.of(MetadataAutoConfiguration.class))
.run(context -> {
Assertions.assertThat(context).hasSingleBean(MetadataLocalProperties.class);
Assertions.assertThat(context)
.hasSingleBean(MetadataLocalProperties.class);
Assertions.assertThat(context).hasSingleBean(
MetadataAutoConfiguration.MetadataServletFilterConfig.class);
Assertions.assertThat(context)
.hasSingleBean(MetadataServletFilter.class);
Assertions.assertThat(context).doesNotHaveBean(
MetadataAutoConfiguration.MetadataReactiveFilterConfig.class);
Assertions.assertThat(context)
.doesNotHaveBean(MetadataReactiveFilter.class);
Assertions.assertThat(context).hasSingleBean(
MetadataAutoConfiguration.MetadataFeignInterceptorConfig.class);
.hasSingleBean(MetadataAutoConfiguration.MetadataServletFilterConfig.class);
Assertions.assertThat(context).hasSingleBean(MetadataServletFilter.class);
Assertions.assertThat(context)
.hasSingleBean(MetadataFirstFeignInterceptor.class);
Assertions.assertThat(context).hasSingleBean(
MetadataAutoConfiguration.MetadataZuulFilterConfig.class);
.doesNotHaveBean(MetadataAutoConfiguration.MetadataReactiveFilterConfig.class);
Assertions.assertThat(context).doesNotHaveBean(MetadataReactiveFilter.class);
Assertions.assertThat(context)
.hasSingleBean(MetadataFirstZuulFilter.class);
Assertions.assertThat(context).hasSingleBean(
MetadataAutoConfiguration.MetadataScgFilterConfig.class);
.hasSingleBean(MetadataAutoConfiguration.MetadataFeignInterceptorConfig.class);
Assertions.assertThat(context).hasSingleBean(MetadataFirstFeignInterceptor.class);
Assertions.assertThat(context)
.hasSingleBean(MetadataFirstScgFilter.class);
.hasSingleBean(MetadataAutoConfiguration.MetadataScgFilterConfig.class);
Assertions.assertThat(context).hasSingleBean(MetadataFirstScgFilter.class);
});
}
@ -115,30 +94,20 @@ public class MetadataAutoConfigurationTest {
@Test
public void test3() {
this.reactiveWebApplicationContextRunner
.withConfiguration(AutoConfigurations.of(MetadataAutoConfiguration.class))
.run(context -> {
Assertions.assertThat(context)
.hasSingleBean(MetadataLocalProperties.class);
Assertions.assertThat(context).doesNotHaveBean(
MetadataAutoConfiguration.MetadataServletFilterConfig.class);
Assertions.assertThat(context)
.doesNotHaveBean(MetadataServletFilter.class);
Assertions.assertThat(context).hasSingleBean(
MetadataAutoConfiguration.MetadataReactiveFilterConfig.class);
.withConfiguration(AutoConfigurations.of(MetadataAutoConfiguration.class)).run(context -> {
Assertions.assertThat(context).hasSingleBean(MetadataLocalProperties.class);
Assertions.assertThat(context)
.hasSingleBean(MetadataReactiveFilter.class);
Assertions.assertThat(context).hasSingleBean(
MetadataAutoConfiguration.MetadataFeignInterceptorConfig.class);
.doesNotHaveBean(MetadataAutoConfiguration.MetadataServletFilterConfig.class);
Assertions.assertThat(context).doesNotHaveBean(MetadataServletFilter.class);
Assertions.assertThat(context)
.hasSingleBean(MetadataFirstFeignInterceptor.class);
Assertions.assertThat(context).hasSingleBean(
MetadataAutoConfiguration.MetadataZuulFilterConfig.class);
.hasSingleBean(MetadataAutoConfiguration.MetadataReactiveFilterConfig.class);
Assertions.assertThat(context).hasSingleBean(MetadataReactiveFilter.class);
Assertions.assertThat(context)
.hasSingleBean(MetadataFirstZuulFilter.class);
Assertions.assertThat(context).hasSingleBean(
MetadataAutoConfiguration.MetadataScgFilterConfig.class);
.hasSingleBean(MetadataAutoConfiguration.MetadataFeignInterceptorConfig.class);
Assertions.assertThat(context).hasSingleBean(MetadataFirstFeignInterceptor.class);
Assertions.assertThat(context)
.hasSingleBean(MetadataFirstScgFilter.class);
.hasSingleBean(MetadataAutoConfiguration.MetadataScgFilterConfig.class);
Assertions.assertThat(context).hasSingleBean(MetadataFirstScgFilter.class);
});
}

@ -42,17 +42,14 @@ public class MetadataLocalPropertiesTest {
@Test
public void test1() {
Assertions.assertThat(metadataLocalProperties.getContent().get("a"))
.isEqualTo("1");
Assertions.assertThat(metadataLocalProperties.getContent().get("b"))
.isEqualTo("2");
Assertions.assertThat(metadataLocalProperties.getContent().get("a")).isEqualTo("1");
Assertions.assertThat(metadataLocalProperties.getContent().get("b")).isEqualTo("2");
Assertions.assertThat(metadataLocalProperties.getContent().get("c")).isNull();
}
@Test
public void test2() {
Assertions.assertThat(metadataLocalProperties.getTransitive().contains("b"))
.isTrue();
Assertions.assertThat(metadataLocalProperties.getTransitive().contains("b")).isTrue();
}
@SpringBootApplication

@ -41,8 +41,7 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
* @author Haotian Zhang
*/
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = MOCK,
classes = MetadataServletFilterTest.TestApplication.class,
@SpringBootTest(webEnvironment = MOCK, classes = MetadataServletFilterTest.TestApplication.class,
properties = { "spring.config.location = classpath:application-test.yml" })
public class MetadataReactiveFilterTest {
@ -69,15 +68,12 @@ public class MetadataReactiveFilterTest {
// Mock request
MockServerHttpRequest request = MockServerHttpRequest.get("test")
.header(MetadataConstant.HeaderName.CUSTOM_METADATA, "{\"c\": \"3\"}")
.build();
.header(MetadataConstant.HeaderName.CUSTOM_METADATA, "{\"c\": \"3\"}").build();
ServerWebExchange exchange = MockServerWebExchange.from(request);
metadataReactiveFilter.filter(exchange, webFilterChain);
Assertions.assertThat(metadataLocalProperties.getContent().get("a"))
.isEqualTo("1");
Assertions.assertThat(metadataLocalProperties.getContent().get("b"))
.isEqualTo("2");
Assertions.assertThat(metadataLocalProperties.getContent().get("a")).isEqualTo("1");
Assertions.assertThat(metadataLocalProperties.getContent().get("b")).isEqualTo("2");
Assertions.assertThat(metadataLocalProperties.getContent().get("c")).isNull();
}

@ -43,8 +43,7 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
* @author Haotian Zhang
*/
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = RANDOM_PORT,
classes = MetadataServletFilterTest.TestApplication.class,
@SpringBootTest(webEnvironment = RANDOM_PORT, classes = MetadataServletFilterTest.TestApplication.class,
properties = { "spring.config.location = classpath:application-test.yml" })
public class MetadataServletFilterTest {
@ -66,10 +65,8 @@ public class MetadataServletFilterTest {
request.addHeader(MetadataConstant.HeaderName.CUSTOM_METADATA, "{\"c\": \"3\"}");
MockHttpServletResponse response = new MockHttpServletResponse();
metadataServletFilter.doFilter(request, response, filterChain);
Assertions.assertThat(metadataLocalProperties.getContent().get("a"))
.isEqualTo("1");
Assertions.assertThat(metadataLocalProperties.getContent().get("b"))
.isEqualTo("2");
Assertions.assertThat(metadataLocalProperties.getContent().get("a")).isEqualTo("1");
Assertions.assertThat(metadataLocalProperties.getContent().get("b")).isEqualTo("2");
Assertions.assertThat(metadataLocalProperties.getContent().get("c")).isNull();
}

@ -4,7 +4,6 @@ spring:
autoconfigure:
exclude:
- org.springframework.cloud.gateway.config.GatewayAutoConfiguration
- org.springframework.cloud.netflix.zuul.ZuulServerAutoConfiguration
cloud:
tencent:
metadata:

@ -1,93 +1,93 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies-parent</artifactId>
<version>2.3.1.RELEASE</version>
<relativePath/>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-dependencies</artifactId>
<version>${revision}</version>
<packaging>pom</packaging>
<name>Spring Cloud Tencent Dependencies</name>
<description>Spring Cloud Tencent Dependencies</description>
<url>https://github.com/Tencent/spring-cloud-tencent/tree/main</url>
<organization>
<name>Tencent</name>
<url>https://opensource.tencent.com/</url>
</organization>
<licenses>
<license>
<name>The BSD 3-Clause License (BSD3)</name>
<url>https://raw.githubusercontent.com/Tencent/spring-cloud-tencent/main/LICENSE</url>
<distribution>repo</distribution>
</license>
</licenses>
<scm>
<url>https://github.com/Tencent/spring-cloud-tencent</url>
<connection>scm:git:git@github.com:Tencent/spring-cloud-tencent.git</connection>
<developerConnection>scm:git:git@github.com:Tencent/spring-cloud-tencent.git</developerConnection>
</scm>
<developers>
<developer>
<id>SkyeBeFreeman</id>
<name>Haotian Zhang</name>
<email>928016560@qq.com</email>
<organization>Tencent</organization>
<url>https://github.com/SkyeBeFreeman/</url>
</developer>
<developer>
<name>Andrew Shan</name>
<email>samshan08@126.com</email>
<organization>Tencent</organization>
</developer>
<developer>
<id>xiaoyao1999hn</id>
<name>Jie Cheng</name>
<email>348893717@qq.com</email>
<organization>Tencent</organization>
<url>https://github.com/xiaoyao1999hn/</url>
</developer>
</developers>
<properties>
<revision>1.2.0-Hoxton.SR9-SNAPSHOT</revision>
<polaris.version>1.3.0</polaris.version>
<powermock.version>2.0.0</powermock.version>
<!-- Maven Plugin Versions -->
<maven-source-plugin.version>3.2.0</maven-source-plugin.version>
<maven-javadoc-plugin.version>3.1.1</maven-javadoc-plugin.version>
<flatten-maven-plugin.version>1.2.7</flatten-maven-plugin.version>
<maven-gpg-plugin.version>1.6</maven-gpg-plugin.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<artifactId>polaris-dependencies</artifactId>
<groupId>com.tencent.polaris</groupId>
<version>${polaris.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-commons</artifactId>
<version>${revision}</version>
</dependency>
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies-parent</artifactId>
<version>3.0.4</version>
<relativePath/>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-dependencies</artifactId>
<version>${revision}</version>
<packaging>pom</packaging>
<name>Spring Cloud Tencent Dependencies</name>
<description>Spring Cloud Tencent Dependencies</description>
<url>https://github.com/Tencent/spring-cloud-tencent/tree/main</url>
<organization>
<name>Tencent</name>
<url>https://opensource.tencent.com/</url>
</organization>
<licenses>
<license>
<name>The BSD 3-Clause License (BSD3)</name>
<url>https://raw.githubusercontent.com/Tencent/spring-cloud-tencent/main/LICENSE</url>
<distribution>repo</distribution>
</license>
</licenses>
<scm>
<url>https://github.com/Tencent/spring-cloud-tencent</url>
<connection>scm:git:git@github.com:Tencent/spring-cloud-tencent.git</connection>
<developerConnection>scm:git:git@github.com:Tencent/spring-cloud-tencent.git</developerConnection>
</scm>
<developers>
<developer>
<id>SkyeBeFreeman</id>
<name>Haotian Zhang</name>
<email>928016560@qq.com</email>
<organization>Tencent</organization>
<url>https://github.com/SkyeBeFreeman/</url>
</developer>
<developer>
<name>Andrew Shan</name>
<email>samshan08@126.com</email>
<organization>Tencent</organization>
</developer>
<developer>
<id>xiaoyao1999hn</id>
<name>Jie Cheng</name>
<email>348893717@qq.com</email>
<organization>Tencent</organization>
<url>https://github.com/xiaoyao1999hn/</url>
</developer>
</developers>
<properties>
<revision>1.2.0-2020.0.5-SNAPSHOT</revision>
<polaris.version>1.3.1</polaris.version>
<powermock.version>2.0.0</powermock.version>
<!-- Maven Plugin Versions -->
<maven-source-plugin.version>3.2.0</maven-source-plugin.version>
<maven-javadoc-plugin.version>3.1.1</maven-javadoc-plugin.version>
<flatten-maven-plugin.version>1.2.7</flatten-maven-plugin.version>
<maven-gpg-plugin.version>1.6</maven-gpg-plugin.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<artifactId>polaris-dependencies</artifactId>
<groupId>com.tencent.polaris</groupId>
<version>${polaris.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-commons</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
@ -101,24 +101,24 @@
<version>${revision}</version>
</dependency>
<!-- polaris starter-->
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-ratelimit</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-circuitbreaker</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-router</artifactId>
<version>${revision}</version>
</dependency>
<!-- polaris starter-->
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-ratelimit</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-circuitbreaker</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-router</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
@ -126,116 +126,116 @@
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-discovery</artifactId>
<version>${revision}</version>
</dependency>
<!-- powermock-module-junit4 -->
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>${powermock.version}</version>
</dependency>
<!-- powermock-api-mockito -->
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>${powermock.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>flatten-maven-plugin</artifactId>
<version>${flatten-maven-plugin.version}</version>
<configuration>
<updatePomFile>true</updatePomFile>
<flattenMode>resolveCiFriendliesOnly</flattenMode>
</configuration>
<executions>
<execution>
<id>flatten</id>
<phase>process-resources</phase>
<goals>
<goal>flatten</goal>
</goals>
</execution>
<execution>
<id>flatten.clean</id>
<phase>clean</phase>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>release</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>${maven-source-plugin.version}</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>${maven-gpg-plugin.version}</version>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<distributionManagement>
<snapshotRepository>
<id>nexus-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</snapshotRepository>
<repository>
<id>nexus-releases</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
</profile>
</profiles>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-discovery</artifactId>
<version>${revision}</version>
</dependency>
<!-- powermock-module-junit4 -->
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>${powermock.version}</version>
</dependency>
<!-- powermock-api-mockito -->
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>${powermock.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>flatten-maven-plugin</artifactId>
<version>${flatten-maven-plugin.version}</version>
<configuration>
<updatePomFile>true</updatePomFile>
<flattenMode>resolveCiFriendliesOnly</flattenMode>
</configuration>
<executions>
<execution>
<id>flatten</id>
<phase>process-resources</phase>
<goals>
<goal>flatten</goal>
</goals>
</execution>
<execution>
<id>flatten.clean</id>
<phase>clean</phase>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>release</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>${maven-source-plugin.version}</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>${maven-gpg-plugin.version}</version>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<distributionManagement>
<snapshotRepository>
<id>nexus-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</snapshotRepository>
<repository>
<id>nexus-releases</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
</profile>
</profiles>
</project>

@ -31,7 +31,7 @@
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
</dependencies>

@ -25,8 +25,7 @@ import org.springframework.web.bind.annotation.GetMapping;
*
* @author Haotian Zhang
*/
@FeignClient(name = "polaris-circuitbreaker-example-b",
fallback = ProviderBFallback.class)
@FeignClient(name = "polaris-circuitbreaker-example-b", fallback = ProviderBFallback.class)
public interface ProviderB {
/**

@ -54,9 +54,8 @@ public class ServiceAController {
*/
@GetMapping("/testRest")
public String testRest() {
ResponseEntity<String> entity = restTemplate.getForEntity(
"http://polaris-circuitbreaker-example-b/example/service/b/info",
String.class);
ResponseEntity<String> entity = restTemplate
.getForEntity("http://polaris-circuitbreaker-example-b/example/service/b/info", String.class);
return entity.getBody();
}

@ -8,7 +8,7 @@ spring:
address: grpc://127.0.0.1:8091
namespace: default
feign:
hystrix:
circuitbreaker:
enabled: true
compression:
request:
@ -17,16 +17,6 @@ feign:
min-request-size: 2048
response:
enabled: false
ribbon:
polaris:
enabled: true
MaxAutoRetries: 1
MaxAutoRetriesNextServer: 2
OkToRetryOnAllOperations: false
ConnectionTimeout: 1000
ReadTimeout: 1000
eager-load:
enabled: on
serivceB:
url: http://localhost:48081

@ -28,6 +28,11 @@
<!-- <groupId>org.springframework.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>-->
<!-- </dependency>-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
</dependencies>
<build>
<plugins>

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

Loading…
Cancel
Save