diff --git a/CHANGELOG.md b/CHANGELOG.md
index 41f979111..0fd331294 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,7 +1,7 @@
# Change Log
---
-- [Feature: Support custom rate limit reject response info](https://github.com/Tencent/spring-cloud-tencent/pull/128)
-- [Feature: Optimize config server address](https://github.com/Tencent/spring-cloud-tencent/pull/130)
-- [Feature: Remove spring-javaformat-maven-plugin](https://github.com/Tencent/spring-cloud-tencent/pull/131)
-- [feat:refactor loadbalancer module as a basic module for router and circuit breaker.](https://github.com/Tencent/spring-cloud-tencent/pull/136)
+
+- [Feature: Support parse ratelimit rule expression labels.](https://github.com/Tencent/spring-cloud-tencent/pull/183)
+- [Feature: Router support request label.](https://github.com/Tencent/spring-cloud-tencent/pull/165)
+- [Feature: Support router expression label](https://github.com/Tencent/spring-cloud-tencent/pull/190)
diff --git a/README-zh.md b/README-zh.md
index ff760c7d5..2f42d8720 100644
--- a/README-zh.md
+++ b/README-zh.md
@@ -12,7 +12,7 @@
## 介绍
-Spring Cloud Tencent 是腾讯开发和维护的一站式微服务解决方案。
+Spring Cloud Tencent 是腾讯开源的一站式微服务解决方案。
Spring Cloud Tencent 实现了Spring Cloud 标准微服务 SPI,开发者可以基于 Spring Cloud Tencent 快速开发 Spring Cloud 云原生分布式应用。
@@ -80,6 +80,13 @@ Spring Cloud Tencent 所有组件都已上传到 Maven 中央仓库,只需要
- [项目概览](https://github.com/Tencent/spring-cloud-tencent/wiki/%E9%A1%B9%E7%9B%AE%E6%A6%82%E8%A7%88)
- [参与共建](https://github.com/Tencent/spring-cloud-tencent/wiki/Contributing)
+## 交流群
+
+扫描下面的二维码加入 Spring Cloud Tencent 交流群。
+
+
+
+
## License
The spring-cloud-tencent is licensed under the BSD 3-Clause License. Copyright and license information can be found in the file [LICENSE](LICENSE)
diff --git a/README.md b/README.md
index e7b735c3a..b6226bb07 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@ English | [简体中文](./README-zh.md)
## Introduction
-Spring Cloud Tencent is a one-stop microservice solution developed and maintained by Tencent.
+Spring Cloud Tencent is a open source one-stop microservice solution from Tencent.
Spring Cloud Tencent implements the Spring Cloud standard microservice SPI, so developers can quickly develop Spring Cloud cloud-native distributed applications based on Spring Cloud Tencent.
@@ -78,6 +78,12 @@ For example:
- [Project Structure Overview](https://github.com/Tencent/spring-cloud-tencent/wiki/%E9%A1%B9%E7%9B%AE%E6%A6%82%E8%A7%88)
- [Participate in co-construction](https://github.com/Tencent/spring-cloud-tencent/wiki/Contributing)
+## Chat Group
+
+Please scan the QR code to join the chat group.
+
+
+
## License
The spring-cloud-tencent is licensed under the BSD 3-Clause License. Copyright and license information can be found in the file [LICENSE](LICENSE)
diff --git a/changes/changes-1.4.0.md b/changes/changes-1.4.0.md
new file mode 100644
index 000000000..2784188a0
--- /dev/null
+++ b/changes/changes-1.4.0.md
@@ -0,0 +1,8 @@
+# Change Log
+---
+
+- [Feature: Support custom rate limit reject response info](https://github.com/Tencent/spring-cloud-tencent/pull/128)
+- [Feature: Optimize config server address](https://github.com/Tencent/spring-cloud-tencent/pull/130)
+- [Feature: Remove spring-javaformat-maven-plugin](https://github.com/Tencent/spring-cloud-tencent/pull/131)
+- [feat:refactor loadbalancer module as a basic module for router and circuit breaker.](https://github.com/Tencent/spring-cloud-tencent/pull/136)
+- [feat:enable distribute rate limit](https://github.com/Tencent/spring-cloud-tencent/pull/139)
\ No newline at end of file
diff --git a/changes/changes-1.4.2.md b/changes/changes-1.4.2.md
new file mode 100644
index 000000000..af06c3331
--- /dev/null
+++ b/changes/changes-1.4.2.md
@@ -0,0 +1,5 @@
+# Change Log
+---
+
+- [fix:fix routes of gateway doesn't refresh bug.](https://github.com/Tencent/spring-cloud-tencent/pull/158)
+- [fix:Turn off automatic injection of Polars rule.](https://github.com/Tencent/spring-cloud-tencent/pull/162)
diff --git a/changes/changes-1.4.3.md b/changes/changes-1.4.3.md
new file mode 100644
index 000000000..c8e3ed71d
--- /dev/null
+++ b/changes/changes-1.4.3.md
@@ -0,0 +1,5 @@
+# Change Log
+---
+
+- [fix:fix wrong context data storage.](https://github.com/Tencent/spring-cloud-tencent/pull/170)
+- [fix:fix route not refreshing bug when first instance of one service up.](https://github.com/Tencent/spring-cloud-tencent/pull/174)
diff --git a/changes/changes-1.4.4.md b/changes/changes-1.4.4.md
new file mode 100644
index 000000000..1aa0ff740
--- /dev/null
+++ b/changes/changes-1.4.4.md
@@ -0,0 +1,4 @@
+# Change Log
+---
+
+- [fix:fix wrong isAliveFlag config when creating new PolarisServer.](https://github.com/Tencent/spring-cloud-tencent/pull/179)
diff --git a/pom.xml b/pom.xml
index e3346026b..b7489edde 100644
--- a/pom.xml
+++ b/pom.xml
@@ -86,7 +86,7 @@
- 1.4.0-Hoxton.SR9-SNAPSHOT
+ 1.5.0-Hoxton.SR9-SNAPSHOT
Hoxton.SR9
diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/DecodeTransferMetadataReactiveFilter.java b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/DecodeTransferMetadataReactiveFilter.java
index aac449fac..2dea4fd66 100644
--- a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/DecodeTransferMetadataReactiveFilter.java
+++ b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/DecodeTransferMetadataReactiveFilter.java
@@ -75,7 +75,7 @@ public class DecodeTransferMetadataReactiveFilter implements WebFilter, Ordered
Map upstreamCustomMetadataMap = JacksonUtils
.deserialize2Map(customMetadataStr);
- MetadataContextHolder.init(upstreamCustomMetadataMap, null);
+ MetadataContextHolder.init(upstreamCustomMetadataMap);
// Save to ServerWebExchange.
serverWebExchange.getAttributes().put(
diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/DecodeTransferMetadataServletFilter.java b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/DecodeTransferMetadataServletFilter.java
index da1261f65..23934edec 100644
--- a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/DecodeTransferMetadataServletFilter.java
+++ b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/DecodeTransferMetadataServletFilter.java
@@ -72,7 +72,7 @@ public class DecodeTransferMetadataServletFilter extends OncePerRequestFilter {
.deserialize2Map(customMetadataStr);
try {
- MetadataContextHolder.init(upstreamCustomMetadataMap, null);
+ MetadataContextHolder.init(upstreamCustomMetadataMap);
filterChain.doFilter(httpServletRequest, httpServletResponse);
}
diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataFeignInterceptor.java b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataFeignInterceptor.java
index 711d5b947..2e6e78d24 100644
--- a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataFeignInterceptor.java
+++ b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataFeignInterceptor.java
@@ -65,14 +65,13 @@ public class EncodeTransferMedataFeignInterceptor implements RequestInterceptor,
Map headerMetadataMap = JacksonUtils
.deserialize2Map(headerMetadataStr);
for (String key : headerMetadataMap.keySet()) {
- metadataContext.putTransitiveCustomMetadata(key,
- headerMetadataMap.get(key));
+ metadataContext.putContext(MetadataContext.FRAGMENT_TRANSITIVE, key, headerMetadataMap.get(key));
}
}
}
- Map customMetadata = metadataContext
- .getAllTransitiveCustomMetadata();
+ Map customMetadata = metadataContext.getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE);
+
if (!CollectionUtils.isEmpty(customMetadata)) {
String metadataStr = JacksonUtils.serialize2Json(customMetadata);
requestTemplate.removeHeader(CUSTOM_METADATA);
diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataRestTemplateInterceptor.java b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataRestTemplateInterceptor.java
index 47709ba6c..c97ddb9d8 100644
--- a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataRestTemplateInterceptor.java
+++ b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataRestTemplateInterceptor.java
@@ -63,12 +63,10 @@ public class EncodeTransferMedataRestTemplateInterceptor
Map headerMetadataMap = JacksonUtils
.deserialize2Map(metadataStr);
for (String key : headerMetadataMap.keySet()) {
- metadataContext.putTransitiveCustomMetadata(key,
- headerMetadataMap.get(key));
+ metadataContext.putContext(MetadataContext.FRAGMENT_TRANSITIVE, key, headerMetadataMap.get(key));
}
}
- Map customMetadata = metadataContext
- .getAllTransitiveCustomMetadata();
+ Map customMetadata = metadataContext.getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE);
if (!CollectionUtils.isEmpty(customMetadata)) {
metadataStr = JacksonUtils.serialize2Json(customMetadata);
try {
diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataScgFilter.java b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataScgFilter.java
index 6c5937bce..200a83743 100644
--- a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataScgFilter.java
+++ b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataScgFilter.java
@@ -65,8 +65,7 @@ public class EncodeTransferMedataScgFilter implements GlobalFilter, Ordered {
if (metadataContext == null) {
metadataContext = MetadataContextHolder.get();
}
- Map customMetadata = metadataContext
- .getAllTransitiveCustomMetadata();
+ Map customMetadata = metadataContext.getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE);
if (!CollectionUtils.isEmpty(customMetadata)) {
String metadataStr = JacksonUtils.serialize2Json(customMetadata);
try {
diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMetadataZuulFilter.java b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMetadataZuulFilter.java
index 3fac6f6d7..cf192e955 100644
--- a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMetadataZuulFilter.java
+++ b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMetadataZuulFilter.java
@@ -65,8 +65,7 @@ public class EncodeTransferMetadataZuulFilter extends ZuulFilter {
MetadataContext metadataContext = MetadataContextHolder.get();
// add new metadata and cover old
- Map customMetadata = metadataContext
- .getAllTransitiveCustomMetadata();
+ Map customMetadata = metadataContext.getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE);
if (!CollectionUtils.isEmpty(customMetadata)) {
String metadataStr = JacksonUtils.serialize2Json(customMetadata);
try {
diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/config/MetadataTransferAutoConfigurationTest.java b/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/config/MetadataTransferAutoConfigurationTest.java
index a3d924158..87968b8b3 100644
--- a/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/config/MetadataTransferAutoConfigurationTest.java
+++ b/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/config/MetadataTransferAutoConfigurationTest.java
@@ -29,7 +29,7 @@ import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.cloud.gateway.filter.GlobalFilter;
/**
- * Test for {@link MetadataTransferAutoConfiguration}
+ * Test for {@link MetadataTransferAutoConfiguration}.
*
* @author Haotian Zhang
*/
diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/intercepter/EncodeTransferMedataFeignInterceptorTest.java b/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/intercepter/EncodeTransferMedataFeignInterceptorTest.java
index 21426f565..7d7811420 100644
--- a/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/intercepter/EncodeTransferMedataFeignInterceptorTest.java
+++ b/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/intercepter/EncodeTransferMedataFeignInterceptorTest.java
@@ -22,9 +22,9 @@ import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
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.metadata.config.MetadataLocalProperties;
-import com.tencent.cloud.common.util.JacksonUtils;
import com.tencent.cloud.metadata.core.EncodeTransferMedataFeignInterceptor;
import feign.RequestInterceptor;
import feign.RequestTemplate;
@@ -46,15 +46,15 @@ import org.springframework.web.bind.annotation.RestController;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.DEFINED_PORT;
/**
- * Test for {@link EncodeTransferMedataFeignInterceptor}
+ * Test for {@link EncodeTransferMedataFeignInterceptor}.
*
* @author Haotian Zhang
*/
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = DEFINED_PORT,
classes = EncodeTransferMedataFeignInterceptorTest.TestApplication.class,
- properties = { "server.port=8081",
- "spring.config.location = classpath:application-test.yml" })
+ properties = {"server.port=8081",
+ "spring.config.location = classpath:application-test.yml"})
public class EncodeTransferMedataFeignInterceptorTest {
@Autowired
@@ -67,19 +67,19 @@ public class EncodeTransferMedataFeignInterceptorTest {
public void test1() {
String metadata = testFeign.test();
Assertions.assertThat(metadata)
- .isEqualTo("{\"a\":\"11\",\"b\":\"22\",\"c\":\"33\"}{}");
+ .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"))
+ .assertThat(MetadataContextHolder.get().getContext(MetadataContext.FRAGMENT_TRANSITIVE, "a"))
.isEqualTo("11");
Assertions
- .assertThat(MetadataContextHolder.get().getTransitiveCustomMetadata("b"))
+ .assertThat(MetadataContextHolder.get().getContext(MetadataContext.FRAGMENT_TRANSITIVE, "b"))
.isEqualTo("22");
Assertions
- .assertThat(MetadataContextHolder.get().getTransitiveCustomMetadata("c"))
+ .assertThat(MetadataContextHolder.get().getContext(MetadataContext.FRAGMENT_TRANSITIVE, "c"))
.isEqualTo("33");
}
@@ -92,17 +92,15 @@ public class EncodeTransferMedataFeignInterceptorTest {
public String test(
@RequestHeader(MetadataConstant.HeaderName.CUSTOM_METADATA) String customMetadataStr)
throws UnsupportedEncodingException {
- String systemMetadataStr = JacksonUtils
- .serialize2Json(MetadataContextHolder.get().getAllSystemMetadata());
- return URLDecoder.decode(customMetadataStr, "UTF-8") + systemMetadataStr;
+ return URLDecoder.decode(customMetadataStr, "UTF-8");
}
@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\"}" })
+ headers = {MetadataConstant.HeaderName.CUSTOM_METADATA
+ + "={\"a\":\"11" + "\",\"b\":\"22\",\"c\":\"33\"}"})
String test();
}
diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/intercepter/EncodeTransferMedataRestTemplateInterceptorTest.java b/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/intercepter/EncodeTransferMedataRestTemplateInterceptorTest.java
index 6a7f98b25..26f1bc395 100644
--- a/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/intercepter/EncodeTransferMedataRestTemplateInterceptorTest.java
+++ b/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/intercepter/EncodeTransferMedataRestTemplateInterceptorTest.java
@@ -22,9 +22,9 @@ import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
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.metadata.config.MetadataLocalProperties;
-import com.tencent.cloud.common.util.JacksonUtils;
import com.tencent.cloud.metadata.core.EncodeTransferMedataRestTemplateInterceptor;
import org.assertj.core.api.Assertions;
import org.junit.Test;
@@ -47,7 +47,7 @@ import org.springframework.web.client.RestTemplate;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
/**
- * Test for {@link EncodeTransferMedataRestTemplateInterceptor}
+ * Test for {@link EncodeTransferMedataRestTemplateInterceptor}.
*
* @author Haotian Zhang
*/
@@ -77,19 +77,19 @@ public class EncodeTransferMedataRestTemplateInterceptorTest {
httpEntity, String.class)
.getBody();
Assertions.assertThat(metadata)
- .isEqualTo("{\"a\":\"11\",\"b\":\"22\",\"c\":\"33\"}{}");
+ .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"))
+ .assertThat(MetadataContextHolder.get().getContext(MetadataContext.FRAGMENT_TRANSITIVE, "a"))
.isEqualTo("11");
Assertions
- .assertThat(MetadataContextHolder.get().getTransitiveCustomMetadata("b"))
+ .assertThat(MetadataContextHolder.get().getContext(MetadataContext.FRAGMENT_TRANSITIVE, "b"))
.isEqualTo("22");
Assertions
- .assertThat(MetadataContextHolder.get().getTransitiveCustomMetadata("c"))
+ .assertThat(MetadataContextHolder.get().getContext(MetadataContext.FRAGMENT_TRANSITIVE, "c"))
.isEqualTo("33");
}
@@ -106,9 +106,7 @@ public class EncodeTransferMedataRestTemplateInterceptorTest {
public String test(
@RequestHeader(MetadataConstant.HeaderName.CUSTOM_METADATA) String customMetadataStr)
throws UnsupportedEncodingException {
- String systemMetadataStr = JacksonUtils
- .serialize2Json(MetadataContextHolder.get().getAllSystemMetadata());
- return URLDecoder.decode(customMetadataStr, "UTF-8") + systemMetadataStr;
+ return URLDecoder.decode(customMetadataStr, "UTF-8");
}
}
diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisFeignClient.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisFeignClient.java
index bb061b3b7..54ab9a53e 100644
--- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisFeignClient.java
+++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisFeignClient.java
@@ -13,6 +13,7 @@
* 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;
@@ -20,9 +21,7 @@ package com.tencent.cloud.polaris.circuitbreaker.feign;
import java.io.IOException;
import java.net.URI;
-import com.tencent.cloud.common.constant.MetadataConstant.SystemMetadataKey;
import com.tencent.cloud.common.metadata.MetadataContext;
-import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.polaris.api.core.ConsumerAPI;
import com.tencent.polaris.api.pojo.RetStatus;
import com.tencent.polaris.api.pojo.ServiceKey;
@@ -32,6 +31,8 @@ import feign.Request;
import feign.Request.Options;
import feign.Response;
import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import static feign.Util.checkNotNull;
@@ -42,6 +43,9 @@ import static feign.Util.checkNotNull;
*/
public class PolarisFeignClient implements Client {
+
+ private static final Logger LOG = LoggerFactory.getLogger(PolarisFeignClient.class);
+
private final Client delegate;
private final ConsumerAPI consumerAPI;
@@ -64,6 +68,7 @@ public class PolarisFeignClient implements Client {
}
catch (IOException origin) {
resultRequest.setRetStatus(RetStatus.RetFail);
+
throw origin;
}
finally {
@@ -74,24 +79,17 @@ public class PolarisFeignClient implements Client {
private ServiceCallResult createServiceCallResult(final Request request) {
ServiceCallResult resultRequest = new ServiceCallResult();
- MetadataContext metadataContext = MetadataContextHolder.get();
- String namespace = metadataContext
- .getSystemMetadata(SystemMetadataKey.PEER_NAMESPACE);
- resultRequest.setNamespace(namespace);
- String serviceName = metadataContext
- .getSystemMetadata(SystemMetadataKey.PEER_SERVICE);
+ resultRequest.setNamespace(MetadataContext.LOCAL_NAMESPACE);
+ String serviceName = request.requestTemplate().feignTarget().name();
resultRequest.setService(serviceName);
- String method = metadataContext.getSystemMetadata(SystemMetadataKey.PEER_PATH);
- resultRequest.setMethod(method);
+ URI uri = URI.create(request.url());
+ resultRequest.setMethod(uri.getPath());
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());
resultRequest.setPort(uri.getPort());
diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/feign/TestPolarisFeignApp.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/feign/TestPolarisFeignApp.java
index b593392d5..b6dfb10b2 100644
--- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/feign/TestPolarisFeignApp.java
+++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/feign/TestPolarisFeignApp.java
@@ -43,6 +43,8 @@ public class TestPolarisFeignApp {
/**
* Get info of service B.
+ *
+ * @return info
*/
@GetMapping("/example/service/b/info")
String info();
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/DiscoveryConfigModifier.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/DiscoveryConfigModifier.java
index a52a6dd4b..67690ef24 100644
--- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/DiscoveryConfigModifier.java
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/DiscoveryConfigModifier.java
@@ -24,6 +24,8 @@ import com.tencent.polaris.api.config.consumer.ServiceRouterConfig;
import com.tencent.polaris.factory.config.ConfigurationImpl;
import com.tencent.polaris.plugins.router.healthy.RecoverRouterConfig;
+import org.springframework.beans.factory.annotation.Autowired;
+
/**
* Spring Cloud Tencent config Override polaris config.
*
@@ -31,6 +33,9 @@ import com.tencent.polaris.plugins.router.healthy.RecoverRouterConfig;
*/
public class DiscoveryConfigModifier implements PolarisConfigModifier {
+ @Autowired
+ private PolarisDiscoveryProperties polarisDiscoveryProperties;
+
@Override
public void modify(ConfigurationImpl configuration) {
// Set excludeCircuitBreakInstances to false
@@ -41,6 +46,10 @@ public class DiscoveryConfigModifier implements PolarisConfigModifier {
// Update modified config to source properties
configuration.getConsumer().getServiceRouter()
.setPluginConfig(ServiceRouterConfig.DEFAULT_ROUTER_RECOVER, recoverRouterConfig);
+
+ // Set ServiceRefreshInterval
+ configuration.getConsumer().getLocalCache()
+ .setServiceListRefreshInterval(polarisDiscoveryProperties.getServiceListRefreshInterval());
}
@Override
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/PolarisDiscoveryProperties.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/PolarisDiscoveryProperties.java
index 37b0ad45f..77483b360 100644
--- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/PolarisDiscoveryProperties.java
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/PolarisDiscoveryProperties.java
@@ -105,6 +105,11 @@ public class PolarisDiscoveryProperties {
@Value("${spring.cloud.polaris.discovery.health-check-url:}")
private String healthCheckUrl;
+ /**
+ * Millis interval of refresh of service info list. Default: 60000.
+ */
+ private Long serviceListRefreshInterval = 60000L;
+
@Autowired
private Environment environment;
@@ -218,6 +223,14 @@ public class PolarisDiscoveryProperties {
this.healthCheckUrl = healthCheckUrl;
}
+ public Long getServiceListRefreshInterval() {
+ return serviceListRefreshInterval;
+ }
+
+ public void setServiceListRefreshInterval(Long serviceListRefreshInterval) {
+ this.serviceListRefreshInterval = serviceListRefreshInterval;
+ }
+
@Override
public String toString() {
return "PolarisProperties{" + "token='" + token + '\'' + ", namespace='"
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/PolarisDiscoveryAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/PolarisDiscoveryAutoConfiguration.java
index 139f72508..cc8000f44 100644
--- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/PolarisDiscoveryAutoConfiguration.java
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/PolarisDiscoveryAutoConfiguration.java
@@ -19,6 +19,7 @@
package com.tencent.cloud.polaris.discovery;
import com.tencent.cloud.polaris.discovery.reactive.PolarisReactiveDiscoveryClientConfiguration;
+import com.tencent.cloud.polaris.discovery.refresh.PolarisRefreshConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
@@ -32,8 +33,8 @@ import org.springframework.context.annotation.Import;
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnPolarisDiscoveryEnabled
-@Import({ PolarisDiscoveryClientConfiguration.class,
- PolarisReactiveDiscoveryClientConfiguration.class })
+@Import({PolarisDiscoveryClientConfiguration.class,
+ PolarisReactiveDiscoveryClientConfiguration.class, PolarisRefreshConfiguration.class})
public class PolarisDiscoveryAutoConfiguration {
@Bean
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/PolarisDiscoveryHandler.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/PolarisDiscoveryHandler.java
index 951c99f76..bd64f463b 100644
--- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/PolarisDiscoveryHandler.java
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/PolarisDiscoveryHandler.java
@@ -20,7 +20,6 @@ package com.tencent.cloud.polaris.discovery;
import java.util.Map;
-import com.tencent.cloud.common.constant.MetadataConstant.SystemMetadataKey;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.polaris.PolarisDiscoveryProperties;
@@ -33,6 +32,7 @@ import com.tencent.polaris.api.rpc.GetInstancesRequest;
import com.tencent.polaris.api.rpc.GetServicesRequest;
import com.tencent.polaris.api.rpc.InstancesResponse;
import com.tencent.polaris.api.rpc.ServicesResponse;
+import com.tencent.polaris.client.api.SDKContext;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
@@ -52,6 +52,9 @@ public class PolarisDiscoveryHandler {
@Autowired
private ProviderAPI providerAPI;
+ @Autowired
+ private SDKContext sdkContext;
+
@Autowired
private ConsumerAPI polarisConsumer;
@@ -66,13 +69,10 @@ public class PolarisDiscoveryHandler {
GetInstancesRequest getInstancesRequest = new GetInstancesRequest();
getInstancesRequest.setNamespace(namespace);
getInstancesRequest.setService(service);
- String method = MetadataContextHolder.get()
- .getSystemMetadata(SystemMetadataKey.PEER_PATH);
- getInstancesRequest.setMethod(method);
String localNamespace = MetadataContext.LOCAL_NAMESPACE;
String localService = MetadataContext.LOCAL_SERVICE;
- Map allTransitiveCustomMetadata = MetadataContextHolder.get()
- .getAllTransitiveCustomMetadata();
+ Map allTransitiveCustomMetadata = MetadataContextHolder.get().
+ getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE);
if (StringUtils.isNotBlank(localNamespace) || StringUtils.isNotBlank(localService)
|| null != allTransitiveCustomMetadata) {
ServiceInfo sourceService = new ServiceInfo();
@@ -114,6 +114,10 @@ public class PolarisDiscoveryHandler {
return providerAPI;
}
+ public SDKContext getSdkContext() {
+ return sdkContext;
+ }
+
/**
* Return all service for given namespace.
* @return service list
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/PolarisRefreshApplicationReadyEventListener.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/PolarisRefreshApplicationReadyEventListener.java
new file mode 100644
index 000000000..d80accc57
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/PolarisRefreshApplicationReadyEventListener.java
@@ -0,0 +1,86 @@
+/*
+ * Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
+ *
+ * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+package com.tencent.cloud.polaris.discovery.refresh;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import com.tencent.cloud.polaris.discovery.PolarisDiscoveryHandler;
+import com.tencent.polaris.client.util.NamedThreadFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.springframework.boot.context.event.ApplicationReadyEvent;
+import org.springframework.cloud.client.discovery.event.HeartbeatEvent;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.context.ApplicationEventPublisherAware;
+import org.springframework.context.ApplicationListener;
+
+import static com.tencent.cloud.polaris.discovery.refresh.PolarisServiceStatusChangeListener.INDEX;
+
+/**
+ * Begin refresh when application is ready.
+ *
+ * @author Haotian Zhang
+ */
+public class PolarisRefreshApplicationReadyEventListener implements ApplicationListener, ApplicationEventPublisherAware {
+
+ private static final Logger LOG = LoggerFactory.getLogger(PolarisRefreshConfiguration.class);
+ private static final int DELAY = 60;
+ private final PolarisDiscoveryHandler polarisDiscoveryHandler;
+ private final PolarisServiceStatusChangeListener polarisServiceStatusChangeListener;
+ private final ScheduledExecutorService refreshExecutor;
+ private ApplicationEventPublisher publisher;
+
+ public PolarisRefreshApplicationReadyEventListener(PolarisDiscoveryHandler polarisDiscoveryHandler, PolarisServiceStatusChangeListener polarisServiceStatusChangeListener) {
+ this.polarisDiscoveryHandler = polarisDiscoveryHandler;
+ this.polarisServiceStatusChangeListener = polarisServiceStatusChangeListener;
+ this.refreshExecutor = Executors.newSingleThreadScheduledExecutor(
+ new NamedThreadFactory("polaris-service-refresh"));
+ }
+
+ @Override
+ public void onApplicationEvent(ApplicationReadyEvent event) {
+ // Register service change listener.
+ polarisDiscoveryHandler.getSdkContext().getExtensions().getLocalRegistry()
+ .registerResourceListener(polarisServiceStatusChangeListener);
+
+ // Begin scheduled refresh thread.
+ refresh();
+ }
+
+ /**
+ * Start the refresh thread.
+ */
+ public void refresh() {
+ refreshExecutor.scheduleWithFixedDelay(() -> {
+ try {
+ // Trigger reload of gateway route cache.
+ this.publisher.publishEvent(new HeartbeatEvent(this, INDEX.getAndIncrement()));
+ }
+ catch (Exception e) {
+ LOG.error("refresh polaris service error.", e);
+ }
+ }, DELAY, DELAY, TimeUnit.SECONDS);
+ }
+
+ @Override
+ public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
+ this.publisher = applicationEventPublisher;
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/PolarisRefreshConfiguration.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/PolarisRefreshConfiguration.java
new file mode 100644
index 000000000..acbe54b7a
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/PolarisRefreshConfiguration.java
@@ -0,0 +1,48 @@
+/*
+ * Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
+ *
+ * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+package com.tencent.cloud.polaris.discovery.refresh;
+
+import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled;
+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 for listening the change of service status.
+ *
+ * @author Haotian Zhang
+ */
+@Configuration(proxyBeanMethods = false)
+@ConditionalOnPolarisEnabled
+public class PolarisRefreshConfiguration {
+
+ @Bean
+ @ConditionalOnMissingBean
+ public PolarisServiceStatusChangeListener polarisServiceChangeListener() {
+ return new PolarisServiceStatusChangeListener();
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ public PolarisRefreshApplicationReadyEventListener polarisServiceStatusApplicationReadyEventListener(
+ PolarisDiscoveryHandler polarisDiscoveryHandler,
+ PolarisServiceStatusChangeListener polarisServiceStatusChangeListener) {
+ return new PolarisRefreshApplicationReadyEventListener(polarisDiscoveryHandler, polarisServiceStatusChangeListener);
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/PolarisServiceStatusChangeListener.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/PolarisServiceStatusChangeListener.java
new file mode 100644
index 000000000..c923295d5
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/PolarisServiceStatusChangeListener.java
@@ -0,0 +1,96 @@
+/*
+ * Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
+ *
+ * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+package com.tencent.cloud.polaris.discovery.refresh;
+
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.stream.Collectors;
+
+import com.google.common.collect.Sets;
+import com.tencent.polaris.api.plugin.registry.AbstractResourceEventListener;
+import com.tencent.polaris.api.pojo.RegistryCacheValue;
+import com.tencent.polaris.api.pojo.ServiceEventKey;
+import com.tencent.polaris.client.pojo.ServiceInstancesByProto;
+import com.tencent.polaris.client.pojo.ServicesByProto;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.springframework.cloud.client.discovery.event.HeartbeatEvent;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.context.ApplicationEventPublisherAware;
+import org.springframework.util.CollectionUtils;
+
+/**
+ * Change listener of Polaris service info. When service info is created or deleted, or, instance of service is from 0 to
+ *
+ * @author Haotian Zhang
+ */
+public class PolarisServiceStatusChangeListener extends AbstractResourceEventListener implements ApplicationEventPublisherAware {
+
+ /**
+ * Index of service info status.
+ */
+ public static final AtomicLong INDEX = new AtomicLong(0);
+
+ private static final Logger LOG = LoggerFactory.getLogger(PolarisServiceStatusChangeListener.class);
+
+ private ApplicationEventPublisher publisher;
+
+ @Override
+ public void onResourceUpdated(ServiceEventKey svcEventKey, RegistryCacheValue oldValue,
+ RegistryCacheValue newValue) {
+ if (newValue.getEventType() == ServiceEventKey.EventType.SERVICE) {
+ if (oldValue instanceof ServicesByProto && newValue instanceof ServicesByProto) {
+ LOG.debug("receive service={} change event", svcEventKey);
+ Set oldServiceInfoSet = ((ServicesByProto) oldValue).getServices().stream()
+ .map(i -> i.getNamespace() + "::" + i.getService()).collect(Collectors.toSet());
+ Set newServiceInfoSet = ((ServicesByProto) newValue).getServices().stream()
+ .map(i -> i.getNamespace() + "::" + i.getService()).collect(Collectors.toSet());
+
+ Sets.SetView addServiceInfoSetView = Sets.difference(newServiceInfoSet, oldServiceInfoSet);
+ Sets.SetView deleteServiceInfoSetView = Sets.difference(oldServiceInfoSet, newServiceInfoSet);
+
+ if (addServiceInfoSetView.isEmpty() && deleteServiceInfoSetView.isEmpty()) {
+ return;
+ }
+ LOG.info("Service status is update. Add service of {}. Delete service of {}", addServiceInfoSetView, deleteServiceInfoSetView);
+
+ // Trigger reload of gateway route cache.
+ this.publisher.publishEvent(new HeartbeatEvent(this, INDEX.getAndIncrement()));
+ }
+ }
+ else if (newValue.getEventType() == ServiceEventKey.EventType.INSTANCE) {
+ if (oldValue instanceof ServiceInstancesByProto && newValue instanceof ServiceInstancesByProto) {
+ LOG.debug("receive service instances={} change event", svcEventKey);
+ ServiceInstancesByProto oldIns = (ServiceInstancesByProto) oldValue;
+ ServiceInstancesByProto newIns = (ServiceInstancesByProto) newValue;
+ if ((CollectionUtils.isEmpty(oldIns.getInstances()) && !CollectionUtils.isEmpty(newIns.getInstances())) ||
+ (!CollectionUtils.isEmpty(oldIns.getInstances()) && CollectionUtils.isEmpty(newIns.getInstances()))) {
+ LOG.info("Service status of {} is update.", newIns.getService());
+
+ // Trigger reload of gateway route cache.
+ this.publisher.publishEvent(new HeartbeatEvent(this, INDEX.getAndIncrement()));
+ }
+ }
+ }
+ }
+
+ @Override
+ public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
+ this.publisher = applicationEventPublisher;
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisRegistration.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisRegistration.java
index 9ca6b9e08..ed8baacc9 100644
--- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisRegistration.java
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisRegistration.java
@@ -19,9 +19,9 @@
package com.tencent.cloud.polaris.registry;
import java.net.URI;
+import java.util.Collections;
import java.util.Map;
-import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.polaris.DiscoveryPropertiesAutoConfiguration;
import com.tencent.cloud.polaris.PolarisDiscoveryProperties;
import com.tencent.polaris.client.api.SDKContext;
@@ -84,7 +84,7 @@ public class PolarisRegistration implements Registration, ServiceInstance {
@Override
public Map getMetadata() {
- return MetadataContextHolder.get().getAllSystemMetadata();
+ return Collections.emptyMap();
}
public PolarisDiscoveryProperties getPolarisProperties() {
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistry.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistry.java
index 83f8967f0..0d39c7262 100644
--- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistry.java
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistry.java
@@ -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;
@@ -199,7 +198,7 @@ public class PolarisServiceRegistry implements ServiceRegistry {
// 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;
}
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistryAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistryAutoConfiguration.java
index 93e282c8c..68f338c5d 100644
--- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistryAutoConfiguration.java
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistryAutoConfiguration.java
@@ -52,11 +52,9 @@ public class PolarisServiceRegistryAutoConfiguration {
@Bean
public PolarisServiceRegistry polarisServiceRegistry(
- PolarisDiscoveryProperties polarisDiscoveryProperties,
- PolarisDiscoveryHandler polarisDiscoveryHandler,
+ PolarisDiscoveryProperties polarisDiscoveryProperties, PolarisDiscoveryHandler polarisDiscoveryHandler,
MetadataLocalProperties metadataLocalProperties) {
- return new PolarisServiceRegistry(polarisDiscoveryProperties,
- polarisDiscoveryHandler, metadataLocalProperties);
+ return new PolarisServiceRegistry(polarisDiscoveryProperties, polarisDiscoveryHandler, metadataLocalProperties);
}
@Bean
@@ -77,5 +75,4 @@ public class PolarisServiceRegistryAutoConfiguration {
return new PolarisAutoServiceRegistration(registry,
autoServiceRegistrationProperties, registration);
}
-
}
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-starter-tencent-polaris-discovery/src/main/resources/META-INF/additional-spring-configuration-metadata.json
index eb160ae93..7743b5f6c 100644
--- a/spring-cloud-starter-tencent-polaris-discovery/src/main/resources/META-INF/additional-spring-configuration-metadata.json
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/resources/META-INF/additional-spring-configuration-metadata.json
@@ -59,6 +59,12 @@
"type": "java.lang.Integer",
"defaultValue": 100,
"description": "the weight of polaris instance , use to load-balance."
+ },
+ {
+ "name": "spring.cloud.polaris.discovery.service-list-refresh-interval",
+ "type": "java.lang.Long",
+ "defaultValue": 60000,
+ "description": "Millis interval of refresh of service info list. Default: 60000."
}
]
}
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/PolarisPropertiesTest.java b/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/PolarisPropertiesTest.java
index 518797e2c..a1259704a 100644
--- a/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/PolarisPropertiesTest.java
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/PolarisPropertiesTest.java
@@ -26,7 +26,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.fail;
/**
- * Test for {@link PolarisDiscoveryProperties}
+ * Test for {@link PolarisDiscoveryProperties}.
*
* @author Haotian Zhang
*/
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/discovery/PolarisDiscoveryAutoConfigurationTest.java b/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/discovery/PolarisDiscoveryAutoConfigurationTest.java
index fc6ed91fe..cdad58bc0 100644
--- a/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/discovery/PolarisDiscoveryAutoConfigurationTest.java
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/discovery/PolarisDiscoveryAutoConfigurationTest.java
@@ -38,7 +38,7 @@ import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER;
import static org.assertj.core.api.Assertions.assertThat;
/**
- * Test for {@link PolarisDiscoveryAutoConfiguration}
+ * Test for {@link PolarisDiscoveryAutoConfiguration}.
*
* @author Haotian Zhang
*/
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/discovery/PolarisDiscoveryClientConfigurationTest.java b/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/discovery/PolarisDiscoveryClientConfigurationTest.java
index 7a9b78943..022377238 100644
--- a/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/discovery/PolarisDiscoveryClientConfigurationTest.java
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/discovery/PolarisDiscoveryClientConfigurationTest.java
@@ -34,7 +34,7 @@ import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER;
import static org.assertj.core.api.Assertions.assertThat;
/**
- * Test for {@link PolarisDiscoveryClientConfiguration}
+ * Test for {@link PolarisDiscoveryClientConfiguration}.
*
* @author Haotian Zhang
*/
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/discovery/PolarisDiscoveryClientTest.java b/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/discovery/PolarisDiscoveryClientTest.java
index baad9d365..e72393161 100644
--- a/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/discovery/PolarisDiscoveryClientTest.java
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/discovery/PolarisDiscoveryClientTest.java
@@ -37,7 +37,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
- * Test for {@link PolarisDiscoveryClient}
+ * Test for {@link PolarisDiscoveryClient}.
*
* @author Haotian Zhang
*/
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/discovery/PolarisServiceDiscoveryTest.java b/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/discovery/PolarisServiceDiscoveryTest.java
index 56ff83db7..874d577b1 100644
--- a/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/discovery/PolarisServiceDiscoveryTest.java
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/discovery/PolarisServiceDiscoveryTest.java
@@ -41,7 +41,7 @@ import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER;
import static org.assertj.core.api.Assertions.assertThat;
/**
- * Test for {@link PolarisServiceDiscovery}
+ * Test for {@link PolarisServiceDiscovery}.
*
* @author Haotian Zhang
*/
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/discovery/reactive/PolarisReactiveDiscoveryClientConfigurationTest.java b/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/discovery/reactive/PolarisReactiveDiscoveryClientConfigurationTest.java
index 0bbcc6548..527b07e22 100644
--- a/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/discovery/reactive/PolarisReactiveDiscoveryClientConfigurationTest.java
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/discovery/reactive/PolarisReactiveDiscoveryClientConfigurationTest.java
@@ -35,7 +35,7 @@ import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER;
import static org.assertj.core.api.Assertions.assertThat;
/**
- * Test for {@link PolarisReactiveDiscoveryClientConfiguration}
+ * Test for {@link PolarisReactiveDiscoveryClientConfiguration}.
*
* @author Haotian Zhang
*/
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/discovery/reactive/PolarisReactiveDiscoveryClientTest.java b/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/discovery/reactive/PolarisReactiveDiscoveryClientTest.java
index 99aa8f1df..300a94cd9 100644
--- a/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/discovery/reactive/PolarisReactiveDiscoveryClientTest.java
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/discovery/reactive/PolarisReactiveDiscoveryClientTest.java
@@ -37,7 +37,7 @@ import static java.util.Collections.singletonList;
import static org.mockito.Mockito.when;
/**
- * Test for {@link PolarisReactiveDiscoveryClient}
+ * Test for {@link PolarisReactiveDiscoveryClient}.
*
* @author Haotian Zhang
*/
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistryAutoConfigurationTest.java b/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistryAutoConfigurationTest.java
index e1645d80c..ede3f0387 100644
--- a/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistryAutoConfigurationTest.java
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistryAutoConfigurationTest.java
@@ -37,7 +37,7 @@ import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER;
import static org.assertj.core.api.Assertions.assertThat;
/**
- * Test for {@link PolarisServiceRegistryAutoConfiguration}
+ * Test for {@link PolarisServiceRegistryAutoConfiguration}.
*
* @author Haotian Zhang
*/
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistryTest.java b/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistryTest.java
index 4371e32ac..f37ed344c 100644
--- a/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistryTest.java
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistryTest.java
@@ -41,7 +41,7 @@ import static org.junit.Assert.fail;
import static org.mockito.Mockito.when;
/**
- * Test for {@link PolarisServiceRegistry}
+ * Test for {@link PolarisServiceRegistry}.
*
* @author Haotian Zhang
*/
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/ribbon/PolarisRibbonServerListConfigurationTest.java b/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/ribbon/PolarisRibbonServerListConfigurationTest.java
index d429da7b4..ae3a1eb79 100644
--- a/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/ribbon/PolarisRibbonServerListConfigurationTest.java
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/ribbon/PolarisRibbonServerListConfigurationTest.java
@@ -39,7 +39,7 @@ import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER;
import static org.assertj.core.api.Assertions.assertThat;
/**
- * Test for {@link PolarisRibbonServerListConfiguration}
+ * Test for {@link PolarisRibbonServerListConfiguration}.
*
* @author Haotian Zhang
*/
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/ribbon/PolarisServerListTest.java b/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/ribbon/PolarisServerListTest.java
index 9cd01db87..a036ed344 100644
--- a/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/ribbon/PolarisServerListTest.java
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/ribbon/PolarisServerListTest.java
@@ -46,7 +46,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
- * Test for {@link PolarisServerList}
+ * Test for {@link PolarisServerList}.
*
* @author Haotian Zhang
*/
diff --git a/spring-cloud-starter-tencent-polaris-ratelimit/pom.xml b/spring-cloud-starter-tencent-polaris-ratelimit/pom.xml
index a313fb962..fe07a8d90 100644
--- a/spring-cloud-starter-tencent-polaris-ratelimit/pom.xml
+++ b/spring-cloud-starter-tencent-polaris-ratelimit/pom.xml
@@ -34,10 +34,6 @@
com.tencent.polaris
router-nearby
-
- com.tencent.polaris
- router-metadata
-
com.tencent.polaris
router-canary
diff --git a/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/RateLimitRuleLabelResolver.java b/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/RateLimitRuleLabelResolver.java
new file mode 100644
index 000000000..4c29cb3ad
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/RateLimitRuleLabelResolver.java
@@ -0,0 +1,72 @@
+/*
+ * Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
+ *
+ * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ */
+
+package com.tencent.cloud.polaris.ratelimit;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.tencent.cloud.common.util.ExpressionLabelUtils;
+import com.tencent.cloud.polaris.context.ServiceRuleManager;
+import com.tencent.polaris.client.pb.ModelProto;
+import com.tencent.polaris.client.pb.RateLimitProto;
+
+import org.springframework.util.CollectionUtils;
+
+/**
+ * resolve labels from rate limit rule.
+ *
+ *@author lepdou 2022-05-13
+ */
+public class RateLimitRuleLabelResolver {
+
+ private final ServiceRuleManager serviceRuleManager;
+
+ public RateLimitRuleLabelResolver(ServiceRuleManager serviceRuleManager) {
+ this.serviceRuleManager = serviceRuleManager;
+ }
+
+ public Set getExpressionLabelKeys(String namespace, String service) {
+ RateLimitProto.RateLimit rateLimitRule = serviceRuleManager.getServiceRateLimitRule(namespace, service);
+ if (rateLimitRule == null) {
+ return Collections.emptySet();
+ }
+
+ List rules = rateLimitRule.getRulesList();
+ if (CollectionUtils.isEmpty(rules)) {
+ return Collections.emptySet();
+ }
+
+ Set expressionLabels = new HashSet<>();
+ for (RateLimitProto.Rule rule : rules) {
+ Map labels = rule.getLabelsMap();
+ if (CollectionUtils.isEmpty(labels)) {
+ return Collections.emptySet();
+ }
+ for (String key : labels.keySet()) {
+ if (ExpressionLabelUtils.isExpressionLabel(key)) {
+ expressionLabels.add(key);
+ }
+ }
+ }
+ return expressionLabels;
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/config/RateLimitConfiguration.java b/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/config/RateLimitConfiguration.java
index cf4d33a91..bf912674d 100644
--- a/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/config/RateLimitConfiguration.java
+++ b/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/config/RateLimitConfiguration.java
@@ -19,6 +19,8 @@
package com.tencent.cloud.polaris.ratelimit.config;
import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled;
+import com.tencent.cloud.polaris.context.ServiceRuleManager;
+import com.tencent.cloud.polaris.ratelimit.RateLimitRuleLabelResolver;
import com.tencent.cloud.polaris.ratelimit.constant.RateLimitConstant;
import com.tencent.cloud.polaris.ratelimit.filter.QuotaCheckReactiveFilter;
import com.tencent.cloud.polaris.ratelimit.filter.QuotaCheckServletFilter;
@@ -62,6 +64,11 @@ public class RateLimitConfiguration {
return LimitAPIFactory.createLimitAPIByContext(polarisContext);
}
+ @Bean
+ public RateLimitRuleLabelResolver rateLimitRuleLabelService(ServiceRuleManager serviceRuleManager) {
+ return new RateLimitRuleLabelResolver(serviceRuleManager);
+ }
+
/**
* Create when web application type is SERVLET.
*/
@@ -73,9 +80,10 @@ public class RateLimitConfiguration {
@ConditionalOnMissingBean
public QuotaCheckServletFilter quotaCheckFilter(LimitAPI limitAPI,
@Nullable PolarisRateLimiterLabelServletResolver labelResolver,
- PolarisRateLimitProperties polarisRateLimitProperties) {
+ PolarisRateLimitProperties polarisRateLimitProperties,
+ RateLimitRuleLabelResolver rateLimitRuleLabelResolver) {
return new QuotaCheckServletFilter(limitAPI, labelResolver,
- polarisRateLimitProperties);
+ polarisRateLimitProperties, rateLimitRuleLabelResolver);
}
@Bean
@@ -101,9 +109,10 @@ public class RateLimitConfiguration {
@Bean
public QuotaCheckReactiveFilter quotaCheckReactiveFilter(LimitAPI limitAPI,
@Nullable PolarisRateLimiterLabelReactiveResolver labelResolver,
- PolarisRateLimitProperties polarisRateLimitProperties) {
+ PolarisRateLimitProperties polarisRateLimitProperties,
+ RateLimitRuleLabelResolver rateLimitRuleLabelResolver) {
return new QuotaCheckReactiveFilter(limitAPI, labelResolver,
- polarisRateLimitProperties);
+ polarisRateLimitProperties, rateLimitRuleLabelResolver);
}
}
diff --git a/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckReactiveFilter.java b/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckReactiveFilter.java
index 9a0db9a77..d9b8d3389 100644
--- a/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckReactiveFilter.java
+++ b/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckReactiveFilter.java
@@ -21,10 +21,14 @@ package com.tencent.cloud.polaris.ratelimit.filter;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
+import java.util.Set;
import javax.annotation.PostConstruct;
+import com.google.common.collect.Maps;
import com.tencent.cloud.common.metadata.MetadataContext;
+import com.tencent.cloud.common.util.ExpressionLabelUtils;
+import com.tencent.cloud.polaris.ratelimit.RateLimitRuleLabelResolver;
import com.tencent.cloud.polaris.ratelimit.config.PolarisRateLimitProperties;
import com.tencent.cloud.polaris.ratelimit.constant.RateLimitConstant;
import com.tencent.cloud.polaris.ratelimit.spi.PolarisRateLimiterLabelReactiveResolver;
@@ -42,7 +46,6 @@ import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
-import org.springframework.util.CollectionUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
@@ -52,7 +55,7 @@ import static com.tencent.cloud.polaris.ratelimit.constant.RateLimitConstant.LAB
/**
* Reactive filter to check quota.
*
- * @author Haotian Zhang
+ * @author Haotian Zhang, lepdou
*/
public class QuotaCheckReactiveFilter implements WebFilter, Ordered {
@@ -65,14 +68,18 @@ public class QuotaCheckReactiveFilter implements WebFilter, Ordered {
private final PolarisRateLimitProperties polarisRateLimitProperties;
+ private final RateLimitRuleLabelResolver rateLimitRuleLabelResolver;
+
private String rejectTips;
public QuotaCheckReactiveFilter(LimitAPI limitAPI,
PolarisRateLimiterLabelReactiveResolver labelResolver,
- PolarisRateLimitProperties polarisRateLimitProperties) {
+ PolarisRateLimitProperties polarisRateLimitProperties,
+ RateLimitRuleLabelResolver rateLimitRuleLabelResolver) {
this.limitAPI = limitAPI;
this.labelResolver = labelResolver;
this.polarisRateLimitProperties = polarisRateLimitProperties;
+ this.rateLimitRuleLabelResolver = rateLimitRuleLabelResolver;
}
@PostConstruct
@@ -90,27 +97,7 @@ public class QuotaCheckReactiveFilter implements WebFilter, Ordered {
String localNamespace = MetadataContext.LOCAL_NAMESPACE;
String localService = MetadataContext.LOCAL_SERVICE;
- Map labels = new HashMap<>();
-
- // add build in labels
- String path = exchange.getRequest().getURI().getPath();
- if (StringUtils.isNotBlank(path)) {
- labels.put(LABEL_METHOD, path);
- }
-
- // add custom labels
- if (labelResolver != null) {
- try {
- Map customLabels = labelResolver.resolve(exchange);
- if (!CollectionUtils.isEmpty(customLabels)) {
- labels.putAll(customLabels);
- }
- }
- catch (Throwable e) {
- LOG.error("resolve custom label failed. resolver = {}",
- labelResolver.getClass().getName(), e);
- }
- }
+ Map labels = getRequestLabels(exchange, localNamespace, localService);
try {
QuotaResponse quotaResponse = QuotaCheckUtils.getQuota(limitAPI,
@@ -134,4 +121,42 @@ public class QuotaCheckReactiveFilter implements WebFilter, Ordered {
return chain.filter(exchange);
}
+ private Map getRequestLabels(ServerWebExchange exchange, String localNamespace, String localService) {
+ Map labels = new HashMap<>();
+
+ // add build in labels
+ String path = exchange.getRequest().getURI().getPath();
+ if (StringUtils.isNotBlank(path)) {
+ labels.put(LABEL_METHOD, path);
+ }
+
+ // add rule expression labels
+ Map expressionLabels = getRuleExpressionLabels(exchange, localNamespace, localService);
+ labels.putAll(expressionLabels);
+
+ // add custom labels
+ Map customResolvedLabels = getCustomResolvedLabels(exchange);
+ labels.putAll(customResolvedLabels);
+
+ return labels;
+ }
+
+ private Map getCustomResolvedLabels(ServerWebExchange exchange) {
+ if (labelResolver != null) {
+ try {
+ return labelResolver.resolve(exchange);
+ }
+ catch (Throwable e) {
+ LOG.error("resolve custom label failed. resolver = {}",
+ labelResolver.getClass().getName(), e);
+ }
+ }
+ return Maps.newHashMap();
+ }
+
+ private Map getRuleExpressionLabels(ServerWebExchange exchange, String namespace, String service) {
+ Set expressionLabels = rateLimitRuleLabelResolver.getExpressionLabelKeys(namespace, service);
+ return ExpressionLabelUtils.resolve(exchange, expressionLabels);
+ }
+
}
diff --git a/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckServletFilter.java b/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckServletFilter.java
index ae1601093..54a9e545f 100644
--- a/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckServletFilter.java
+++ b/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckServletFilter.java
@@ -19,8 +19,10 @@
package com.tencent.cloud.polaris.ratelimit.filter;
import java.io.IOException;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
+import java.util.Set;
import javax.annotation.PostConstruct;
import javax.servlet.FilterChain;
@@ -29,6 +31,8 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.tencent.cloud.common.metadata.MetadataContext;
+import com.tencent.cloud.common.util.ExpressionLabelUtils;
+import com.tencent.cloud.polaris.ratelimit.RateLimitRuleLabelResolver;
import com.tencent.cloud.polaris.ratelimit.config.PolarisRateLimitProperties;
import com.tencent.cloud.polaris.ratelimit.constant.RateLimitConstant;
import com.tencent.cloud.polaris.ratelimit.spi.PolarisRateLimiterLabelServletResolver;
@@ -42,7 +46,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
-import org.springframework.util.CollectionUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import static com.tencent.cloud.polaris.ratelimit.constant.RateLimitConstant.LABEL_METHOD;
@@ -50,13 +53,12 @@ import static com.tencent.cloud.polaris.ratelimit.constant.RateLimitConstant.LAB
/**
* Servlet filter to check quota.
*
- * @author Haotian Zhang
+ * @author Haotian Zhang, lepdou
*/
@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;
@@ -64,14 +66,18 @@ public class QuotaCheckServletFilter extends OncePerRequestFilter {
private final PolarisRateLimitProperties polarisRateLimitProperties;
+ private final RateLimitRuleLabelResolver rateLimitRuleLabelResolver;
+
private String rejectTips;
public QuotaCheckServletFilter(LimitAPI limitAPI,
PolarisRateLimiterLabelServletResolver labelResolver,
- PolarisRateLimitProperties polarisRateLimitProperties) {
+ PolarisRateLimitProperties polarisRateLimitProperties,
+ RateLimitRuleLabelResolver rateLimitRuleLabelResolver) {
this.limitAPI = limitAPI;
this.labelResolver = labelResolver;
this.polarisRateLimitProperties = polarisRateLimitProperties;
+ this.rateLimitRuleLabelResolver = rateLimitRuleLabelResolver;
}
@PostConstruct
@@ -80,52 +86,68 @@ 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;
+ Map labels = getRequestLabels(request, localNamespace, localService);
+
+ try {
+ QuotaResponse quotaResponse = QuotaCheckUtils.getQuota(limitAPI,
+ localNamespace, localService, 1, labels, null);
+
+ if (quotaResponse.getCode() == QuotaResultCode.QuotaResultLimited) {
+ response.setStatus(polarisRateLimitProperties.getRejectHttpCode());
+ response.getWriter().write(rejectTips);
+ return;
+ }
+
+ filterChain.doFilter(request, response);
+ }
+ catch (Throwable t) {
+ // An exception occurs in the rate limiting API call,
+ // which should not affect the call of the business process.
+ LOG.error("fail to invoke getQuota, service is " + localService, t);
+ filterChain.doFilter(request, response);
+ }
+ }
+
+ private Map getRequestLabels(HttpServletRequest request, String localNamespace, String localService) {
Map labels = new HashMap<>();
// add build in labels
String path = request.getRequestURI();
-
if (StringUtils.isNotBlank(path)) {
labels.put(LABEL_METHOD, path);
}
- // add custom labels
+ // add rule expression labels
+ Map expressionLabels = getRuleExpressionLabels(request, localNamespace, localService);
+ labels.putAll(expressionLabels);
+
+ // add custom resolved labels
+ Map customLabels = getCustomResolvedLabels(request);
+ labels.putAll(customLabels);
+
+ return labels;
+ }
+
+ private Map getCustomResolvedLabels(HttpServletRequest request) {
if (labelResolver != null) {
try {
- Map customLabels = labelResolver.resolve(request);
- if (!CollectionUtils.isEmpty(customLabels)) {
- labels.putAll(customLabels);
- }
+ return labelResolver.resolve(request);
}
catch (Throwable e) {
LOG.error("resolve custom label failed. resolver = {}",
labelResolver.getClass().getName(), e);
}
}
-
- try {
- QuotaResponse quotaResponse = QuotaCheckUtils.getQuota(limitAPI,
- localNamespace, localService, 1, labels, null);
- if (quotaResponse.getCode() == QuotaResultCode.QuotaResultLimited) {
- response.setStatus(polarisRateLimitProperties.getRejectHttpCode());
- response.getWriter().write(rejectTips);
- }
- else {
- filterChain.doFilter(request, response);
- }
- }
- catch (Throwable t) {
- // An exception occurs in the rate limiting API call,
- // which should not affect the call of the business process.
- LOG.error("fail to invoke getQuota, service is " + localService, t);
- filterChain.doFilter(request, response);
- }
+ return Collections.emptyMap();
}
+ private Map getRuleExpressionLabels(HttpServletRequest request, String namespace, String service) {
+ Set expressionLabels = rateLimitRuleLabelResolver.getExpressionLabelKeys(namespace, service);
+ return ExpressionLabelUtils.resolve(request, expressionLabels);
+ }
}
diff --git a/spring-cloud-starter-tencent-polaris-router/pom.xml b/spring-cloud-starter-tencent-polaris-router/pom.xml
index d623da7b1..6f0fa315d 100644
--- a/spring-cloud-starter-tencent-polaris-router/pom.xml
+++ b/spring-cloud-starter-tencent-polaris-router/pom.xml
@@ -27,6 +27,19 @@
router-rule
+
+
+ org.springframework.cloud
+ spring-cloud-starter-openfeign
+ true
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+ true
+
+
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisLoadBalancerCompositeRule.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisLoadBalancerCompositeRule.java
new file mode 100644
index 000000000..d270f766c
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisLoadBalancerCompositeRule.java
@@ -0,0 +1,184 @@
+/*
+ * 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.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import com.netflix.client.config.IClientConfig;
+import com.netflix.loadbalancer.AbstractLoadBalancerRule;
+import com.netflix.loadbalancer.AvailabilityFilteringRule;
+import com.netflix.loadbalancer.BestAvailableRule;
+import com.netflix.loadbalancer.ILoadBalancer;
+import com.netflix.loadbalancer.RandomRule;
+import com.netflix.loadbalancer.RetryRule;
+import com.netflix.loadbalancer.RoundRobinRule;
+import com.netflix.loadbalancer.Server;
+import com.netflix.loadbalancer.WeightedResponseTimeRule;
+import com.netflix.loadbalancer.ZoneAvoidanceRule;
+import com.tencent.cloud.common.metadata.MetadataContext;
+import com.tencent.cloud.common.pojo.PolarisServer;
+import com.tencent.cloud.polaris.loadbalancer.LoadBalancerUtils;
+import com.tencent.cloud.polaris.loadbalancer.PolarisWeightedRule;
+import com.tencent.cloud.polaris.loadbalancer.config.PolarisLoadBalancerProperties;
+import com.tencent.polaris.api.pojo.Instance;
+import com.tencent.polaris.api.pojo.ServiceInfo;
+import com.tencent.polaris.api.pojo.ServiceInstances;
+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 org.springframework.util.CollectionUtils;
+
+/**
+ *
+ * Service routing entrance.
+ *
+ * Rule routing needs to rely on request parameters for server filtering,
+ * and {@link com.netflix.loadbalancer.ServerListFilter#getFilteredListOfServers(List)}
+ * The interface cannot obtain the context object of the request granularity,
+ * so the routing capability cannot be achieved through ServerListFilter.
+ *
+ * And {@link com.netflix.loadbalancer.IRule#choose(Object)} provides the ability to pass in context parameters,
+ * so routing capabilities are implemented through IRule.
+ *
+ * @author Haotian Zhang, lepdou
+ */
+public class PolarisLoadBalancerCompositeRule extends AbstractLoadBalancerRule {
+
+ private final static String STRATEGY_RANDOM = "random";
+ private final static String STRATEGY_ROUND_ROBIN = "roundRobin";
+ private final static String STRATEGY_WEIGHT = "polarisWeighted";
+ private final static String STRATEGY_RETRY = "retry";
+ private final static String STRATEGY_RESPONSE_TIME_WEIGHTED = "responseTimeWeighted";
+ private final static String STRATEGY_BEST_AVAILABLE = "bestAvailable";
+ private final static String STRATEGY_ZONE_AVOIDANCE = "zoneAvoidance";
+ private final static String STRATEGY_AVAILABILITY_FILTERING = "availabilityFilteringRule";
+
+ private final PolarisLoadBalancerProperties loadBalancerProperties;
+ private final RouterAPI routerAPI;
+
+ private final AbstractLoadBalancerRule delegateRule;
+
+ public PolarisLoadBalancerCompositeRule(RouterAPI routerAPI, PolarisLoadBalancerProperties polarisLoadBalancerProperties,
+ IClientConfig iClientConfig) {
+ this.routerAPI = routerAPI;
+ this.loadBalancerProperties = polarisLoadBalancerProperties;
+
+ delegateRule = getRule();
+ delegateRule.initWithNiwsConfig(iClientConfig);
+ }
+
+ @Override
+ public void initWithNiwsConfig(IClientConfig clientConfig) {
+ }
+
+ @Override
+ public Server choose(Object key) {
+ // 1. get all servers
+ List allServers = getLoadBalancer().getReachableServers();
+ if (CollectionUtils.isEmpty(allServers)) {
+ return null;
+ }
+
+ // 2. filter by router
+ List serversAfterRouter = doRouter(allServers, key);
+
+ // 3. filter by load balance.
+ // A LoadBalancer needs to be regenerated for each request,
+ // because the list of servers may be different after filtered by router
+ ILoadBalancer loadBalancer = new SimpleLoadBalancer();
+ loadBalancer.addServers(serversAfterRouter);
+ delegateRule.setLoadBalancer(loadBalancer);
+
+ return delegateRule.choose(key);
+ }
+
+ private List doRouter(List allServers, Object key) {
+ ServiceInstances serviceInstances = LoadBalancerUtils.transferServersToServiceInstances(allServers);
+
+ // filter instance by routers
+ ProcessRoutersRequest processRoutersRequest = buildProcessRoutersRequest(serviceInstances, key);
+
+ ProcessRoutersResponse processRoutersResponse = routerAPI.processRouters(processRoutersRequest);
+
+ List filteredInstances = new ArrayList<>();
+ ServiceInstances filteredServiceInstances = processRoutersResponse.getServiceInstances();
+ for (Instance instance : filteredServiceInstances.getInstances()) {
+ filteredInstances.add(new PolarisServer(serviceInstances, instance));
+ }
+ return filteredInstances;
+ }
+
+ private ProcessRoutersRequest buildProcessRoutersRequest(ServiceInstances serviceInstances, Object key) {
+ ProcessRoutersRequest processRoutersRequest = new ProcessRoutersRequest();
+ processRoutersRequest.setDstInstances(serviceInstances);
+
+ Map routerMetadata;
+ if (key instanceof PolarisRouterContext) {
+ routerMetadata = ((PolarisRouterContext) key).getLabels();
+ }
+ else {
+ routerMetadata = Collections.emptyMap();
+ }
+
+ String srcNamespace = MetadataContext.LOCAL_NAMESPACE;
+ String srcService = MetadataContext.LOCAL_SERVICE;
+
+ if (StringUtils.isNotBlank(srcNamespace) && StringUtils.isNotBlank(srcService)) {
+ ServiceInfo serviceInfo = new ServiceInfo();
+ serviceInfo.setNamespace(srcNamespace);
+ serviceInfo.setService(srcService);
+ serviceInfo.setMetadata(routerMetadata);
+ processRoutersRequest.setSourceService(serviceInfo);
+ }
+
+ return processRoutersRequest;
+ }
+
+ public AbstractLoadBalancerRule getRule() {
+ String loadBalanceStrategy = loadBalancerProperties.getStrategy();
+ if (org.springframework.util.StringUtils.isEmpty(loadBalanceStrategy)) {
+ return new RoundRobinRule();
+ }
+
+ switch (loadBalanceStrategy) {
+ case STRATEGY_RANDOM:
+ return new RandomRule();
+ case STRATEGY_WEIGHT:
+ return new PolarisWeightedRule(routerAPI);
+ case STRATEGY_RETRY:
+ return new RetryRule();
+ case STRATEGY_RESPONSE_TIME_WEIGHTED:
+ return new WeightedResponseTimeRule();
+ case STRATEGY_BEST_AVAILABLE:
+ return new BestAvailableRule();
+ case STRATEGY_ROUND_ROBIN:
+ return new RoundRobinRule();
+ case STRATEGY_AVAILABILITY_FILTERING:
+ return new AvailabilityFilteringRule();
+ case STRATEGY_ZONE_AVOIDANCE:
+ default:
+ return new ZoneAvoidanceRule();
+ }
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisRouterContext.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisRouterContext.java
new file mode 100644
index 000000000..2ed7e727e
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisRouterContext.java
@@ -0,0 +1,53 @@
+/*
+ * 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.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.springframework.util.CollectionUtils;
+
+/**
+ * the context for router.
+ *
+ *@author lepdou 2022-05-17
+ */
+public class PolarisRouterContext {
+
+ private Map labels;
+
+ public Map getLabels() {
+ if (CollectionUtils.isEmpty(labels)) {
+ return Collections.emptyMap();
+ }
+ return Collections.unmodifiableMap(labels);
+ }
+
+ public void setLabels(Map labels) {
+ this.labels = labels;
+ }
+
+ public void putLabel(String key, String value) {
+ if (labels == null) {
+ labels = new HashMap<>();
+ }
+ labels.put(key, value);
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/package-info.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/RouterConstants.java
similarity index 80%
rename from spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/package-info.java
rename to spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/RouterConstants.java
index 3eb18e376..77266cc02 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/package-info.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/RouterConstants.java
@@ -13,11 +13,20 @@
* 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;
+
/**
- * Package info of router.
+ * Router constants.
*
- * @author Haotian Zhang
+ *@author lepdou 2022-05-17
*/
-package com.tencent.cloud.polaris.router;
+public class RouterConstants {
+
+ /**
+ * the header of router label.
+ */
+ public static final String ROUTER_LABEL_HEADER = "router-label";
+}
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/RouterRuleLabelResolver.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/RouterRuleLabelResolver.java
new file mode 100644
index 000000000..5ab6e549f
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/RouterRuleLabelResolver.java
@@ -0,0 +1,75 @@
+/*
+ * 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.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.tencent.cloud.common.util.ExpressionLabelUtils;
+import com.tencent.cloud.polaris.context.ServiceRuleManager;
+import com.tencent.polaris.client.pb.ModelProto;
+import com.tencent.polaris.client.pb.RoutingProto;
+
+import org.springframework.util.CollectionUtils;
+
+/**
+ * Resolve label expressions from routing rules.
+ * @author lepdou 2022-05-19
+ */
+public class RouterRuleLabelResolver {
+
+ private final ServiceRuleManager serviceRuleManager;
+
+ public RouterRuleLabelResolver(ServiceRuleManager serviceRuleManager) {
+ this.serviceRuleManager = serviceRuleManager;
+ }
+
+ public Set getExpressionLabelKeys(String namespace, String sourceService, String dstService) {
+ List rules = serviceRuleManager.getServiceRouterRule(namespace, sourceService, dstService);
+
+ if (CollectionUtils.isEmpty(rules)) {
+ return Collections.emptySet();
+ }
+
+ Set expressionLabels = new HashSet<>();
+
+ for (RoutingProto.Route rule : rules) {
+ List sources = rule.getSourcesList();
+ if (CollectionUtils.isEmpty(sources)) {
+ continue;
+ }
+ for (RoutingProto.Source source : sources) {
+ Map labels = source.getMetadataMap();
+ if (CollectionUtils.isEmpty(labels)) {
+ continue;
+ }
+ for (String labelKey : labels.keySet()) {
+ if (ExpressionLabelUtils.isExpressionLabel(labelKey)) {
+ expressionLabels.add(labelKey);
+ }
+ }
+ }
+ }
+
+ return expressionLabels;
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/SimpleLoadBalancer.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/SimpleLoadBalancer.java
new file mode 100644
index 000000000..c8ab04c3c
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/SimpleLoadBalancer.java
@@ -0,0 +1,63 @@
+/*
+ * Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
+ *
+ * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ */
+
+package com.tencent.cloud.polaris.router;
+
+import java.util.List;
+
+import com.netflix.loadbalancer.ILoadBalancer;
+import com.netflix.loadbalancer.Server;
+
+/**
+ * Simple load balancer only for getting and setting servers.
+ *
+ *@author lepdou 2022-05-17
+ */
+public class SimpleLoadBalancer implements ILoadBalancer {
+ private List servers;
+
+ @Override
+ public void addServers(List newServers) {
+ this.servers = newServers;
+ }
+
+ @Override
+ public Server chooseServer(Object key) {
+ return null;
+ }
+
+ @Override
+ public void markServerDown(Server server) {
+
+ }
+
+ @Override
+ public List getServerList(boolean availableOnly) {
+ return servers;
+ }
+
+ @Override
+ public List getReachableServers() {
+ return servers;
+ }
+
+ @Override
+ public List getAllServers() {
+ return servers;
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/FeignConfiguration.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/FeignConfiguration.java
new file mode 100644
index 000000000..d5d22444e
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/FeignConfiguration.java
@@ -0,0 +1,44 @@
+/*
+ * 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.tencent.cloud.polaris.router.feign.PolarisFeignLoadBalancer;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.cloud.netflix.ribbon.ServerIntrospector;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * configuration for feign component.
+ *
+ *@author lepdou 2022-05-16
+ */
+@Configuration
+public class FeignConfiguration {
+
+ @Bean
+ @ConditionalOnMissingBean
+ public PolarisFeignLoadBalancer polarisFeignLoadBalancer(ILoadBalancer lb, IClientConfig clientConfig,
+ ServerIntrospector serverIntrospector) {
+ return new PolarisFeignLoadBalancer(lb, clientConfig, serverIntrospector);
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RibbonConfiguration.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RibbonConfiguration.java
new file mode 100644
index 000000000..d139bf7b3
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RibbonConfiguration.java
@@ -0,0 +1,43 @@
+/*
+ * 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.IRule;
+import com.tencent.cloud.polaris.loadbalancer.config.PolarisLoadBalancerProperties;
+import com.tencent.cloud.polaris.router.PolarisLoadBalancerCompositeRule;
+import com.tencent.polaris.router.api.core.RouterAPI;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * Auto configuration for ribbon components.
+ * @author lepdou 2022-05-17
+ */
+@Configuration
+public class RibbonConfiguration {
+
+ @Bean
+ public IRule polarisLoadBalancerCompositeRule(RouterAPI routerAPI,
+ PolarisLoadBalancerProperties polarisLoadBalancerProperties,
+ IClientConfig iClientConfig) {
+ return new PolarisLoadBalancerCompositeRule(routerAPI, polarisLoadBalancerProperties, iClientConfig);
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RouterAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RouterAutoConfiguration.java
new file mode 100644
index 000000000..5065b09b5
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RouterAutoConfiguration.java
@@ -0,0 +1,69 @@
+/*
+ * 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.common.metadata.config.MetadataLocalProperties;
+import com.tencent.cloud.polaris.context.ServiceRuleManager;
+import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
+import com.tencent.cloud.polaris.router.feign.PolarisCachingSpringLoadBalanceFactory;
+import com.tencent.cloud.polaris.router.feign.RouterLabelInterceptor;
+import com.tencent.cloud.polaris.router.resttemplate.PolarisLoadBalancerBeanPostProcessor;
+import com.tencent.cloud.polaris.router.spi.RouterLabelResolver;
+
+import org.springframework.cloud.netflix.ribbon.RibbonClients;
+import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.annotation.Order;
+import org.springframework.lang.Nullable;
+
+import static org.springframework.core.Ordered.HIGHEST_PRECEDENCE;
+
+/**
+ * router module auto configuration.
+ *
+ *@author lepdou 2022-05-11
+ */
+@Configuration
+@RibbonClients(defaultConfiguration = {FeignConfiguration.class, RibbonConfiguration.class})
+public class RouterAutoConfiguration {
+
+ @Bean
+ public RouterLabelInterceptor routerLabelInterceptor(@Nullable RouterLabelResolver resolver,
+ MetadataLocalProperties metadataLocalProperties,
+ RouterRuleLabelResolver routerRuleLabelResolver) {
+ return new RouterLabelInterceptor(resolver, metadataLocalProperties, routerRuleLabelResolver);
+ }
+
+ @Bean
+ public PolarisCachingSpringLoadBalanceFactory polarisCachingSpringLoadBalanceFactory(SpringClientFactory factory) {
+ return new PolarisCachingSpringLoadBalanceFactory(factory);
+ }
+
+ @Bean
+ @Order(HIGHEST_PRECEDENCE)
+ public PolarisLoadBalancerBeanPostProcessor polarisLoadBalancerBeanPostProcessor() {
+ return new PolarisLoadBalancerBeanPostProcessor();
+ }
+
+ @Bean
+ public RouterRuleLabelResolver routerRuleLabelResolver(ServiceRuleManager serviceRuleManager) {
+ return new RouterRuleLabelResolver(serviceRuleManager);
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/FeignExpressionLabelUtils.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/FeignExpressionLabelUtils.java
new file mode 100644
index 000000000..cf4408d37
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/FeignExpressionLabelUtils.java
@@ -0,0 +1,81 @@
+/*
+ * 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.feign;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import com.tencent.cloud.common.util.ExpressionLabelUtils;
+import feign.RequestTemplate;
+import org.apache.commons.lang.StringUtils;
+
+import org.springframework.util.CollectionUtils;
+
+/**
+ * Resolve rule expression label from feign request.
+ * @author lepdou 2022-05-20
+ */
+public class FeignExpressionLabelUtils {
+
+ public static Map resolve(RequestTemplate request, Set labelKeys) {
+ if (CollectionUtils.isEmpty(labelKeys)) {
+ return Collections.emptyMap();
+ }
+
+ Map labels = new HashMap<>();
+
+ for (String labelKey : labelKeys) {
+ if (StringUtils.startsWithIgnoreCase(labelKey, ExpressionLabelUtils.LABEL_HEADER_PREFIX)) {
+ String headerKey = ExpressionLabelUtils.parseHeaderKey(labelKey);
+ if (StringUtils.isBlank(headerKey)) {
+ continue;
+ }
+ labels.put(labelKey, getHeaderValue(request, headerKey));
+ }
+ else if (StringUtils.startsWithIgnoreCase(labelKey, ExpressionLabelUtils.LABEL_QUERY_PREFIX)) {
+ String queryKey = ExpressionLabelUtils.parseQueryKey(labelKey);
+ if (StringUtils.isBlank(queryKey)) {
+ continue;
+ }
+ labels.put(labelKey, getQueryValue(request, queryKey));
+ }
+ else if (StringUtils.equalsIgnoreCase(ExpressionLabelUtils.LABEL_METHOD, labelKey)) {
+ labels.put(labelKey, request.method());
+ }
+ else if (StringUtils.equalsIgnoreCase(ExpressionLabelUtils.LABEL_URI, labelKey)) {
+ labels.put(labelKey, request.request().url());
+ }
+ }
+
+ return labels;
+ }
+
+ public static String getHeaderValue(RequestTemplate request, String key) {
+ Map> headers = request.headers();
+ return ExpressionLabelUtils.getFirstValue(headers, key);
+
+ }
+
+ public static String getQueryValue(RequestTemplate request, String key) {
+ return ExpressionLabelUtils.getFirstValue(request.queries(), key);
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/PolarisCachingSpringLoadBalanceFactory.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/PolarisCachingSpringLoadBalanceFactory.java
new file mode 100644
index 000000000..2c15ce790
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/PolarisCachingSpringLoadBalanceFactory.java
@@ -0,0 +1,72 @@
+/*
+ * Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
+ *
+ * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ */
+
+package com.tencent.cloud.polaris.router.feign;
+
+import java.util.Map;
+
+import com.netflix.client.config.IClientConfig;
+import com.netflix.loadbalancer.ILoadBalancer;
+
+import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryFactory;
+import org.springframework.cloud.netflix.ribbon.ServerIntrospector;
+import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
+import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory;
+import org.springframework.cloud.openfeign.ribbon.FeignLoadBalancer;
+import org.springframework.util.ConcurrentReferenceHashMap;
+
+/**
+ * Extends CachingSpringLoadBalancerFactory to be able to create PolarisFeignLoadBalance.
+ *
+ *@author lepdou 2022-05-16
+ */
+public class PolarisCachingSpringLoadBalanceFactory extends CachingSpringLoadBalancerFactory {
+
+ private final Map cache = new ConcurrentReferenceHashMap<>();
+
+ public PolarisCachingSpringLoadBalanceFactory(SpringClientFactory factory) {
+ super(factory);
+ }
+
+ public PolarisCachingSpringLoadBalanceFactory(SpringClientFactory factory,
+ LoadBalancedRetryFactory loadBalancedRetryPolicyFactory) {
+ super(factory, loadBalancedRetryPolicyFactory);
+ }
+
+ @Override
+ public FeignLoadBalancer create(String clientName) {
+ FeignLoadBalancer client = this.cache.get(clientName);
+ if (client != null) {
+ return client;
+ }
+
+ IClientConfig config = this.factory.getClientConfig(clientName);
+ ILoadBalancer lb = this.factory.getLoadBalancer(clientName);
+ ServerIntrospector serverIntrospector = this.factory.getInstance(clientName, ServerIntrospector.class);
+
+ FeignLoadBalancer loadBalancer = new PolarisFeignLoadBalancer(lb, config, serverIntrospector);
+
+ //There is a concurrency problem here.
+ //When the concurrency is high, it may cause a service to create multiple FeignLoadBalancers.
+ //But there is no concurrency control in CachingSpringLoadBalancerFactory,
+ //so no locks will be added here for the time being
+ cache.putIfAbsent(clientName, loadBalancer);
+
+ return loadBalancer;
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/PolarisFeignLoadBalancer.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/PolarisFeignLoadBalancer.java
new file mode 100644
index 000000000..067332dd6
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/PolarisFeignLoadBalancer.java
@@ -0,0 +1,76 @@
+/*
+ * Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
+ *
+ * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ */
+
+package com.tencent.cloud.polaris.router.feign;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.netflix.client.config.IClientConfig;
+import com.netflix.loadbalancer.ILoadBalancer;
+import com.netflix.loadbalancer.reactive.LoadBalancerCommand;
+import com.tencent.cloud.common.util.ExpressionLabelUtils;
+import com.tencent.cloud.common.util.JacksonUtils;
+import com.tencent.cloud.polaris.router.PolarisRouterContext;
+import com.tencent.cloud.polaris.router.RouterConstants;
+
+import org.springframework.cloud.netflix.ribbon.ServerIntrospector;
+import org.springframework.cloud.openfeign.ribbon.FeignLoadBalancer;
+import org.springframework.util.CollectionUtils;
+
+/**
+ * In order to pass router context for {@link com.tencent.cloud.polaris.router.PolarisLoadBalancerCompositeRule}.
+ *
+ *@author lepdou 2022-05-16
+ */
+public class PolarisFeignLoadBalancer extends FeignLoadBalancer {
+
+ public PolarisFeignLoadBalancer(ILoadBalancer lb, IClientConfig clientConfig, ServerIntrospector serverIntrospector) {
+ super(lb, clientConfig, serverIntrospector);
+ }
+
+ @Override
+ protected void customizeLoadBalancerCommandBuilder(RibbonRequest request, IClientConfig config,
+ LoadBalancerCommand.Builder builder) {
+ Map> headers = request.getRequest().headers();
+ Collection labelHeaderValues = headers.get(RouterConstants.ROUTER_LABEL_HEADER);
+
+ if (CollectionUtils.isEmpty(labelHeaderValues)) {
+ builder.withServerLocator(null);
+ return;
+ }
+
+ PolarisRouterContext routerContext = new PolarisRouterContext();
+
+ labelHeaderValues.forEach(labelHeaderValue -> {
+ Map labels = JacksonUtils.deserialize2Map(labelHeaderValue);
+ if (!CollectionUtils.isEmpty(labels)) {
+ Map unescapeLabels = new HashMap<>(labels.size());
+ for (Map.Entry entry : labels.entrySet()) {
+ String escapedKey = ExpressionLabelUtils.unescape(entry.getKey());
+ String escapedValue = ExpressionLabelUtils.unescape(entry.getValue());
+ unescapeLabels.put(escapedKey, escapedValue);
+ }
+ routerContext.setLabels(unescapeLabels);
+ }
+ });
+
+ builder.withServerLocator(routerContext);
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/RouterLabelInterceptor.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/RouterLabelInterceptor.java
new file mode 100644
index 000000000..48c3fb667
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/RouterLabelInterceptor.java
@@ -0,0 +1,123 @@
+/*
+ * 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.feign;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import com.tencent.cloud.common.metadata.MetadataContext;
+import com.tencent.cloud.common.metadata.MetadataContextHolder;
+import com.tencent.cloud.common.metadata.config.MetadataLocalProperties;
+import com.tencent.cloud.common.util.ExpressionLabelUtils;
+import com.tencent.cloud.common.util.JacksonUtils;
+import com.tencent.cloud.polaris.router.RouterConstants;
+import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
+import com.tencent.cloud.polaris.router.spi.RouterLabelResolver;
+import feign.RequestInterceptor;
+import feign.RequestTemplate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.springframework.core.Ordered;
+import org.springframework.util.CollectionUtils;
+
+/**
+ * Resolver labels from request.
+ *
+ *@author lepdou 2022-05-12
+ */
+public class RouterLabelInterceptor implements RequestInterceptor, Ordered {
+ private static final Logger LOGGER = LoggerFactory.getLogger(RouterLabelInterceptor.class);
+
+ private final RouterLabelResolver resolver;
+ private final MetadataLocalProperties metadataLocalProperties;
+ private final RouterRuleLabelResolver routerRuleLabelResolver;
+
+ public RouterLabelInterceptor(RouterLabelResolver resolver,
+ MetadataLocalProperties metadataLocalProperties,
+ RouterRuleLabelResolver routerRuleLabelResolver) {
+ this.resolver = resolver;
+ this.metadataLocalProperties = metadataLocalProperties;
+ this.routerRuleLabelResolver = routerRuleLabelResolver;
+ }
+
+ @Override
+ public int getOrder() {
+ return 0;
+ }
+
+ @Override
+ public void apply(RequestTemplate requestTemplate) {
+ Map labels = new HashMap<>();
+
+ // labels from downstream
+ Map transitiveLabels = MetadataContextHolder.get()
+ .getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE);
+ labels.putAll(transitiveLabels);
+
+ // labels from request
+ if (resolver != null) {
+ try {
+ Map customResolvedLabels = resolver.resolve(requestTemplate);
+ if (!CollectionUtils.isEmpty(customResolvedLabels)) {
+ labels.putAll(customResolvedLabels);
+ }
+ }
+ catch (Throwable t) {
+ LOGGER.error("[SCT][Router] revoke RouterLabelResolver occur some exception. ", t);
+ }
+ }
+
+ // labels from rule expression
+ String peerServiceName = requestTemplate.feignTarget().name();
+ Map ruleExpressionLabels = getRuleExpressionLabels(requestTemplate, peerServiceName);
+ labels.putAll(ruleExpressionLabels);
+
+
+ //local service labels
+ labels.putAll(metadataLocalProperties.getContent());
+
+ // Because when the label is placed in RequestTemplate.header,
+ // RequestTemplate will parse the header according to the regular, which conflicts with the expression.
+ // Avoid conflicts by escaping.
+ Map escapeLabels = new HashMap<>(labels.size());
+ for (Map.Entry entry : labels.entrySet()) {
+ String escapedKey = ExpressionLabelUtils.escape(entry.getKey());
+ String escapedValue = ExpressionLabelUtils.escape(entry.getValue());
+ escapeLabels.put(escapedKey, escapedValue);
+ }
+
+ // pass label by header
+ requestTemplate.header(RouterConstants.ROUTER_LABEL_HEADER, JacksonUtils.serialize2Json(escapeLabels));
+ }
+
+ private Map getRuleExpressionLabels(RequestTemplate requestTemplate, String peerService) {
+ Set labelKeys = routerRuleLabelResolver.getExpressionLabelKeys(MetadataContext.LOCAL_NAMESPACE,
+ MetadataContext.LOCAL_SERVICE, peerService);
+
+ if (CollectionUtils.isEmpty(labelKeys)) {
+ return Collections.emptyMap();
+ }
+
+ return FeignExpressionLabelUtils.resolve(requestTemplate, labelKeys);
+ }
+
+}
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerBeanPostProcessor.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerBeanPostProcessor.java
new file mode 100644
index 000000000..6fe192003
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerBeanPostProcessor.java
@@ -0,0 +1,62 @@
+/*
+ * 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.resttemplate;
+
+import com.tencent.cloud.common.metadata.config.MetadataLocalProperties;
+import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
+import com.tencent.cloud.polaris.router.spi.RouterLabelResolver;
+
+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.LoadBalancerClient;
+import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor;
+import org.springframework.cloud.client.loadbalancer.LoadBalancerRequestFactory;
+
+/**
+ * Replace LoadBalancerInterceptor with PolarisLoadBalancerInterceptor.
+ * PolarisLoadBalancerInterceptor can pass routing context information.
+ *
+ *@author lepdou 2022-05-18
+ */
+public class PolarisLoadBalancerBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware {
+
+ private BeanFactory factory;
+
+ @Override
+ public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
+ this.factory = beanFactory;
+ }
+
+ @Override
+ public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
+ if (bean instanceof LoadBalancerInterceptor) {
+ LoadBalancerRequestFactory requestFactory = this.factory.getBean(LoadBalancerRequestFactory.class);
+ LoadBalancerClient loadBalancerClient = this.factory.getBean(LoadBalancerClient.class);
+ RouterLabelResolver routerLabelResolver = this.factory.getBean(RouterLabelResolver.class);
+ MetadataLocalProperties metadataLocalProperties = this.factory.getBean(MetadataLocalProperties.class);
+ RouterRuleLabelResolver routerRuleLabelResolver = this.factory.getBean(RouterRuleLabelResolver.class);
+
+ return new PolarisLoadBalancerInterceptor(loadBalancerClient, requestFactory,
+ routerLabelResolver, metadataLocalProperties, routerRuleLabelResolver);
+ }
+ return bean;
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerInterceptor.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerInterceptor.java
new file mode 100644
index 000000000..2e3e691f4
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerInterceptor.java
@@ -0,0 +1,143 @@
+/*
+ * 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.resttemplate;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import com.tencent.cloud.common.metadata.MetadataContext;
+import com.tencent.cloud.common.metadata.MetadataContextHolder;
+import com.tencent.cloud.common.metadata.config.MetadataLocalProperties;
+import com.tencent.cloud.common.util.ExpressionLabelUtils;
+import com.tencent.cloud.polaris.router.PolarisRouterContext;
+import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
+import com.tencent.cloud.polaris.router.spi.RouterLabelResolver;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
+import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor;
+import org.springframework.cloud.client.loadbalancer.LoadBalancerRequestFactory;
+import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient;
+import org.springframework.http.HttpRequest;
+import org.springframework.http.client.ClientHttpRequestExecution;
+import org.springframework.http.client.ClientHttpResponse;
+import org.springframework.util.Assert;
+import org.springframework.util.CollectionUtils;
+
+/**
+ * PolarisLoadBalancerInterceptor extends LoadBalancerInterceptor capabilities.
+ * Parses the label from the request and puts it into the RouterContext for routing.
+ *
+ *@author lepdou 2022-05-18
+ */
+public class PolarisLoadBalancerInterceptor extends LoadBalancerInterceptor {
+ private static final Logger LOGGER = LoggerFactory.getLogger(PolarisLoadBalancerInterceptor.class);
+
+ private final LoadBalancerClient loadBalancer;
+ private final LoadBalancerRequestFactory requestFactory;
+ private final RouterLabelResolver resolver;
+ private final MetadataLocalProperties metadataLocalProperties;
+ private final RouterRuleLabelResolver routerRuleLabelResolver;
+
+ private final boolean isRibbonLoadBalanceClient;
+
+ public PolarisLoadBalancerInterceptor(LoadBalancerClient loadBalancer,
+ LoadBalancerRequestFactory requestFactory,
+ RouterLabelResolver resolver,
+ MetadataLocalProperties metadataLocalProperties,
+ RouterRuleLabelResolver routerRuleLabelResolver) {
+ super(loadBalancer, requestFactory);
+ this.loadBalancer = loadBalancer;
+ this.requestFactory = requestFactory;
+ this.resolver = resolver;
+ this.metadataLocalProperties = metadataLocalProperties;
+ this.routerRuleLabelResolver = routerRuleLabelResolver;
+
+ this.isRibbonLoadBalanceClient = loadBalancer instanceof RibbonLoadBalancerClient;
+ }
+
+ @Override
+ public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
+ final URI originalUri = request.getURI();
+ String peerServiceName = originalUri.getHost();
+ Assert.state(peerServiceName != null,
+ "Request URI does not contain a valid hostname: " + originalUri);
+
+ if (isRibbonLoadBalanceClient) {
+ PolarisRouterContext routerContext = genRouterContext(request, body, peerServiceName);
+
+ return ((RibbonLoadBalancerClient) loadBalancer).execute(peerServiceName,
+ this.requestFactory.createRequest(request, body, execution), routerContext);
+ }
+
+ return this.loadBalancer.execute(peerServiceName,
+ this.requestFactory.createRequest(request, body, execution));
+ }
+
+ private PolarisRouterContext genRouterContext(HttpRequest request, byte[] body, String peerServiceName) {
+ Map labels = new HashMap<>();
+
+ // labels from downstream
+ Map transitiveLabels = MetadataContextHolder.get()
+ .getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE);
+ labels.putAll(transitiveLabels);
+
+ // labels from request
+ if (resolver != null) {
+ try {
+ Map customResolvedLabels = resolver.resolve(request, body);
+ if (!CollectionUtils.isEmpty(customResolvedLabels)) {
+ labels.putAll(customResolvedLabels);
+ }
+ }
+ catch (Throwable t) {
+ LOGGER.error("[SCT][Router] revoke RouterLabelResolver occur some exception. ", t);
+ }
+ }
+
+ Map ruleExpressionLabels = getExpressionLabels(request, peerServiceName);
+ if (!CollectionUtils.isEmpty(ruleExpressionLabels)) {
+ labels.putAll(ruleExpressionLabels);
+ }
+
+ //local service labels
+ labels.putAll(metadataLocalProperties.getContent());
+
+ PolarisRouterContext routerContext = new PolarisRouterContext();
+ routerContext.setLabels(labels);
+
+ return routerContext;
+ }
+
+ private Map getExpressionLabels(HttpRequest request, String peerServiceName) {
+ Set labelKeys = routerRuleLabelResolver.getExpressionLabelKeys(MetadataContext.LOCAL_NAMESPACE,
+ MetadataContext.LOCAL_SERVICE, peerServiceName);
+
+ if (CollectionUtils.isEmpty(labelKeys)) {
+ return Collections.emptyMap();
+ }
+
+ return ExpressionLabelUtils.resolve(request, labelKeys);
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/spi/RouterLabelResolver.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/spi/RouterLabelResolver.java
new file mode 100644
index 000000000..8b2f394d5
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/spi/RouterLabelResolver.java
@@ -0,0 +1,48 @@
+/*
+ * 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.spi;
+
+import java.util.Map;
+
+import feign.RequestTemplate;
+
+import org.springframework.http.HttpRequest;
+
+/**
+ * The spi for resolving labels from request.
+ *
+ * @author lepdou 2022-05-11
+ */
+public interface RouterLabelResolver {
+
+ /**
+ * resolve labels from feign request.
+ * @param requestTemplate the feign request.
+ * @return resolved labels
+ */
+ Map resolve(RequestTemplate requestTemplate);
+
+ /**
+ * resolve labels from rest template request.
+ * @param request the rest template request.
+ * @param body the rest template request body.
+ * @return resolved labels
+ */
+ Map resolve(HttpRequest request, byte[] body);
+}
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/resources/META-INF/spring.factories b/spring-cloud-starter-tencent-polaris-router/src/main/resources/META-INF/spring.factories
new file mode 100644
index 000000000..d33dcea7f
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,2 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+ com.tencent.cloud.polaris.router.config.RouterAutoConfiguration
diff --git a/spring-cloud-tencent-commons/pom.xml b/spring-cloud-tencent-commons/pom.xml
index b9b853c2e..eae677526 100644
--- a/spring-cloud-tencent-commons/pom.xml
+++ b/spring-cloud-tencent-commons/pom.xml
@@ -83,6 +83,18 @@
true
+
+ org.springframework.boot
+ spring-boot-starter-web
+ true
+
+
+
+ org.springframework.boot
+ spring-boot-starter-webflux
+ true
+
+
org.springframework.boot
spring-boot-starter-test
diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/constant/MetadataConstant.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/constant/MetadataConstant.java
index ce498126b..d45c71568 100644
--- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/constant/MetadataConstant.java
+++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/constant/MetadataConstant.java
@@ -26,28 +26,6 @@ import org.springframework.core.Ordered;
*/
public final class MetadataConstant {
- /**
- * System metadata key.
- */
- public static class SystemMetadataKey {
-
- /**
- * Peer namespace.
- */
- public static String PEER_NAMESPACE = "PEER_NAMESPACE";
-
- /**
- * Peer service.
- */
- public static String PEER_SERVICE = "PEER_SERVICE";
-
- /**
- * Peer path.
- */
- public static String PEER_PATH = "PEER_PATH";
-
- }
-
/**
* Order of filter, interceptor, ...
*/
diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/MetadataContext.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/MetadataContext.java
index 6f06e811b..f98ea308a 100644
--- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/MetadataContext.java
+++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/MetadataContext.java
@@ -34,6 +34,10 @@ import org.springframework.util.StringUtils;
*/
public class MetadataContext {
+ /**
+ * transitive context.
+ */
+ public static final String FRAGMENT_TRANSITIVE = "transitive";
/**
* Namespace of local instance.
*/
@@ -44,15 +48,8 @@ public class MetadataContext {
*/
public static String LOCAL_SERVICE;
- /**
- * Transitive custom metadata content.
- */
- private final Map transitiveCustomMetadata;
- /**
- * System metadata content.
- */
- private final Map systemMetadata;
+ private final Map> fragmentContexts;
static {
String namespace = ApplicationContextAwareUtils
@@ -74,47 +71,43 @@ public class MetadataContext {
}
public MetadataContext() {
- this.transitiveCustomMetadata = new ConcurrentHashMap<>();
- this.systemMetadata = new ConcurrentHashMap<>();
- }
-
- public Map getAllTransitiveCustomMetadata() {
- return Collections.unmodifiableMap(this.transitiveCustomMetadata);
+ this.fragmentContexts = new ConcurrentHashMap<>();
}
- public String getTransitiveCustomMetadata(String key) {
- return this.transitiveCustomMetadata.get(key);
- }
- public void putTransitiveCustomMetadata(String key, String value) {
- this.transitiveCustomMetadata.put(key, value);
- }
-
- public void putAllTransitiveCustomMetadata(Map customMetadata) {
- this.transitiveCustomMetadata.putAll(customMetadata);
- }
-
- public Map getAllSystemMetadata() {
- return Collections.unmodifiableMap(this.systemMetadata);
+ public Map getFragmentContext(String fragment) {
+ Map fragmentContext = fragmentContexts.get(fragment);
+ if (fragmentContext == null) {
+ return Collections.emptyMap();
+ }
+ return Collections.unmodifiableMap(fragmentContext);
}
- public String getSystemMetadata(String key) {
- return this.systemMetadata.get(key);
+ public String getContext(String fragment, String key) {
+ Map fragmentContext = fragmentContexts.get(fragment);
+ if (fragmentContext == null) {
+ return null;
+ }
+ return fragmentContext.get(key);
}
- public void putSystemMetadata(String key, String value) {
- this.systemMetadata.put(key, value);
+ public void putContext(String fragment, String key, String value) {
+ Map fragmentContext = fragmentContexts.get(fragment);
+ if (fragmentContext == null) {
+ fragmentContext = new ConcurrentHashMap<>();
+ fragmentContexts.put(fragment, fragmentContext);
+ }
+ fragmentContext.put(key, value);
}
- public void putAllSystemMetadata(Map systemMetadata) {
- this.systemMetadata.putAll(systemMetadata);
+ public void putFragmentContext(String fragment, Map context) {
+ fragmentContexts.put(fragment, context);
}
@Override
public String toString() {
- return "MetadataContext{" + "transitiveCustomMetadata="
- + JacksonUtils.serialize2Json(transitiveCustomMetadata)
- + ", systemMetadata=" + JacksonUtils.serialize2Json(systemMetadata) + '}';
+ return "MetadataContext{" +
+ "fragmentContexts=" + JacksonUtils.serialize2Json(fragmentContexts) +
+ '}';
}
-
}
diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/MetadataContextHolder.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/MetadataContextHolder.java
index b8811f8a5..d12dd79e2 100644
--- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/MetadataContextHolder.java
+++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/MetadataContextHolder.java
@@ -13,6 +13,7 @@
* 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;
@@ -57,7 +58,7 @@ public final class MetadataContextHolder {
Map transitiveMetadataMap = getTransitiveMetadataMap(
metadataLocalProperties.getContent(),
metadataLocalProperties.getTransitive());
- metadataContext.putAllTransitiveCustomMetadata(transitiveMetadataMap);
+ metadataContext.putFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE, transitiveMetadataMap);
METADATA_CONTEXT.set(metadataContext);
}
@@ -92,20 +93,15 @@ public final class MetadataContextHolder {
/**
* Save metadata map to thread local.
* @param customMetadataMap custom metadata collection
- * @param systemMetadataMap system metadata collection
*/
- public static void init(Map customMetadataMap,
- Map systemMetadataMap) {
+ public static void init(Map customMetadataMap) {
// Init ThreadLocal.
MetadataContextHolder.remove();
MetadataContext metadataContext = MetadataContextHolder.get();
// Save to ThreadLocal.
if (!CollectionUtils.isEmpty(customMetadataMap)) {
- metadataContext.putAllTransitiveCustomMetadata(customMetadataMap);
- }
- if (!CollectionUtils.isEmpty(systemMetadataMap)) {
- metadataContext.putAllSystemMetadata(systemMetadataMap);
+ metadataContext.putFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE, customMetadataMap);
}
MetadataContextHolder.set(metadataContext);
}
diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/config/MetadataAutoConfiguration.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/config/MetadataAutoConfiguration.java
index b0e85c4ae..6188c61ae 100644
--- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/config/MetadataAutoConfiguration.java
+++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/config/MetadataAutoConfiguration.java
@@ -18,10 +18,7 @@
package com.tencent.cloud.common.metadata.config;
-import com.netflix.zuul.ZuulFilter;
import com.tencent.cloud.common.metadata.filter.gateway.MetadataFirstScgFilter;
-import com.tencent.cloud.common.metadata.filter.gateway.MetadataFirstZuulFilter;
-import com.tencent.cloud.common.metadata.interceptor.feign.MetadataFirstFeignInterceptor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.cloud.gateway.filter.GlobalFilter;
@@ -45,34 +42,6 @@ public class MetadataAutoConfiguration {
return new MetadataLocalProperties();
}
- /**
- * Create when Feign exists.
- */
- @Configuration
- @ConditionalOnClass(name = "feign.Feign")
- static class MetadataFeignInterceptorConfig {
-
- @Bean
- public MetadataFirstFeignInterceptor metadataFirstFeignInterceptor() {
- return new MetadataFirstFeignInterceptor();
- }
-
- }
-
- /**
- * 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.
*/
diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/filter/gateway/MetadataFirstScgFilter.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/filter/gateway/MetadataFirstScgFilter.java
index 21c6c4d54..a79ba5323 100644
--- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/filter/gateway/MetadataFirstScgFilter.java
+++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/filter/gateway/MetadataFirstScgFilter.java
@@ -25,12 +25,10 @@ import reactor.core.publisher.Mono;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
-import org.springframework.cloud.gateway.route.Route;
import org.springframework.core.Ordered;
import org.springframework.web.server.ServerWebExchange;
import static org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter.ROUTE_TO_URL_FILTER_ORDER;
-import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR;
/**
* Scg output first filter used for setting peer info in context.
@@ -51,9 +49,6 @@ public class MetadataFirstScgFilter implements GlobalFilter, Ordered {
@Override
public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
- // get request context
- Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);
-
// get metadata of current thread
MetadataContext metadataContext = exchange
.getAttribute(MetadataConstant.HeaderName.METADATA_CONTEXT);
@@ -61,23 +56,6 @@ public class MetadataFirstScgFilter implements GlobalFilter, Ordered {
metadataContext = MetadataContextHolder.get();
}
- // TODO The peer namespace is temporarily the same as the local namespace
- metadataContext.putSystemMetadata(
- MetadataConstant.SystemMetadataKey.PEER_NAMESPACE,
- MetadataContext.LOCAL_NAMESPACE);
- if (route != null) {
- metadataContext.putSystemMetadata(
- MetadataConstant.SystemMetadataKey.PEER_SERVICE,
- route.getUri().getAuthority());
- }
- else {
- metadataContext.putSystemMetadata(
- MetadataConstant.SystemMetadataKey.PEER_SERVICE,
- exchange.getRequest().getURI().getAuthority());
- }
- metadataContext.putSystemMetadata(MetadataConstant.SystemMetadataKey.PEER_PATH,
- exchange.getRequest().getURI().getPath());
-
exchange.getAttributes().put(MetadataConstant.HeaderName.METADATA_CONTEXT,
metadataContext);
diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/filter/gateway/MetadataFirstZuulFilter.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/filter/gateway/MetadataFirstZuulFilter.java
deleted file mode 100644
index acb2acc87..000000000
--- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/filter/gateway/MetadataFirstZuulFilter.java
+++ /dev/null
@@ -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;
- }
-
-}
diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/interceptor/feign/MetadataFirstFeignInterceptor.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/interceptor/feign/MetadataFirstFeignInterceptor.java
deleted file mode 100644
index 18f5390ab..000000000
--- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/interceptor/feign/MetadataFirstFeignInterceptor.java
+++ /dev/null
@@ -1,55 +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.interceptor.feign;
-
-import com.tencent.cloud.common.constant.MetadataConstant;
-import com.tencent.cloud.common.metadata.MetadataContext;
-import com.tencent.cloud.common.metadata.MetadataContextHolder;
-import feign.RequestInterceptor;
-import feign.RequestTemplate;
-
-import org.springframework.core.Ordered;
-
-/**
- * Interceptor used for setting peer info in context.
- *
- * @author Haotian Zhang
- */
-public class MetadataFirstFeignInterceptor implements RequestInterceptor, Ordered {
-
- @Override
- public int getOrder() {
- return MetadataConstant.OrderConstant.METADATA_FIRST_FEIGN_INTERCEPTOR_ORDER;
- }
-
- @Override
- public void apply(RequestTemplate requestTemplate) {
- // get metadata of current thread
- MetadataContext metadataContext = MetadataContextHolder.get();
-
- // TODO The peer namespace is temporarily the same as the local 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());
- }
-
-}
diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/pojo/PolarisServer.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/pojo/PolarisServer.java
index be55ed31e..fa458f5c3 100644
--- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/pojo/PolarisServer.java
+++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/pojo/PolarisServer.java
@@ -48,6 +48,7 @@ public class PolarisServer extends Server {
}
this.serviceInstances = serviceInstances;
this.instance = instance;
+ this.setAlive(true);
this.metaInfo = new MetaInfo() {
@Override
public String getAppName() {
diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/ExpressionLabelUtils.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/ExpressionLabelUtils.java
new file mode 100644
index 000000000..26557aa3d
--- /dev/null
+++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/ExpressionLabelUtils.java
@@ -0,0 +1,323 @@
+/*
+ * 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.util;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.lang.StringUtils;
+
+import org.springframework.http.HttpCookie;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpRequest;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.server.ServerWebExchange;
+
+/**
+ * the utils for parse label expression.
+ *
+ *@author lepdou 2022-05-13
+ */
+public class ExpressionLabelUtils {
+
+ /**
+ * the expression prefix of header label.
+ */
+ public static final String LABEL_HEADER_PREFIX = "${http.header.";
+ /**
+ * the length of expression header label prefix.
+ */
+ public static final int LABEL_HEADER_PREFIX_LEN = LABEL_HEADER_PREFIX.length();
+ /**
+ * the expression prefix of query.
+ */
+ public static final String LABEL_QUERY_PREFIX = "${http.query.";
+ /**
+ * the length of expression query label prefix.
+ */
+ public static final int LABEL_QUERY_PREFIX_LEN = LABEL_QUERY_PREFIX.length();
+ /**
+ * the expression prefix of cookie.
+ */
+ public static final String LABEL_COOKIE_PREFIX = "${http.cookie.";
+ /**
+ * the length of expression cookie label prefix.
+ */
+ public static final int LABEL_COOKIE_PREFIX_LEN = LABEL_COOKIE_PREFIX.length();
+ /**
+ * the expression of method.
+ */
+ public static final String LABEL_METHOD = "${http.method}";
+ /**
+ * the expression of uri.
+ */
+ public static final String LABEL_URI = "${http.uri}";
+ /**
+ * the prefix of expression.
+ */
+ public static final String LABEL_PREFIX = "${";
+ /**
+ * the suffix of expression.
+ */
+ public static final String LABEL_SUFFIX = "}";
+ /**
+ * the escape prefix of label.
+ */
+ public static final String LABEL_ESCAPE_PREFIX = "$$$$";
+
+ public static boolean isExpressionLabel(String labelKey) {
+ if (StringUtils.isEmpty(labelKey)) {
+ return false;
+ }
+ if (StringUtils.equalsIgnoreCase(LABEL_METHOD, labelKey) ||
+ StringUtils.startsWithIgnoreCase(LABEL_URI, labelKey)) {
+ return true;
+ }
+ return (StringUtils.startsWithIgnoreCase(labelKey, LABEL_HEADER_PREFIX) ||
+ StringUtils.startsWithIgnoreCase(labelKey, LABEL_QUERY_PREFIX) ||
+ StringUtils.startsWithIgnoreCase(labelKey, LABEL_COOKIE_PREFIX))
+ && StringUtils.endsWith(labelKey, LABEL_SUFFIX);
+ }
+
+ public static String escape(String str) {
+ return StringUtils.replace(str, LABEL_PREFIX, LABEL_ESCAPE_PREFIX);
+ }
+
+ public static String unescape(String str) {
+ return StringUtils.replace(str, LABEL_ESCAPE_PREFIX, LABEL_PREFIX);
+ }
+
+ public static Map resolve(HttpServletRequest request, Set labelKeys) {
+ if (CollectionUtils.isEmpty(labelKeys)) {
+ return Collections.emptyMap();
+ }
+
+ Map labels = new HashMap<>();
+
+ for (String labelKey : labelKeys) {
+ if (StringUtils.startsWithIgnoreCase(labelKey, LABEL_HEADER_PREFIX)) {
+ String headerKey = parseHeaderKey(labelKey);
+ if (StringUtils.isBlank(headerKey)) {
+ continue;
+ }
+ labels.put(labelKey, request.getHeader(headerKey));
+ }
+ else if (StringUtils.startsWithIgnoreCase(labelKey, LABEL_QUERY_PREFIX)) {
+ String queryKey = parseQueryKey(labelKey);
+ if (StringUtils.isBlank(queryKey)) {
+ continue;
+ }
+ labels.put(labelKey, getQueryValue(request.getQueryString(), queryKey));
+ }
+ else if (StringUtils.startsWithIgnoreCase(labelKey, LABEL_COOKIE_PREFIX)) {
+ String cookieKey = parseCookieKey(labelKey);
+ if (StringUtils.isBlank(cookieKey)) {
+ continue;
+ }
+ labels.put(labelKey, getCookieValue(request.getCookies(), cookieKey));
+ }
+ else if (StringUtils.equalsIgnoreCase(LABEL_METHOD, labelKey)) {
+ labels.put(labelKey, request.getMethod());
+ }
+ else if (StringUtils.equalsIgnoreCase(LABEL_URI, labelKey)) {
+ labels.put(labelKey, request.getRequestURI());
+ }
+ }
+
+ return labels;
+ }
+
+ public static Map resolve(ServerWebExchange exchange, Set labelKeys) {
+ if (CollectionUtils.isEmpty(labelKeys)) {
+ return Collections.emptyMap();
+ }
+
+ Map labels = new HashMap<>();
+
+ for (String labelKey : labelKeys) {
+ if (StringUtils.startsWithIgnoreCase(labelKey, LABEL_HEADER_PREFIX)) {
+ String headerKey = parseHeaderKey(labelKey);
+ if (StringUtils.isBlank(headerKey)) {
+ continue;
+ }
+ labels.put(labelKey, getHeaderValue(exchange.getRequest(), headerKey));
+ }
+ else if (StringUtils.startsWithIgnoreCase(labelKey, LABEL_QUERY_PREFIX)) {
+ String queryKey = parseQueryKey(labelKey);
+ if (StringUtils.isBlank(queryKey)) {
+ continue;
+ }
+ labels.put(labelKey, getQueryValue(exchange.getRequest(), queryKey));
+ }
+ else if (StringUtils.startsWithIgnoreCase(labelKey, LABEL_COOKIE_PREFIX)) {
+ String cookieKey = parseCookieKey(labelKey);
+ if (StringUtils.isBlank(cookieKey)) {
+ continue;
+ }
+ labels.put(labelKey, getCookieValue(exchange.getRequest(), cookieKey));
+ }
+ else if (StringUtils.equalsIgnoreCase(LABEL_METHOD, labelKey)) {
+ labels.put(labelKey, exchange.getRequest().getMethodValue());
+ }
+ else if (StringUtils.equalsIgnoreCase(LABEL_URI, labelKey)) {
+ labels.put(labelKey, exchange.getRequest().getURI().getPath());
+ }
+ }
+
+ return labels;
+ }
+
+ public static Map resolve(HttpRequest request, Set labelKeys) {
+ if (CollectionUtils.isEmpty(labelKeys)) {
+ return Collections.emptyMap();
+ }
+
+ Map labels = new HashMap<>();
+
+ for (String labelKey : labelKeys) {
+ if (StringUtils.startsWithIgnoreCase(labelKey, LABEL_HEADER_PREFIX)) {
+ String headerKey = parseHeaderKey(labelKey);
+ if (StringUtils.isBlank(headerKey)) {
+ continue;
+ }
+ labels.put(labelKey, getHeaderValue(request, headerKey));
+ }
+ else if (StringUtils.startsWithIgnoreCase(labelKey, LABEL_QUERY_PREFIX)) {
+ String queryKey = parseQueryKey(labelKey);
+ if (StringUtils.isBlank(queryKey)) {
+ continue;
+ }
+ labels.put(labelKey, getQueryValue(request, queryKey));
+ }
+ else if (StringUtils.equalsIgnoreCase(LABEL_METHOD, labelKey)) {
+ labels.put(labelKey, request.getMethodValue());
+ }
+ else if (StringUtils.equalsIgnoreCase(LABEL_URI, labelKey)) {
+ labels.put(labelKey, request.getURI().getPath());
+ }
+ }
+
+ return labels;
+ }
+
+ public static String parseHeaderKey(String expression) {
+ return expression.substring(LABEL_HEADER_PREFIX_LEN, expression.length() - 1);
+ }
+
+ public static String parseQueryKey(String expression) {
+ return expression.substring(LABEL_QUERY_PREFIX_LEN, expression.length() - 1);
+ }
+
+ public static String parseCookieKey(String expression) {
+ return expression.substring(LABEL_COOKIE_PREFIX_LEN, expression.length() - 1);
+ }
+
+ public static String getQueryValue(String queryString, String queryKey) {
+ if (StringUtils.isBlank(queryString)) {
+ return StringUtils.EMPTY;
+ }
+ String[] queries = StringUtils.split(queryString, "&");
+ if (queries == null || queries.length == 0) {
+ return StringUtils.EMPTY;
+ }
+ for (String query : queries) {
+ String[] queryKV = StringUtils.split(query, "=");
+ if (queryKV != null && queryKV.length == 2 && StringUtils.equals(queryKV[0], queryKey)) {
+ return queryKV[1];
+ }
+ }
+ return StringUtils.EMPTY;
+ }
+
+ public static String getCookieValue(Cookie[] cookies, String key) {
+ if (cookies == null || cookies.length == 0) {
+ return StringUtils.EMPTY;
+ }
+ for (Cookie cookie : cookies) {
+ if (StringUtils.equals(cookie.getName(), key)) {
+ return cookie.getValue();
+ }
+ }
+ return StringUtils.EMPTY;
+ }
+
+ public static String getHeaderValue(ServerHttpRequest request, String key) {
+ String value = request.getHeaders().getFirst(key);
+ if (value == null) {
+ return StringUtils.EMPTY;
+ }
+ return value;
+ }
+
+ public static String getQueryValue(ServerHttpRequest request, String key) {
+ MultiValueMap queries = request.getQueryParams();
+ if (CollectionUtils.isEmpty(queries)) {
+ return StringUtils.EMPTY;
+ }
+ String value = queries.getFirst(key);
+ if (value == null) {
+ return StringUtils.EMPTY;
+ }
+ return value;
+ }
+
+ public static String getCookieValue(ServerHttpRequest request, String key) {
+ HttpCookie cookie = request.getCookies().getFirst(key);
+ if (cookie == null) {
+ return StringUtils.EMPTY;
+ }
+ return cookie.getValue();
+ }
+
+ public static String getHeaderValue(HttpRequest request, String key) {
+ HttpHeaders headers = request.getHeaders();
+ return headers.getFirst(key);
+ }
+
+ public static String getQueryValue(HttpRequest request, String key) {
+ String query = request.getURI().getQuery();
+ return getQueryValue(query, key);
+ }
+
+ public static String getFirstValue(Map> valueMaps, String key) {
+ if (CollectionUtils.isEmpty(valueMaps)) {
+ return StringUtils.EMPTY;
+ }
+
+ Collection values = valueMaps.get(key);
+
+ if (CollectionUtils.isEmpty(values)) {
+ return StringUtils.EMPTY;
+ }
+
+ for (String value : values) {
+ return value;
+ }
+
+ return StringUtils.EMPTY;
+ }
+}
diff --git a/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/metadata/MetadataContextHolderTest.java b/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/metadata/MetadataContextHolderTest.java
index 6883ae50d..39375d753 100644
--- a/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/metadata/MetadataContextHolderTest.java
+++ b/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/metadata/MetadataContextHolderTest.java
@@ -13,6 +13,7 @@
* 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;
@@ -29,7 +30,7 @@ import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
/**
- * Test for {@link MetadataContextHolder}
+ * Test for {@link MetadataContextHolder}.
*
* @author Haotian Zhang
*/
@@ -45,10 +46,10 @@ public class MetadataContextHolderTest {
customMetadata.put("a", "1");
customMetadata.put("b", "2");
MetadataContext metadataContext = MetadataContextHolder.get();
- metadataContext.putAllTransitiveCustomMetadata(customMetadata);
+ metadataContext.putFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE, customMetadata);
MetadataContextHolder.set(metadataContext);
- customMetadata = MetadataContextHolder.get().getAllTransitiveCustomMetadata();
+ customMetadata = MetadataContextHolder.get().getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE);
Assertions.assertThat(customMetadata.get("a")).isEqualTo("1");
Assertions.assertThat(customMetadata.get("b")).isEqualTo("2");
@@ -58,10 +59,9 @@ public class MetadataContextHolderTest {
customMetadata.put("a", "1");
customMetadata.put("b", "22");
customMetadata.put("c", "3");
- Map systemMetadata = new HashMap<>();
- MetadataContextHolder.init(customMetadata, systemMetadata);
+ MetadataContextHolder.init(customMetadata);
metadataContext = MetadataContextHolder.get();
- customMetadata = metadataContext.getAllTransitiveCustomMetadata();
+ customMetadata = metadataContext.getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE);
Assertions.assertThat(customMetadata.get("a")).isEqualTo("1");
Assertions.assertThat(customMetadata.get("b")).isEqualTo("22");
Assertions.assertThat(customMetadata.get("c")).isEqualTo("3");
diff --git a/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/metadata/config/MetadataAutoConfigurationTest.java b/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/metadata/config/MetadataAutoConfigurationTest.java
index bcf42ee14..fb19efb18 100644
--- a/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/metadata/config/MetadataAutoConfigurationTest.java
+++ b/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/metadata/config/MetadataAutoConfigurationTest.java
@@ -19,8 +19,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.interceptor.feign.MetadataFirstFeignInterceptor;
import org.assertj.core.api.Assertions;
import org.junit.Test;
@@ -30,7 +28,7 @@ import org.springframework.boot.test.context.runner.ReactiveWebApplicationContex
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
/**
- * Test for {@link MetadataAutoConfiguration}
+ * Test for {@link MetadataAutoConfiguration}.
*
* @author Haotian Zhang
*/
@@ -50,20 +48,10 @@ public class MetadataAutoConfigurationTest {
this.applicationContextRunner
.withConfiguration(AutoConfigurations.of(MetadataAutoConfiguration.class))
.run(context -> {
- Assertions.assertThat(context)
- .hasSingleBean(MetadataLocalProperties.class);
- Assertions.assertThat(context).hasSingleBean(
- MetadataAutoConfiguration.MetadataFeignInterceptorConfig.class);
- Assertions.assertThat(context)
- .hasSingleBean(MetadataFirstFeignInterceptor.class);
- Assertions.assertThat(context).hasSingleBean(
- MetadataAutoConfiguration.MetadataZuulFilterConfig.class);
- Assertions.assertThat(context)
- .hasSingleBean(MetadataFirstZuulFilter.class);
+ Assertions.assertThat(context).hasSingleBean(MetadataLocalProperties.class);
Assertions.assertThat(context).hasSingleBean(
MetadataAutoConfiguration.MetadataScgFilterConfig.class);
- Assertions.assertThat(context)
- .hasSingleBean(MetadataFirstScgFilter.class);
+ Assertions.assertThat(context).hasSingleBean(MetadataFirstScgFilter.class);
});
}
@@ -75,20 +63,10 @@ public class MetadataAutoConfigurationTest {
this.webApplicationContextRunner
.withConfiguration(AutoConfigurations.of(MetadataAutoConfiguration.class))
.run(context -> {
- Assertions.assertThat(context)
- .hasSingleBean(MetadataLocalProperties.class);
- Assertions.assertThat(context).hasSingleBean(
- MetadataAutoConfiguration.MetadataFeignInterceptorConfig.class);
- Assertions.assertThat(context)
- .hasSingleBean(MetadataFirstFeignInterceptor.class);
- Assertions.assertThat(context).hasSingleBean(
- MetadataAutoConfiguration.MetadataZuulFilterConfig.class);
- Assertions.assertThat(context)
- .hasSingleBean(MetadataFirstZuulFilter.class);
+ Assertions.assertThat(context).hasSingleBean(MetadataLocalProperties.class);
Assertions.assertThat(context).hasSingleBean(
MetadataAutoConfiguration.MetadataScgFilterConfig.class);
- Assertions.assertThat(context)
- .hasSingleBean(MetadataFirstScgFilter.class);
+ Assertions.assertThat(context).hasSingleBean(MetadataFirstScgFilter.class);
});
}
@@ -100,20 +78,10 @@ public class MetadataAutoConfigurationTest {
this.reactiveWebApplicationContextRunner
.withConfiguration(AutoConfigurations.of(MetadataAutoConfiguration.class))
.run(context -> {
- Assertions.assertThat(context)
- .hasSingleBean(MetadataLocalProperties.class);
- Assertions.assertThat(context).hasSingleBean(
- MetadataAutoConfiguration.MetadataFeignInterceptorConfig.class);
- Assertions.assertThat(context)
- .hasSingleBean(MetadataFirstFeignInterceptor.class);
- Assertions.assertThat(context).hasSingleBean(
- MetadataAutoConfiguration.MetadataZuulFilterConfig.class);
- Assertions.assertThat(context)
- .hasSingleBean(MetadataFirstZuulFilter.class);
+ Assertions.assertThat(context).hasSingleBean(MetadataLocalProperties.class);
Assertions.assertThat(context).hasSingleBean(
MetadataAutoConfiguration.MetadataScgFilterConfig.class);
- Assertions.assertThat(context)
- .hasSingleBean(MetadataFirstScgFilter.class);
+ Assertions.assertThat(context).hasSingleBean(MetadataFirstScgFilter.class);
});
}
diff --git a/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/metadata/config/MetadataLocalPropertiesTest.java b/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/metadata/config/MetadataLocalPropertiesTest.java
index 44128591c..815010ce1 100644
--- a/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/metadata/config/MetadataLocalPropertiesTest.java
+++ b/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/metadata/config/MetadataLocalPropertiesTest.java
@@ -27,7 +27,7 @@ import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
/**
- * Test for {@link MetadataLocalProperties}
+ * Test for {@link MetadataLocalProperties}.
*
* @author Haotian Zhang
*/
diff --git a/spring-cloud-tencent-dependencies/pom.xml b/spring-cloud-tencent-dependencies/pom.xml
index f9da2e8e0..02465fb0a 100644
--- a/spring-cloud-tencent-dependencies/pom.xml
+++ b/spring-cloud-tencent-dependencies/pom.xml
@@ -70,8 +70,8 @@
- 1.4.0-Hoxton.SR9-SNAPSHOT
- 1.5.0-SNAPSHOT
+ 1.5.0-Hoxton.SR9-SNAPSHOT
+ 1.5.2
2.0.0
diff --git a/spring-cloud-tencent-examples/polaris-config-example/README-zh.md b/spring-cloud-tencent-examples/polaris-config-example/README-zh.md
index f4c12aec3..f131d319e 100644
--- a/spring-cloud-tencent-examples/polaris-config-example/README-zh.md
+++ b/spring-cloud-tencent-examples/polaris-config-example/README-zh.md
@@ -13,7 +13,7 @@ spring:
polaris:
namespace: dev
config:
- address: grpc://9.134.122.18:8093 # the address of polaris config server
+ address: grpc://127.0.0.1:8093 # the address of polaris config server
auto-refresh: true # auto refresh when config file changed
groups:
- name: ${spring.application.name} # group name
diff --git a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/GatewayCalleeController.java b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/GatewayCalleeController.java
index 77f84f518..40ddeb240 100644
--- a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/GatewayCalleeController.java
+++ b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/GatewayCalleeController.java
@@ -55,6 +55,10 @@ public class GatewayCalleeController {
/**
* Get metadata in HTTP header.
+ *
+ * @param metadataStr metadata string
+ * @return metadata in HTTP header
+ * @throws UnsupportedEncodingException encoding exception
*/
@RequestMapping("/echo")
public String echoHeader(
diff --git a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-scg-service/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-scg-service/src/main/resources/bootstrap.yml
index b820b2ee6..8acb66cb9 100644
--- a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-scg-service/src/main/resources/bootstrap.yml
+++ b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-scg-service/src/main/resources/bootstrap.yml
@@ -15,19 +15,52 @@ spring:
address: grpc://127.0.0.1:8091
namespace: default
enabled: true
+ discovery:
+ service-list-refresh-interval: 1000
gateway:
discovery:
locator:
enabled: true
- lowerCaseServiceId: false
- routes:
- - id: GatewayCalleeService
- uri: lb://GatewayCalleeService
- predicates:
- - Path=/GatewayCalleeService/**
- filters:
- - StripPrefix=1
+ 'predicates[0]':
+ name: Path
+ args:
+ patterns: '''/'' + serviceId + ''/**'''
+ 'filters[0]':
+ name: RewritePath
+ args:
+ regexp: '''/'' + serviceId + ''/(?.*)'''
+ replacement: '''/$\{remaining}'''
+ 'filters[1]':
+ name: Retry
+ args:
+ retries: 3
+ exceptions:
+ '[0]': '''java.net.ConnectException'''
+ '[1]': '''java.io.IOException'''
+ statuses:
+ '[0]': '''BAD_GATEWAY'''
+ '[1]': '''SERVICE_UNAVAILABLE'''
+ series:
+ '[0]': '''CLIENT_ERROR'''
+ methods:
+ '[0]': '''GET'''
+ '[1]': '''POST'''
+ '[2]': '''PUT'''
+ '[3]': '''DELETE'''
+ backoff:
+ firstBackoff: '''100ms'''
+ maxBackoff: '''500ms'''
+ factor: 2
+ basedOnPreviousValue: false
+# routes:
+# - id: GatewayCalleeService
+# uri: lb://GatewayCalleeService
+# predicates:
+# - Path=/GatewayCalleeService/**
+# filters:
+# - StripPrefix=1
logging:
level:
org.springframework.cloud.gateway: info
+ com.tencent.cloud.polaris: debug
diff --git a/spring-cloud-tencent-examples/polaris-router-example/router-callee-service1/src/main/java/com/tencent/cloud/polaris/router/example/RouterCalleeController.java b/spring-cloud-tencent-examples/polaris-router-example/router-callee-service1/src/main/java/com/tencent/cloud/polaris/router/example/RouterCalleeController.java
index f02f1887d..925031a7b 100644
--- a/spring-cloud-tencent-examples/polaris-router-example/router-callee-service1/src/main/java/com/tencent/cloud/polaris/router/example/RouterCalleeController.java
+++ b/spring-cloud-tencent-examples/polaris-router-example/router-callee-service1/src/main/java/com/tencent/cloud/polaris/router/example/RouterCalleeController.java
@@ -22,7 +22,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
-import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -44,10 +45,10 @@ public class RouterCalleeController {
* Get information of callee.
* @return information of callee
*/
- @GetMapping("/info")
- public String info() {
+ @PostMapping("/info")
+ public String info(String name, @RequestBody User user) {
LOG.info("Discovery Service Callee [{}] is called.", port);
- return String.format("Discovery Service Callee [%s] is called.", port);
+ return String.format("Discovery Service Callee [%s] is called. user = %s", port, user);
}
}
diff --git a/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/rule/PolarisLoadBalanceRule.java b/spring-cloud-tencent-examples/polaris-router-example/router-callee-service1/src/main/java/com/tencent/cloud/polaris/router/example/User.java
similarity index 55%
rename from spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/rule/PolarisLoadBalanceRule.java
rename to spring-cloud-tencent-examples/polaris-router-example/router-callee-service1/src/main/java/com/tencent/cloud/polaris/router/example/User.java
index 4831e76e6..ff83552db 100644
--- a/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/rule/PolarisLoadBalanceRule.java
+++ b/spring-cloud-tencent-examples/polaris-router-example/router-callee-service1/src/main/java/com/tencent/cloud/polaris/router/example/User.java
@@ -13,40 +13,41 @@
* 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.loadbalancer.rule;
-
-import java.util.Arrays;
+package com.tencent.cloud.polaris.router.example;
/**
- * Load balance rule.
- *
- * @author Haotian Zhang
+ * demo object.
+ * @author lepdou 2022-05-12
*/
-public enum PolarisLoadBalanceRule {
+public class User {
- /**
- * Weighted random load balance rule.
- */
- WEIGHTED_RANDOM_RULE("weighted_random");
+ private String name;
+ private int age;
- /**
- * Load balance strategy.
- */
- final String policy;
+ public String getName() {
+ return name;
+ }
- PolarisLoadBalanceRule(String strategy) {
- this.policy = strategy;
+ public void setName(String name) {
+ this.name = name;
}
- public static PolarisLoadBalanceRule fromStrategy(String strategy) {
- return Arrays.stream(values()).filter(t -> t.getPolicy().equals(strategy))
- .findAny().orElse(WEIGHTED_RANDOM_RULE);
+ public int getAge() {
+ return age;
}
- public String getPolicy() {
- return policy;
+ public void setAge(int age) {
+ this.age = age;
}
+ @Override
+ public String toString() {
+ return "User{" +
+ "name='" + name + '\'' +
+ ", age=" + age +
+ '}';
+ }
}
diff --git a/spring-cloud-tencent-examples/polaris-router-example/router-callee-service2/src/main/java/com/tencent/cloud/polaris/router/example/RouterCalleeController.java b/spring-cloud-tencent-examples/polaris-router-example/router-callee-service2/src/main/java/com/tencent/cloud/polaris/router/example/RouterCalleeController.java
index f02f1887d..b3e365ab8 100644
--- a/spring-cloud-tencent-examples/polaris-router-example/router-callee-service2/src/main/java/com/tencent/cloud/polaris/router/example/RouterCalleeController.java
+++ b/spring-cloud-tencent-examples/polaris-router-example/router-callee-service2/src/main/java/com/tencent/cloud/polaris/router/example/RouterCalleeController.java
@@ -22,8 +22,10 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
-import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
@@ -44,10 +46,10 @@ public class RouterCalleeController {
* Get information of callee.
* @return information of callee
*/
- @GetMapping("/info")
- public String info() {
+ @PostMapping("/info")
+ public String info(@RequestParam("name") String name, @RequestBody User user) {
LOG.info("Discovery Service Callee [{}] is called.", port);
- return String.format("Discovery Service Callee [%s] is called.", port);
+ return String.format("Discovery Service Callee [%s] is called. user = %s", port, user);
}
}
diff --git a/spring-cloud-tencent-examples/polaris-router-example/router-callee-service2/src/main/java/com/tencent/cloud/polaris/router/example/User.java b/spring-cloud-tencent-examples/polaris-router-example/router-callee-service2/src/main/java/com/tencent/cloud/polaris/router/example/User.java
new file mode 100644
index 000000000..ff83552db
--- /dev/null
+++ b/spring-cloud-tencent-examples/polaris-router-example/router-callee-service2/src/main/java/com/tencent/cloud/polaris/router/example/User.java
@@ -0,0 +1,53 @@
+/*
+ * 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.example;
+
+/**
+ * demo object.
+ * @author lepdou 2022-05-12
+ */
+public class User {
+
+ private String name;
+ private int age;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+
+ @Override
+ public String toString() {
+ return "User{" +
+ "name='" + name + '\'' +
+ ", age=" + age +
+ '}';
+ }
+}
diff --git a/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/pom.xml b/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/pom.xml
index 8a1af3407..fbdbf7081 100644
--- a/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/pom.xml
+++ b/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/pom.xml
@@ -22,6 +22,12 @@
com.tencent.cloud
spring-cloud-starter-tencent-polaris-router
+
+
+ com.google.code.gson
+ gson
+ 2.9.0
+
diff --git a/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/java/com/tencent/cloud/polaris/router/example/CustomRouterLabelResolver.java b/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/java/com/tencent/cloud/polaris/router/example/CustomRouterLabelResolver.java
new file mode 100644
index 000000000..0eb90aa69
--- /dev/null
+++ b/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/java/com/tencent/cloud/polaris/router/example/CustomRouterLabelResolver.java
@@ -0,0 +1,60 @@
+/*
+ * 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.example;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.google.gson.Gson;
+import com.tencent.cloud.polaris.router.spi.RouterLabelResolver;
+import feign.RequestTemplate;
+
+import org.springframework.http.HttpRequest;
+import org.springframework.stereotype.Component;
+
+/**
+ *
+ * Customize the business tag information obtained from the request
+ *
+ *@author lepdou 2022-05-12
+ */
+@Component
+public class CustomRouterLabelResolver implements RouterLabelResolver {
+ private final Gson gson = new Gson();
+
+ @Override
+ public Map resolve(RequestTemplate requestTemplate) {
+ Map labels = new HashMap<>();
+
+ User user = gson.fromJson(new String(requestTemplate.body()), User.class);
+
+ labels.put("user", user.getName());
+
+ return labels;
+ }
+
+ @Override
+ public Map resolve(HttpRequest request, byte[] body) {
+ Map labels = new HashMap<>();
+ User user = gson.fromJson(new String(body), User.class);
+
+ labels.put("user", user.getName());
+ return labels;
+ }
+}
diff --git a/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/java/com/tencent/cloud/polaris/router/example/RouterCalleeService.java b/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/java/com/tencent/cloud/polaris/router/example/RouterCalleeService.java
index 52439e3e5..7f1f1db39 100644
--- a/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/java/com/tencent/cloud/polaris/router/example/RouterCalleeService.java
+++ b/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/java/com/tencent/cloud/polaris/router/example/RouterCalleeService.java
@@ -19,7 +19,9 @@
package com.tencent.cloud.polaris.router.example;
import org.springframework.cloud.openfeign.FeignClient;
-import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestParam;
/**
* Router callee feign client.
@@ -29,7 +31,7 @@ import org.springframework.web.bind.annotation.GetMapping;
@FeignClient("RouterCalleeService")
public interface RouterCalleeService {
- @GetMapping("/router/service/callee/info")
- String info();
+ @PostMapping("/router/service/callee/info")
+ String info(@RequestParam("name") String name, @RequestBody User user);
}
diff --git a/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/java/com/tencent/cloud/polaris/router/example/RouterCallerController.java b/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/java/com/tencent/cloud/polaris/router/example/RouterCallerController.java
index 13b4ed4b7..866069d24 100644
--- a/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/java/com/tencent/cloud/polaris/router/example/RouterCallerController.java
+++ b/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/java/com/tencent/cloud/polaris/router/example/RouterCallerController.java
@@ -21,6 +21,7 @@ package com.tencent.cloud.polaris.router.example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@@ -44,8 +45,11 @@ public class RouterCallerController {
* @return info
*/
@GetMapping("/feign")
- public String feign() {
- return routerCalleeService.info();
+ public String feign(@RequestParam String name) {
+ User user = new User();
+ user.setName(name);
+ user.setAge(18);
+ return routerCalleeService.info(name, user);
}
/**
@@ -53,10 +57,12 @@ public class RouterCallerController {
* @return information of callee
*/
@GetMapping("/rest")
- public String rest() {
- return restTemplate.getForObject(
- "http://DiscoveryCalleeService/discovery/service/callee/info",
- String.class);
+ public String rest(@RequestParam String name) {
+ User user = new User();
+ user.setName(name);
+ user.setAge(18);
+ return restTemplate.postForObject(
+ "http://RouterCalleeService/router/service/callee/info?name={name}", user, String.class, name);
}
/**
diff --git a/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/java/com/tencent/cloud/polaris/router/example/User.java b/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/java/com/tencent/cloud/polaris/router/example/User.java
new file mode 100644
index 000000000..f68c6fff4
--- /dev/null
+++ b/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/java/com/tencent/cloud/polaris/router/example/User.java
@@ -0,0 +1,45 @@
+/*
+ * 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.example;
+
+/**
+ * demo object.
+ * @author lepdou 2022-05-12
+ */
+public class User {
+
+ private String name;
+ private int age;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+}
diff --git a/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/resources/bootstrap.yml
index ff1b89568..b30d1ff9b 100644
--- a/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/resources/bootstrap.yml
+++ b/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/resources/bootstrap.yml
@@ -4,6 +4,10 @@ spring:
application:
name: RouterCallerService
cloud:
+ tencent:
+ metadata:
+ content:
+ k1: v1
polaris:
address: grpc://127.0.0.1:8091
namespace: default
diff --git a/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/PolarisContextAutoConfiguration.java b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/PolarisContextAutoConfiguration.java
index 11e081287..db8424a34 100644
--- a/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/PolarisContextAutoConfiguration.java
+++ b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/PolarisContextAutoConfiguration.java
@@ -47,4 +47,8 @@ public class PolarisContextAutoConfiguration {
return new ModifyAddress();
}
+ @Bean
+ public ServiceRuleManager serviceRuleManager(SDKContext sdkContext) {
+ return new ServiceRuleManager(sdkContext);
+ }
}
diff --git a/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/ServiceRuleManager.java b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/ServiceRuleManager.java
new file mode 100644
index 000000000..8b3fb16d4
--- /dev/null
+++ b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/ServiceRuleManager.java
@@ -0,0 +1,117 @@
+/*
+ * Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
+ *
+ * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ */
+
+package com.tencent.cloud.polaris.context;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import com.tencent.polaris.api.pojo.DefaultServiceEventKeysProvider;
+import com.tencent.polaris.api.pojo.ServiceEventKey;
+import com.tencent.polaris.api.pojo.ServiceKey;
+import com.tencent.polaris.api.pojo.ServiceRule;
+import com.tencent.polaris.client.api.SDKContext;
+import com.tencent.polaris.client.flow.BaseFlow;
+import com.tencent.polaris.client.flow.DefaultFlowControlParam;
+import com.tencent.polaris.client.flow.FlowControlParam;
+import com.tencent.polaris.client.flow.ResourcesResponse;
+import com.tencent.polaris.client.pb.RateLimitProto;
+import com.tencent.polaris.client.pb.RoutingProto;
+
+/**
+ * the manager of service governance rules. for example: rate limit rule, router rules.
+ *
+ *@author lepdou 2022-05-13
+ */
+public class ServiceRuleManager {
+
+ private final SDKContext sdkContext;
+
+ private final FlowControlParam controlParam;
+
+ public ServiceRuleManager(SDKContext sdkContext) {
+ this.sdkContext = sdkContext;
+ controlParam = new DefaultFlowControlParam();
+ controlParam.setTimeoutMs(sdkContext.getConfig().getGlobal().getAPI().getTimeout());
+ controlParam.setMaxRetry(sdkContext.getConfig().getGlobal().getAPI().getMaxRetryTimes());
+ controlParam.setRetryIntervalMs(sdkContext.getConfig().getGlobal().getAPI().getRetryInterval());
+ }
+
+ public RateLimitProto.RateLimit getServiceRateLimitRule(String namespace, String service) {
+ ServiceEventKey serviceEventKey = new ServiceEventKey(new ServiceKey(namespace, service),
+ ServiceEventKey.EventType.RATE_LIMITING);
+
+ DefaultServiceEventKeysProvider svcKeysProvider = new DefaultServiceEventKeysProvider();
+ svcKeysProvider.setSvcEventKey(serviceEventKey);
+
+ ResourcesResponse resourcesResponse = BaseFlow
+ .syncGetResources(sdkContext.getExtensions(), true, svcKeysProvider, controlParam);
+
+ ServiceRule serviceRule = resourcesResponse.getServiceRule(serviceEventKey);
+ if (serviceRule != null) {
+ Object rule = serviceRule.getRule();
+ if (rule instanceof RateLimitProto.RateLimit) {
+ return (RateLimitProto.RateLimit) rule;
+ }
+ }
+
+ return null;
+ }
+
+ public List getServiceRouterRule(String namespace, String sourceService, String dstService) {
+ Set routerKeys = new HashSet<>();
+
+ ServiceEventKey dstSvcEventKey = new ServiceEventKey(new ServiceKey(namespace, dstService),
+ ServiceEventKey.EventType.ROUTING);
+ routerKeys.add(dstSvcEventKey);
+
+ ServiceEventKey srcSvcEventKey = new ServiceEventKey(new ServiceKey(namespace, sourceService),
+ ServiceEventKey.EventType.ROUTING);
+
+ DefaultServiceEventKeysProvider svcKeysProvider = new DefaultServiceEventKeysProvider();
+ svcKeysProvider.setSvcEventKeys(routerKeys);
+
+
+ ResourcesResponse resourcesResponse = BaseFlow
+ .syncGetResources(sdkContext.getExtensions(), true, svcKeysProvider, controlParam);
+
+ List rules = new ArrayList<>();
+
+ //get source service outbound rules.
+ ServiceRule sourceServiceRule = resourcesResponse.getServiceRule(srcSvcEventKey);
+ if (sourceServiceRule != null) {
+ Object rule = sourceServiceRule.getRule();
+ if (rule instanceof RoutingProto.Routing) {
+ rules.addAll(((RoutingProto.Routing) rule).getOutboundsList());
+ }
+ }
+
+ //get peer service inbound rules.
+ ServiceRule dstServiceRule = resourcesResponse.getServiceRule(dstSvcEventKey);
+ if (dstServiceRule != null) {
+ Object rule = dstServiceRule.getRule();
+ if (rule instanceof RoutingProto.Routing) {
+ rules.addAll(((RoutingProto.Routing) rule).getInboundsList());
+ }
+ }
+
+ return rules;
+ }
+}
diff --git a/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/LoadBalancerUtils.java b/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/LoadBalancerUtils.java
new file mode 100644
index 000000000..d7295447e
--- /dev/null
+++ b/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/LoadBalancerUtils.java
@@ -0,0 +1,58 @@
+/*
+ * 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.loadbalancer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.netflix.loadbalancer.Server;
+import com.tencent.cloud.common.metadata.MetadataContext;
+import com.tencent.cloud.common.pojo.PolarisServer;
+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;
+
+/**
+ * load balancer utils.
+ *
+ *@author lepdou 2022-05-17
+ */
+public class LoadBalancerUtils {
+
+ public static ServiceInstances transferServersToServiceInstances(List servers) {
+ List instances = new ArrayList<>(servers.size());
+ String serviceName = null;
+
+ for (Server server : servers) {
+ if (server instanceof PolarisServer) {
+ Instance instance = ((PolarisServer) server).getInstance();
+ instances.add(instance);
+
+ if (serviceName == null) {
+ serviceName = instance.getService();
+ }
+ }
+ }
+
+ ServiceKey serviceKey = new ServiceKey(MetadataContext.LOCAL_NAMESPACE, serviceName);
+
+ return new DefaultServiceInstances(serviceKey, instances);
+ }
+}
diff --git a/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/PolarisLoadBalancer.java b/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/PolarisLoadBalancer.java
index 37ae60526..2bc371b9d 100644
--- a/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/PolarisLoadBalancer.java
+++ b/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/PolarisLoadBalancer.java
@@ -13,14 +13,15 @@
* 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.loadbalancer;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.LinkedList;
import java.util.List;
-import java.util.Map;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.DynamicServerListLoadBalancer;
@@ -30,23 +31,17 @@ import com.netflix.loadbalancer.PollingServerListUpdater;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerList;
import com.tencent.cloud.common.constant.ContextConstant;
-import com.tencent.cloud.common.constant.MetadataConstant.SystemMetadataKey;
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.polaris.loadbalancer.config.PolarisLoadBalancerProperties;
import com.tencent.polaris.api.core.ConsumerAPI;
import com.tencent.polaris.api.pojo.DefaultInstance;
import com.tencent.polaris.api.pojo.DefaultServiceInstances;
import com.tencent.polaris.api.pojo.Instance;
-import com.tencent.polaris.api.pojo.ServiceInfo;
import com.tencent.polaris.api.pojo.ServiceInstances;
import com.tencent.polaris.api.pojo.ServiceKey;
-import com.tencent.polaris.api.rpc.GetAllInstancesRequest;
+import com.tencent.polaris.api.rpc.GetHealthyInstancesRequest;
import com.tencent.polaris.api.rpc.InstancesResponse;
-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.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
@@ -57,16 +52,13 @@ import org.apache.commons.lang.StringUtils;
*/
public class PolarisLoadBalancer extends DynamicServerListLoadBalancer {
- private final RouterAPI routerAPI;
-
- private ConsumerAPI consumerAPI;
+ private final ConsumerAPI consumerAPI;
- private PolarisLoadBalancerProperties polarisLoadBalancerProperties;
+ private final PolarisLoadBalancerProperties polarisLoadBalancerProperties;
public PolarisLoadBalancer(IClientConfig config, IRule rule, IPing ping, ServerList serverList,
- RouterAPI routerAPI, ConsumerAPI consumerAPI, PolarisLoadBalancerProperties properties) {
+ ConsumerAPI consumerAPI, PolarisLoadBalancerProperties properties) {
super(config, rule, ping, serverList, null, new PollingServerListUpdater());
- this.routerAPI = routerAPI;
this.consumerAPI = consumerAPI;
this.polarisLoadBalancerProperties = properties;
}
@@ -80,46 +72,21 @@ public class PolarisLoadBalancer extends DynamicServerListLoadBalancer {
else {
serviceInstances = getExtendDiscoveryServiceInstances();
}
+
if (serviceInstances == null || CollectionUtils.isEmpty(serviceInstances.getInstances())) {
return Collections.emptyList();
}
- ProcessRoutersRequest processRoutersRequest = new ProcessRoutersRequest();
- processRoutersRequest.setDstInstances(serviceInstances);
- String srcNamespace = MetadataContext.LOCAL_NAMESPACE;
- String srcService = MetadataContext.LOCAL_SERVICE;
- Map transitiveCustomMetadata = MetadataContextHolder.get()
- .getAllTransitiveCustomMetadata();
- String method = MetadataContextHolder.get()
- .getSystemMetadata(SystemMetadataKey.PEER_PATH);
- processRoutersRequest.setMethod(method);
- if (StringUtils.isNotBlank(srcNamespace) && StringUtils.isNotBlank(srcService)) {
- ServiceInfo serviceInfo = new ServiceInfo();
- serviceInfo.setNamespace(srcNamespace);
- serviceInfo.setService(srcService);
- serviceInfo.setMetadata(transitiveCustomMetadata);
- processRoutersRequest.setSourceService(serviceInfo);
- }
- ProcessRoutersResponse processRoutersResponse = routerAPI
- .processRouters(processRoutersRequest);
- ServiceInstances filteredServiceInstances = processRoutersResponse
- .getServiceInstances();
- List filteredInstances = new ArrayList<>();
- for (Instance instance : filteredServiceInstances.getInstances()) {
- filteredInstances.add(new PolarisServer(serviceInstances, instance));
+
+ List servers = new LinkedList<>();
+ for (Instance instance : serviceInstances.getInstances()) {
+ servers.add(new PolarisServer(serviceInstances, instance));
}
- return filteredInstances;
+
+ return servers;
}
private ServiceInstances getPolarisDiscoveryServiceInstances() {
- String serviceName = MetadataContextHolder.get().getSystemMetadata(SystemMetadataKey.PEER_SERVICE);
- if (StringUtils.isBlank(serviceName)) {
- List allServers = super.getAllServers();
- if (CollectionUtils.isEmpty(allServers)) {
- return null;
- }
- serviceName = ((PolarisServer) super.getAllServers().get(0)).getServiceInstances().getService();
- }
- return getAllInstances(MetadataContext.LOCAL_NAMESPACE, serviceName).toServiceInstances();
+ return getAllInstances(MetadataContext.LOCAL_NAMESPACE, name).toServiceInstances();
}
private ServiceInstances getExtendDiscoveryServiceInstances() {
@@ -128,26 +95,16 @@ public class PolarisLoadBalancer extends DynamicServerListLoadBalancer {
return null;
}
ServiceInstances serviceInstances;
- 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)) {
+ if (StringUtils.isBlank(name)) {
throw new IllegalStateException(
"PolarisLoadBalancer only Server with AppName or ServiceIdForDiscovery attribute");
}
- ServiceKey serviceKey = new ServiceKey(MetadataContext.LOCAL_NAMESPACE,
- serviceName);
+ ServiceKey serviceKey = new ServiceKey(MetadataContext.LOCAL_NAMESPACE, name);
List instances = new ArrayList<>(8);
for (Server server : allServers) {
DefaultInstance instance = new DefaultInstance();
instance.setNamespace(MetadataContext.LOCAL_NAMESPACE);
- instance.setService(serviceName);
+ instance.setService(name);
instance.setHealthy(server.isAlive());
instance.setProtocol(server.getScheme());
instance.setId(server.getId());
@@ -173,10 +130,10 @@ public class PolarisLoadBalancer extends DynamicServerListLoadBalancer {
* @return list of instances
*/
public InstancesResponse getAllInstances(String namespace, String serviceName) {
- GetAllInstancesRequest request = new GetAllInstancesRequest();
+ GetHealthyInstancesRequest request = new GetHealthyInstancesRequest();
request.setNamespace(namespace);
request.setService(serviceName);
- return consumerAPI.getAllInstance(request);
+ return consumerAPI.getHealthyInstancesInstance(request);
}
}
diff --git a/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/rule/PolarisWeightedRandomRule.java b/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/PolarisWeightedRule.java
similarity index 53%
rename from spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/rule/PolarisWeightedRandomRule.java
rename to spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/PolarisWeightedRule.java
index 055f4bab3..124085717 100644
--- a/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/rule/PolarisWeightedRandomRule.java
+++ b/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/PolarisWeightedRule.java
@@ -16,86 +16,57 @@
*
*/
-package com.tencent.cloud.polaris.loadbalancer.rule;
+package com.tencent.cloud.polaris.loadbalancer;
-import java.util.ArrayList;
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.metadata.MetadataContext;
import com.tencent.cloud.common.pojo.PolarisServer;
import com.tencent.polaris.api.config.consumer.LoadBalanceConfig;
-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.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.
+ * Polaris weighted load balancer.
*
- * @author Haotian Zhang
+ *@author lepdou 2022-05-17
*/
-public class PolarisWeightedRandomRule extends AbstractLoadBalancerRule {
+public class PolarisWeightedRule extends AbstractLoadBalancerRule {
- private static final String POLICY = LoadBalanceConfig.LOAD_BALANCE_WEIGHTED_RANDOM;
+ private final RouterAPI routerAPI;
- @Autowired
- private RouterAPI polarisRouter;
+ public PolarisWeightedRule(RouterAPI routerAPI) {
+ this.routerAPI = routerAPI;
+ }
@Override
public void initWithNiwsConfig(IClientConfig clientConfig) {
-
}
@Override
public Server choose(Object key) {
- // 1. filter by router
- List serversAfterRouter = getLoadBalancer().getReachableServers();
- if (CollectionUtils.isEmpty(serversAfterRouter)) {
+ List servers = getLoadBalancer().getReachableServers();
+ if (CollectionUtils.isEmpty(servers)) {
return null;
}
- ServiceInstances serviceInstances = transferServersToServiceInstances(
- serversAfterRouter);
+ ServiceInstances serviceInstances = LoadBalancerUtils.transferServersToServiceInstances(servers);
- // 2. filter by load balance
ProcessLoadBalanceRequest request = new ProcessLoadBalanceRequest();
request.setDstInstances(serviceInstances);
- request.setLbPolicy(POLICY);
- ProcessLoadBalanceResponse processLoadBalanceResponse = polarisRouter
- .processLoadBalance(request);
- Instance targetInstance = processLoadBalanceResponse.getTargetInstance();
-
- return new PolarisServer(serviceInstances, targetInstance);
- }
+ request.setLbPolicy(LoadBalanceConfig.LOAD_BALANCE_WEIGHTED_RANDOM);
- ServiceInstances transferServersToServiceInstances(List servers) {
- List instances = new ArrayList<>(servers.size());
- String serviceName = null;
+ ProcessLoadBalanceResponse processLoadBalanceResponse = routerAPI.processLoadBalance(request);
- for (Server server : servers) {
- if (server instanceof PolarisServer) {
- Instance instance = ((PolarisServer) server).getInstance();
- instances.add(instance);
-
- if (serviceName == null) {
- serviceName = instance.getService();
- }
- }
- }
-
- ServiceKey serviceKey = new ServiceKey(MetadataContext.LOCAL_NAMESPACE,
- serviceName);
+ Instance targetInstance = processLoadBalanceResponse.getTargetInstance();
- return new DefaultServiceInstances(serviceKey, instances);
+ return new PolarisServer(serviceInstances, targetInstance);
}
-
}
diff --git a/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/config/PolarisLoadBalancerAutoConfiguration.java b/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/config/PolarisLoadBalancerAutoConfiguration.java
index 0b8b0583c..6774b5487 100644
--- a/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/config/PolarisLoadBalancerAutoConfiguration.java
+++ b/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/config/PolarisLoadBalancerAutoConfiguration.java
@@ -24,7 +24,6 @@ import com.tencent.polaris.factory.api.RouterAPIFactory;
import com.tencent.polaris.router.api.core.RouterAPI;
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;
@@ -46,15 +45,12 @@ import org.springframework.context.annotation.Configuration;
public class PolarisLoadBalancerAutoConfiguration {
@Bean
- @ConditionalOnMissingBean
public PolarisLoadBalancerProperties polarisLoadBalancerProperties() {
return new PolarisLoadBalancerProperties();
}
- @Bean(name = "polarisRoute")
- @ConditionalOnMissingBean
- public RouterAPI polarisRouter(SDKContext polarisContext) throws PolarisException {
+ @Bean
+ public RouterAPI routerAPI(SDKContext polarisContext) throws PolarisException {
return RouterAPIFactory.createRouterAPIByContext(polarisContext);
}
-
}
diff --git a/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/config/PolarisLoadBalancerProperties.java b/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/config/PolarisLoadBalancerProperties.java
index 22760e463..9d4d06059 100644
--- a/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/config/PolarisLoadBalancerProperties.java
+++ b/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/config/PolarisLoadBalancerProperties.java
@@ -37,7 +37,7 @@ public class PolarisLoadBalancerProperties {
/**
* Load balance strategy.
*/
- private String strategy = "weightedRandom";
+ private String strategy;
/**
* Type of discovery server.
diff --git a/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/config/PolarisRibbonClientConfiguration.java b/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/config/PolarisRibbonClientConfiguration.java
index 3e84ed57f..3fbc2c76d 100644
--- a/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/config/PolarisRibbonClientConfiguration.java
+++ b/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/config/PolarisRibbonClientConfiguration.java
@@ -13,6 +13,7 @@
* 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.loadbalancer.config;
@@ -24,12 +25,8 @@ import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerList;
import com.tencent.cloud.polaris.loadbalancer.PolarisLoadBalancer;
-import com.tencent.cloud.polaris.loadbalancer.rule.PolarisLoadBalanceRule;
-import com.tencent.cloud.polaris.loadbalancer.rule.PolarisWeightedRandomRule;
import com.tencent.polaris.api.core.ConsumerAPI;
-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;
@@ -42,24 +39,11 @@ import org.springframework.context.annotation.Configuration;
public class PolarisRibbonClientConfiguration {
@Bean
- @ConditionalOnMissingBean
- public IRule polarisRibbonRule(
- PolarisLoadBalancerProperties polarisLoadBalancerProperties) {
- switch (PolarisLoadBalanceRule
- .fromStrategy(polarisLoadBalancerProperties.getStrategy())) {
- case WEIGHTED_RANDOM_RULE:
- default:
- return new PolarisWeightedRandomRule();
- }
- }
-
- @Bean
- @ConditionalOnMissingBean
public ILoadBalancer polarisLoadBalancer(IClientConfig iClientConfig, IRule iRule,
- IPing iPing, ServerList serverList, RouterAPI polarisRouter,
+ IPing iPing, ServerList serverList,
ConsumerAPI consumerAPI, PolarisLoadBalancerProperties polarisLoadBalancerProperties) {
return new PolarisLoadBalancer(iClientConfig, iRule, iPing, serverList,
- polarisRouter, consumerAPI, polarisLoadBalancerProperties);
+ consumerAPI, polarisLoadBalancerProperties);
}
}
diff --git a/spring-cloud-tencent-polaris-loadbalancer/src/test/java/com/tencent/cloud/polaris/loadbalancer/config/PolarisLoadBalancerAutoConfigurationTest.java b/spring-cloud-tencent-polaris-loadbalancer/src/test/java/com/tencent/cloud/polaris/loadbalancer/config/PolarisLoadBalancerAutoConfigurationTest.java
index 3e87d5fdd..1c89de2d6 100644
--- a/spring-cloud-tencent-polaris-loadbalancer/src/test/java/com/tencent/cloud/polaris/loadbalancer/config/PolarisLoadBalancerAutoConfigurationTest.java
+++ b/spring-cloud-tencent-polaris-loadbalancer/src/test/java/com/tencent/cloud/polaris/loadbalancer/config/PolarisLoadBalancerAutoConfigurationTest.java
@@ -31,7 +31,7 @@ import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER;
import static org.assertj.core.api.Assertions.assertThat;
/**
- * Test for {@link PolarisLoadBalancerAutoConfiguration}
+ * Test for {@link PolarisLoadBalancerAutoConfiguration}.
*
* @author Haotian Zhang
*/
diff --git a/src/checkstyle/checkstyle-suppressions.xml b/src/checkstyle/checkstyle-suppressions.xml
index 5993108df..ace6b329d 100644
--- a/src/checkstyle/checkstyle-suppressions.xml
+++ b/src/checkstyle/checkstyle-suppressions.xml
@@ -4,4 +4,6 @@
"https://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
+
+
\ No newline at end of file