diff --git a/CHANGELOG.md b/CHANGELOG.md
index 43135661f..5d2a38260 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -22,3 +22,4 @@
- [feat: support config ratelimit addresses and remote task interval.](https://github.com/Tencent/spring-cloud-tencent/pull/1679)
- [docs:optimize tsf example.](https://github.com/Tencent/spring-cloud-tencent/pull/1710)
- [feat:support TSF certificate manager.](https://github.com/Tencent/spring-cloud-tencent/pull/1715)
+- [feat:support tsf unit.](https://github.com/Tencent/spring-cloud-tencent/pull/1681)
\ No newline at end of file
diff --git a/spring-cloud-starter-tencent-all/pom.xml b/spring-cloud-starter-tencent-all/pom.xml
index 3758dd093..e917a0a6f 100644
--- a/spring-cloud-starter-tencent-all/pom.xml
+++ b/spring-cloud-starter-tencent-all/pom.xml
@@ -60,6 +60,11 @@
spring-cloud-starter-tencent-gateway-plugin
+
+ com.tencent.cloud
+ spring-cloud-tencent-unit-plugin
+
+
com.tencent.cloud
spring-cloud-starter-tencent-polaris-auth
diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reporter/CircuitBreakerPlugin.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reporter/CircuitBreakerPlugin.java
index 42072c760..221cde125 100644
--- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reporter/CircuitBreakerPlugin.java
+++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reporter/CircuitBreakerPlugin.java
@@ -18,7 +18,7 @@
package com.tencent.cloud.polaris.circuitbreaker.reporter;
import com.tencent.cloud.common.constant.ContextConstant;
-import com.tencent.cloud.common.metadata.MetadataContextHolder;
+import com.tencent.cloud.common.util.MetadataContextUtils;
import com.tencent.cloud.polaris.circuitbreaker.PolarisCircuitBreaker;
import com.tencent.cloud.polaris.circuitbreaker.instrument.resttemplate.PolarisCircuitBreakerHttpResponse;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
@@ -28,7 +28,6 @@ import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext;
import com.tencent.cloud.rpc.enhancement.plugin.reporter.SuccessPolarisReporter;
import com.tencent.polaris.circuitbreak.client.exception.CallAbortedException;
-import com.tencent.polaris.metadata.core.MetadataType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -77,8 +76,8 @@ public class CircuitBreakerPlugin implements EnhancedPlugin {
CircuitBreaker circuitBreaker = circuitBreakerFactory.create(governanceNamespace + "#" + host + "#" + path + "#http#" + httpMethod);
if (circuitBreaker instanceof PolarisCircuitBreaker) {
PolarisCircuitBreaker polarisCircuitBreaker = (PolarisCircuitBreaker) circuitBreaker;
- putMetadataObjectValue(ContextConstant.CircuitBreaker.POLARIS_CIRCUIT_BREAKER, polarisCircuitBreaker);
- putMetadataObjectValue(ContextConstant.CircuitBreaker.CIRCUIT_BREAKER_START_TIME, System.currentTimeMillis());
+ MetadataContextUtils.putMetadataObjectValue(ContextConstant.CircuitBreaker.POLARIS_CIRCUIT_BREAKER, polarisCircuitBreaker);
+ MetadataContextUtils.putMetadataObjectValue(ContextConstant.CircuitBreaker.CIRCUIT_BREAKER_START_TIME, System.currentTimeMillis());
try {
polarisCircuitBreaker.acquirePermission();
@@ -88,7 +87,7 @@ public class CircuitBreakerPlugin implements EnhancedPlugin {
polarisCircuitBreaker.reportStatus(e);
if (e.getFallbackInfo() != null) {
Object fallbackResponse = new PolarisCircuitBreakerHttpResponse(e.getFallbackInfo());
- putMetadataObjectValue(ContextConstant.CircuitBreaker.CIRCUIT_BREAKER_FALLBACK_HTTP_RESPONSE, fallbackResponse);
+ MetadataContextUtils.putMetadataObjectValue(ContextConstant.CircuitBreaker.CIRCUIT_BREAKER_FALLBACK_HTTP_RESPONSE, fallbackResponse);
}
throw e;
}
@@ -105,9 +104,4 @@ public class CircuitBreakerPlugin implements EnhancedPlugin {
public int getOrder() {
return CIRCUIT_BREAKER_REPORTER_PLUGIN_ORDER;
}
-
- private void putMetadataObjectValue(String key, Object value) {
- MetadataContextHolder.get().getMetadataContainer(MetadataType.APPLICATION, true).
- putMetadataObjectValue(key, value);
- }
}
diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reporter/ExceptionCircuitBreakerReporter.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reporter/ExceptionCircuitBreakerReporter.java
index 77245c31e..355c68b4d 100644
--- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reporter/ExceptionCircuitBreakerReporter.java
+++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reporter/ExceptionCircuitBreakerReporter.java
@@ -22,6 +22,7 @@ import java.util.concurrent.TimeUnit;
import com.tencent.cloud.common.constant.ContextConstant;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
+import com.tencent.cloud.common.util.MetadataContextUtils;
import com.tencent.cloud.polaris.circuitbreaker.PolarisCircuitBreaker;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
@@ -61,11 +62,6 @@ public class ExceptionCircuitBreakerReporter implements EnhancedPlugin {
this.circuitBreakAPI = circuitBreakAPI;
}
- private static boolean existMetadataValue(MetadataObjectValue> metadataObjectValue) {
- return Optional.ofNullable(metadataObjectValue).map(MetadataObjectValue::getObjectValue).
- map(Optional::isPresent).orElse(false);
- }
-
@Override
public String getName() {
return ExceptionCircuitBreakerReporter.class.getName();
@@ -103,15 +99,15 @@ public class ExceptionCircuitBreakerReporter implements EnhancedPlugin {
circuitBreakAPI.report(resourceStat);
MetadataObjectValue circuitBreakerObject = MetadataContextHolder.get().
- getMetadataContainer(MetadataType.APPLICATION, true).
+ getMetadataContainer(MetadataType.CUSTOM, false).
getMetadataValue(ContextConstant.CircuitBreaker.POLARIS_CIRCUIT_BREAKER);
MetadataObjectValue startTimeMilliObject = MetadataContextHolder.get().
- getMetadataContainer(MetadataType.APPLICATION, true).
+ getMetadataContainer(MetadataType.CUSTOM, false).
getMetadataValue(ContextConstant.CircuitBreaker.CIRCUIT_BREAKER_START_TIME);
- boolean existCircuitBreaker = existMetadataValue(circuitBreakerObject);
- boolean existStartTime = existMetadataValue(startTimeMilliObject);
+ boolean existCircuitBreaker = MetadataContextUtils.existMetadataValue(circuitBreakerObject);
+ boolean existStartTime = MetadataContextUtils.existMetadataValue(startTimeMilliObject);
if (existCircuitBreaker && existStartTime) {
PolarisCircuitBreaker polarisCircuitBreaker = circuitBreakerObject.getObjectValue().get();
diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reporter/SuccessCircuitBreakerReporter.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reporter/SuccessCircuitBreakerReporter.java
index 3d64e8d94..632257972 100644
--- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reporter/SuccessCircuitBreakerReporter.java
+++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reporter/SuccessCircuitBreakerReporter.java
@@ -22,6 +22,7 @@ import java.util.concurrent.TimeUnit;
import com.tencent.cloud.common.constant.ContextConstant;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
+import com.tencent.cloud.common.util.MetadataContextUtils;
import com.tencent.cloud.polaris.circuitbreaker.PolarisCircuitBreaker;
import com.tencent.cloud.polaris.context.CircuitBreakerStatusCodeException;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
@@ -65,11 +66,6 @@ public class SuccessCircuitBreakerReporter implements EnhancedPlugin {
this.circuitBreakAPI = circuitBreakAPI;
}
- private static boolean existMetadataValue(MetadataObjectValue> metadataObjectValue) {
- return Optional.ofNullable(metadataObjectValue).map(MetadataObjectValue::getObjectValue).
- map(Optional::isPresent).orElse(false);
- }
-
@Override
public String getName() {
return SuccessCircuitBreakerReporter.class.getName();
@@ -107,15 +103,15 @@ public class SuccessCircuitBreakerReporter implements EnhancedPlugin {
circuitBreakAPI.report(resourceStat);
MetadataObjectValue circuitBreakerObject = MetadataContextHolder.get().
- getMetadataContainer(MetadataType.APPLICATION, true).
+ getMetadataContainer(MetadataType.CUSTOM, false).
getMetadataValue(ContextConstant.CircuitBreaker.POLARIS_CIRCUIT_BREAKER);
MetadataObjectValue startTimeMilliObject = MetadataContextHolder.get().
- getMetadataContainer(MetadataType.APPLICATION, true).
+ getMetadataContainer(MetadataType.CUSTOM, false).
getMetadataValue(ContextConstant.CircuitBreaker.CIRCUIT_BREAKER_START_TIME);
- boolean existCircuitBreaker = existMetadataValue(circuitBreakerObject);
- boolean existStartTime = existMetadataValue(startTimeMilliObject);
+ boolean existCircuitBreaker = MetadataContextUtils.existMetadataValue(circuitBreakerObject);
+ boolean existStartTime = MetadataContextUtils.existMetadataValue(startTimeMilliObject);
if (existCircuitBreaker && existStartTime) {
PolarisCircuitBreaker polarisCircuitBreaker = circuitBreakerObject.getObjectValue().get();
diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/reporter/ExceptionCircuitBreakerReporterTest.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/reporter/ExceptionCircuitBreakerReporterTest.java
index ba578e025..a40185d4a 100644
--- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/reporter/ExceptionCircuitBreakerReporterTest.java
+++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/reporter/ExceptionCircuitBreakerReporterTest.java
@@ -170,9 +170,9 @@ public class ExceptionCircuitBreakerReporterTest {
pluginContext.setTargetServiceInstance(serviceInstance, null);
pluginContext.setThrowable(new RuntimeException());
- MetadataContextHolder.get().getMetadataContainer(MetadataType.APPLICATION, true).
+ MetadataContextHolder.get().getMetadataContainer(MetadataType.CUSTOM, false).
putMetadataObjectValue(ContextConstant.CircuitBreaker.POLARIS_CIRCUIT_BREAKER, polarisCircuitBreaker);
- MetadataContextHolder.get().getMetadataContainer(MetadataType.APPLICATION, true).
+ MetadataContextHolder.get().getMetadataContainer(MetadataType.CUSTOM, false).
putMetadataObjectValue(ContextConstant.CircuitBreaker.CIRCUIT_BREAKER_START_TIME, System.currentTimeMillis());
exceptionCircuitBreakerReporter.run(pluginContext);
@@ -205,7 +205,7 @@ public class ExceptionCircuitBreakerReporterTest {
pluginContext.setTargetServiceInstance(serviceInstance, null);
pluginContext.setThrowable(new RuntimeException());
// not exist circuit CIRCUIT_BREAKER_START_TIME
- MetadataContextHolder.get().getMetadataContainer(MetadataType.APPLICATION, true).
+ MetadataContextHolder.get().getMetadataContainer(MetadataType.CUSTOM, false).
putMetadataObjectValue(ContextConstant.CircuitBreaker.POLARIS_CIRCUIT_BREAKER, polarisCircuitBreaker);
exceptionCircuitBreakerReporter.run(pluginContext);
diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/reporter/SuccessCircuitBreakerReporterTest.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/reporter/SuccessCircuitBreakerReporterTest.java
index 7f42b5ceb..540bc51e3 100644
--- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/reporter/SuccessCircuitBreakerReporterTest.java
+++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/reporter/SuccessCircuitBreakerReporterTest.java
@@ -183,9 +183,9 @@ public class SuccessCircuitBreakerReporterTest {
pluginContext.setResponse(response);
pluginContext.setTargetServiceInstance(serviceInstance, null);
- MetadataContextHolder.get().getMetadataContainer(MetadataType.APPLICATION, true).
+ MetadataContextHolder.get().getMetadataContainer(MetadataType.CUSTOM, false).
putMetadataObjectValue(ContextConstant.CircuitBreaker.POLARIS_CIRCUIT_BREAKER, polarisCircuitBreaker);
- MetadataContextHolder.get().getMetadataContainer(MetadataType.APPLICATION, true).
+ MetadataContextHolder.get().getMetadataContainer(MetadataType.CUSTOM, false).
putMetadataObjectValue(ContextConstant.CircuitBreaker.CIRCUIT_BREAKER_START_TIME, System.currentTimeMillis());
successCircuitBreakerReporter.run(pluginContext);
@@ -217,7 +217,7 @@ public class SuccessCircuitBreakerReporterTest {
pluginContext.setResponse(response);
pluginContext.setTargetServiceInstance(serviceInstance, null);
// not exist circuit CIRCUIT_BREAKER_START_TIME
- MetadataContextHolder.get().getMetadataContainer(MetadataType.APPLICATION, true).
+ MetadataContextHolder.get().getMetadataContainer(MetadataType.CUSTOM, false).
putMetadataObjectValue(ContextConstant.CircuitBreaker.POLARIS_CIRCUIT_BREAKER, polarisCircuitBreaker);
successCircuitBreakerReporter.run(pluginContext);
diff --git a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/adapter/PolarisConfigFileLocator.java b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/adapter/PolarisConfigFileLocator.java
index f21285a70..9db25194b 100644
--- a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/adapter/PolarisConfigFileLocator.java
+++ b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/adapter/PolarisConfigFileLocator.java
@@ -24,6 +24,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import com.tencent.cloud.common.util.EnvironmentUtils;
import com.tencent.cloud.plugin.tsf.tls.utils.SyncUtils;
import com.tencent.cloud.polaris.config.config.ConfigFileGroup;
import com.tencent.cloud.polaris.config.config.PolarisConfigProperties;
@@ -222,7 +223,7 @@ public class PolarisConfigFileLocator implements PropertySourceLocator {
tsfConfigGroups.add((StringUtils.isNotBlank(tsfId) ? tsfId + "." : "") + tsfGroupName + ".application_config_group");
tsfConfigGroups.add((StringUtils.isNotBlank(tsfId) ? tsfId + "." : "") + tsfNamespaceName + ".global_config_group");
- if (ClassUtils.isClassPresent("org.springframework.cloud.gateway.filter.GlobalFilter")) {
+ if (EnvironmentUtils.isGateway()) {
tsfConfigGroups.add((StringUtils.isNotBlank(tsfId) ? tsfId + "." : "") + tsfGroupName + ".gateway_config_group");
}
for (String tsfConfigGroup : tsfConfigGroups) {
diff --git a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/adapter/PolarisConfigFilePuller.java b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/adapter/PolarisConfigFilePuller.java
index eb6212f88..7c6f482a1 100644
--- a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/adapter/PolarisConfigFilePuller.java
+++ b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/adapter/PolarisConfigFilePuller.java
@@ -24,6 +24,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import com.tencent.cloud.common.util.EnvironmentUtils;
import com.tencent.cloud.plugin.tsf.tls.utils.SyncUtils;
import com.tencent.cloud.polaris.config.config.ConfigFileGroup;
import com.tencent.cloud.polaris.config.configdata.PolarisConfigDataLoader;
@@ -155,7 +156,7 @@ public final class PolarisConfigFilePuller {
tsfConfigGroups.add((StringUtils.isNotBlank(tsfId) ? tsfId + "." : "") + tsfGroupName + ".application_config_group");
tsfConfigGroups.add((StringUtils.isNotBlank(tsfId) ? tsfId + "." : "") + tsfNamespaceName + ".global_config_group");
- if (ClassUtils.isClassPresent("org.springframework.cloud.gateway.filter.GlobalFilter")) {
+ if (EnvironmentUtils.isGateway()) {
tsfConfigGroups.add((StringUtils.isNotBlank(tsfId) ? tsfId + "." : "") + tsfGroupName + ".gateway_config_group");
}
for (String tsfConfigGroup : tsfConfigGroups) {
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/reactive/PolarisReactiveDiscoveryClient.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/reactive/PolarisReactiveDiscoveryClient.java
index 48644bb70..25607a34c 100644
--- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/reactive/PolarisReactiveDiscoveryClient.java
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/reactive/PolarisReactiveDiscoveryClient.java
@@ -53,7 +53,6 @@ public class PolarisReactiveDiscoveryClient implements ReactiveDiscoveryClient {
@Override
public Flux getInstances(String serviceId) {
-
return Mono.justOrEmpty(serviceId).flatMapMany(loadInstancesFromPolaris())
.subscribeOn(Schedulers.boundedElastic());
}
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 771dacb1b..220fba945 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
@@ -66,6 +66,10 @@ public final class MetadataConstant {
* TSF Metadata.
*/
public static final String TSF_METADATA = "TSF-Metadata";
+ /**
+ * TSF Unit.
+ */
+ public static final String TSF_UNIT = "TSF-Unit";
/**
* Custom metadata.
*/
diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/constant/OrderConstant.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/constant/OrderConstant.java
index 79c2eb027..341340246 100644
--- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/constant/OrderConstant.java
+++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/constant/OrderConstant.java
@@ -42,6 +42,10 @@ public class OrderConstant {
* Order of encode router label interceptor.
*/
public static final int ROUTER_LABEL_INTERCEPTOR_ORDER = Ordered.LOWEST_PRECEDENCE;
+ /**
+ * Order of unit interceptor.
+ */
+ public static final int UNIT_INTERCEPTOR_ORDER = 10;
}
/**
@@ -57,6 +61,10 @@ public class OrderConstant {
* Order of encode router label interceptor.
*/
public static final int ROUTER_LABEL_INTERCEPTOR_ORDER = 0;
+ /**
+ * Order of unit interceptor.
+ */
+ public static final int UNIT_INTERCEPTOR_ORDER = 10;
}
/**
diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/EnvironmentUtils.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/EnvironmentUtils.java
new file mode 100644
index 000000000..97ebc220a
--- /dev/null
+++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/EnvironmentUtils.java
@@ -0,0 +1,32 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 Tencent. 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 com.tencent.polaris.api.utils.ClassUtils;
+
+public final class EnvironmentUtils {
+
+ private final static boolean IS_GATEWAY = ClassUtils.isClassPresent("org.springframework.cloud.gateway.filter.GlobalFilter");
+
+ private EnvironmentUtils() {
+ }
+
+ public static boolean isGateway() {
+ return IS_GATEWAY;
+ }
+}
diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/MetadataContextUtils.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/MetadataContextUtils.java
index ea889bc38..a18e4364b 100644
--- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/MetadataContextUtils.java
+++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/MetadataContextUtils.java
@@ -37,8 +37,11 @@ public final class MetadataContextUtils {
private MetadataContextUtils() {
}
+ /**
+ * use callee's custom metadata to store local thread's metadata. caller's metadata is for remote upstream service.
+ */
public static void putMetadataObjectValue(String key, Object value) {
- MetadataContextHolder.get().getMetadataContainer(MetadataType.APPLICATION, true).
+ MetadataContextHolder.get().getMetadataContainer(MetadataType.CUSTOM, false).
putMetadataObjectValue(key, value);
}
diff --git a/spring-cloud-tencent-dependencies/pom.xml b/spring-cloud-tencent-dependencies/pom.xml
index 6045fe525..ef75f7131 100644
--- a/spring-cloud-tencent-dependencies/pom.xml
+++ b/spring-cloud-tencent-dependencies/pom.xml
@@ -178,6 +178,12 @@
${revision}
+
+ com.tencent.cloud
+ spring-cloud-tencent-unit-plugin
+ ${revision}
+
+
com.tencent.cloud
spring-cloud-starter-tencent-threadlocal-plugin
diff --git a/spring-cloud-tencent-plugin-starters/pom.xml b/spring-cloud-tencent-plugin-starters/pom.xml
index 149ece160..82d740823 100644
--- a/spring-cloud-tencent-plugin-starters/pom.xml
+++ b/spring-cloud-tencent-plugin-starters/pom.xml
@@ -18,6 +18,7 @@
spring-cloud-starter-tencent-gateway-plugin
spring-cloud-starter-tencent-discovery-adapter-plugin
spring-cloud-tencent-lossless-plugin
+ spring-cloud-tencent-unit-plugin
spring-cloud-starter-tencent-threadlocal-plugin
spring-cloud-starter-tencent-trace-plugin
spring-cloud-starter-tencent-fault-tolerance
diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-injection-plugin/src/main/java/com/tencent/cloud/plugin/fault/FaultInjectionPrePlugin.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-injection-plugin/src/main/java/com/tencent/cloud/plugin/fault/FaultInjectionPrePlugin.java
index a02b982bf..fa612c0b8 100644
--- a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-injection-plugin/src/main/java/com/tencent/cloud/plugin/fault/FaultInjectionPrePlugin.java
+++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-injection-plugin/src/main/java/com/tencent/cloud/plugin/fault/FaultInjectionPrePlugin.java
@@ -22,6 +22,7 @@ import java.util.HashMap;
import com.tencent.cloud.common.constant.ContextConstant;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
+import com.tencent.cloud.common.util.MetadataContextUtils;
import com.tencent.cloud.plugin.fault.config.FaultInjectionProperties;
import com.tencent.cloud.plugin.fault.instrument.resttemplate.PolarisFaultInjectionHttpResponse;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
@@ -37,7 +38,6 @@ import com.tencent.polaris.fault.api.rpc.DelayResult;
import com.tencent.polaris.fault.api.rpc.FaultRequest;
import com.tencent.polaris.fault.api.rpc.FaultResponse;
import com.tencent.polaris.fault.client.exception.FaultInjectionException;
-import com.tencent.polaris.metadata.core.MetadataType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -94,18 +94,13 @@ public class FaultInjectionPrePlugin implements EnhancedPlugin {
CircuitBreakerStatus.FallbackInfo fallbackInfo = new CircuitBreakerStatus.FallbackInfo(abortResult.getAbortCode(), new HashMap<>(), "");
if (ClassUtils.isClassPresent("org.springframework.http.client.ClientHttpResponse")) {
Object fallbackResponse = new PolarisFaultInjectionHttpResponse(fallbackInfo);
- putMetadataObjectValue(ContextConstant.FaultInjection.FAULT_INJECTION_FALLBACK_HTTP_RESPONSE, fallbackResponse);
+ MetadataContextUtils.putMetadataObjectValue(ContextConstant.FaultInjection.FAULT_INJECTION_FALLBACK_HTTP_RESPONSE, fallbackResponse);
}
throw new FaultInjectionException(fallbackInfo);
}
}
}
- private void putMetadataObjectValue(String key, Object value) {
- MetadataContextHolder.get().getMetadataContainer(MetadataType.APPLICATION, true).
- putMetadataObjectValue(key, value);
- }
-
@Override
public void handlerThrowable(EnhancedPluginContext context, Throwable throwable) {
LOG.error("FaultInjectionPrePlugin runs failed. context=[{}].", context, throwable);
diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-gateway-plugin/pom.xml b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-gateway-plugin/pom.xml
index 64bbb5991..4690f32c7 100644
--- a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-gateway-plugin/pom.xml
+++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-gateway-plugin/pom.xml
@@ -19,6 +19,11 @@
spring-cloud-starter-tencent-polaris-config
+
+ com.tencent.cloud
+ spring-cloud-tencent-unit-plugin
+
+
com.tencent.cloud
spring-cloud-starter-tencent-polaris-discovery
diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-gateway-plugin/src/main/java/com/tencent/cloud/plugin/gateway/context/ContextGatewayFilter.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-gateway-plugin/src/main/java/com/tencent/cloud/plugin/gateway/context/ContextGatewayFilter.java
index b69ba8d7e..90eb8a282 100644
--- a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-gateway-plugin/src/main/java/com/tencent/cloud/plugin/gateway/context/ContextGatewayFilter.java
+++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-gateway-plugin/src/main/java/com/tencent/cloud/plugin/gateway/context/ContextGatewayFilter.java
@@ -19,6 +19,7 @@ package com.tencent.cloud.plugin.gateway.context;
import java.lang.reflect.Constructor;
import java.net.URI;
+import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
@@ -27,12 +28,15 @@ import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import com.tencent.cloud.common.constant.ContextConstant;
import com.tencent.cloud.common.constant.MetadataConstant;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
+import com.tencent.cloud.common.util.JacksonUtils;
import com.tencent.cloud.common.util.MetadataContextUtils;
+import com.tencent.cloud.plugin.unit.utils.SpringCloudUnitUtils;
import com.tencent.polaris.api.utils.CollectionUtils;
import com.tencent.polaris.api.utils.StringUtils;
import com.tencent.tsf.gateway.core.TsfGatewayRequest;
@@ -47,6 +51,9 @@ import com.tencent.tsf.gateway.core.plugin.GatewayPluginFactory;
import com.tencent.tsf.gateway.core.plugin.IGatewayPlugin;
import com.tencent.tsf.gateway.core.util.CookieUtil;
import com.tencent.tsf.gateway.core.util.IdGenerator;
+import com.tencent.tsf.unit.core.TencentUnitContext;
+import com.tencent.tsf.unit.core.TencentUnitManager;
+import com.tencent.tsf.unit.core.model.UnitTagPosition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.core.publisher.Mono;
@@ -94,6 +101,7 @@ public class ContextGatewayFilter implements GatewayFilter, Ordered {
if (pathRewriteException != null) {
throw pathRewriteException;
}
+
// plugins will add metadata
if (exchange.getAttributes().containsKey(MetadataConstant.HeaderName.METADATA_CONTEXT)) {
MetadataContextHolder.set((MetadataContext) exchange.getAttributes().get(
@@ -114,11 +122,17 @@ public class ContextGatewayFilter implements GatewayFilter, Ordered {
ServerWebExchange apiRebuildExchange;
- if (ApiType.MS.equals(groupContext.getPredicate().getApiType())) {
- apiRebuildExchange = msFilter(exchange, chain, groupContext, path);
+ if (TencentUnitManager.isEnable()) {
+ unitPreprocess(exchange);
+ apiRebuildExchange = unitFilter(exchange, chain, groupContext, path);
}
else {
- apiRebuildExchange = externalFilter(exchange, chain, path);
+ if (ApiType.MS.equals(groupContext.getPredicate().getApiType())) {
+ apiRebuildExchange = msFilter(exchange, chain, groupContext, path);
+ }
+ else {
+ apiRebuildExchange = externalFilter(exchange, chain, path);
+ }
}
ServerWebExchange pluginRebuildExchange = doPlugins(apiRebuildExchange,
@@ -283,6 +297,83 @@ public class ContextGatewayFilter implements GatewayFilter, Ordered {
return exchange.mutate().request(newRequest).build();
}
+ private void unitPreprocess(ServerWebExchange exchange) {
+ // 提前到这里清理
+ TencentUnitContext.removeAll();
+
+ ServerHttpRequest servletRequest = exchange.getRequest();
+ HttpHeaders headers = servletRequest.getHeaders();
+ String unitAttr = Optional.ofNullable(headers.getFirst(HeaderName.UNIT)).orElse("");
+
+ String cid = headers.getFirst(TencentUnitManager.getRouterIdentifierHeader());
+
+ for (String grayKey: TencentUnitManager.getGrayUnitHeaderKey()) {
+ TencentUnitContext.putGrayUserTag(UnitTagPosition.HEADER.name(), grayKey, headers.getFirst(grayKey));
+ }
+
+ Map unitMap = JacksonUtils.deserialize2Map(URLDecoder.decode(unitAttr, StandardCharsets.UTF_8));
+ String path = exchange.getRequest().getURI().getPath();
+ if (CollectionUtils.isEmpty(unitMap)) {
+ SpringCloudUnitUtils.processFromCid(cid, path);
+ }
+ else {
+ SpringCloudUnitUtils.processFromUnitHeader(unitMap, path);
+ }
+ }
+
+ private ServerWebExchange unitFilter(ServerWebExchange exchange, GatewayFilterChain chain, GroupContext groupContext, PathContainer path) {
+ ServerHttpRequest request = exchange.getRequest();
+ String[] apis = rebuildUnitApi(request, path.value());
+ logger.debug("[unitFilter] path:{}, apis: {}", path, apis);
+ // check api
+ GroupContext.ContextRoute contextRoute = manager.getGroupUnitPathRoute(config.getGroup(), apis[0]);
+ if (contextRoute == null) {
+ String msg = String.format("[unitFilter] Can't find context route for group: %s, path: %s, origin path: %s", config.getGroup(), apis[0], path.value());
+ logger.warn(msg);
+ throw NotFoundException.create(true, msg);
+ }
+ updateRouteMetadata(exchange, contextRoute);
+ setTraceAttributes(contextRoute, GatewayConstant.UNIT_TYPE, GatewayConstant.UNIT_TRANSFER_TYPE);
+ exchange.getAttributes().put(GatewayConstant.CONTEXT_ROUTE, contextRoute);
+
+ MetadataContext metadataContext = exchange.getAttribute(
+ MetadataConstant.HeaderName.METADATA_CONTEXT);
+ if (metadataContext != null) {
+ // get unit ns
+ String routeNamespace = TencentUnitContext.getSystemTag(TencentUnitContext.CLOUD_SPACE_TARGET_NAMESPACE_ID);
+ metadataContext.putFragmentContext(MetadataContext.FRAGMENT_APPLICATION_NONE,
+ MetadataConstant.POLARIS_TARGET_NAMESPACE, routeNamespace);
+ }
+ URI requestUri = URI.create("lb://" + contextRoute.getService() + apis[1]);
+ exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, requestUri);
+ // to correct path
+ ServerHttpRequest newRequest = request.mutate().path(apis[1]).build();
+ return exchange.mutate().request(newRequest).build();
+ }
+
+ /**
+ * e.g. "/context/system/svc/api/test" → [ "GET|/svc/api/test", "/api/test"]
+ */
+ String[] rebuildUnitApi(ServerHttpRequest request, String path) {
+ String[] pathSegments = path.split("/");
+ StringBuilder matchPath = new StringBuilder();
+ matchPath.append(request.getMethod().name()).append("|");
+ if (pathSegments.length > 3) {
+ matchPath.append("/").append(pathSegments[3]);
+ }
+ StringBuilder realPath = new StringBuilder();
+ int index = 4;
+ for (int i = index; i < pathSegments.length; i++) {
+ matchPath.append("/").append(pathSegments[i]);
+ realPath.append("/").append(pathSegments[i]);
+ }
+ if (path.endsWith("/")) {
+ matchPath.append("/");
+ realPath.append("/");
+ }
+ return new String[] {matchPath.toString(), realPath.toString()};
+ }
+
/**
* e.g. "/context/api/test" → [ "GET|/api/test", "/api/test"]
*/
diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-gateway-plugin/src/main/java/com/tencent/cloud/plugin/gateway/context/ContextGatewayPropertiesManager.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-gateway-plugin/src/main/java/com/tencent/cloud/plugin/gateway/context/ContextGatewayPropertiesManager.java
index 38ecd8af6..1736af61c 100644
--- a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-gateway-plugin/src/main/java/com/tencent/cloud/plugin/gateway/context/ContextGatewayPropertiesManager.java
+++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-gateway-plugin/src/main/java/com/tencent/cloud/plugin/gateway/context/ContextGatewayPropertiesManager.java
@@ -58,6 +58,14 @@ public class ContextGatewayPropertiesManager {
* context -> {wildcard path key -> route}.
*/
private volatile ConcurrentHashMap> groupWildcardPathRouteMap = new ConcurrentHashMap<>();
+ /**
+ * context -> {unit path key -> route}.
+ */
+ private volatile ConcurrentHashMap> groupUnitPathRouteMap = new ConcurrentHashMap<>();
+ /**
+ * context -> {unit wildcard path key -> route}.
+ */
+ private volatile ConcurrentHashMap> groupUnitWildcardPathRouteMap = new ConcurrentHashMap<>();
/**
* group -> plugin info.
*/
@@ -145,31 +153,47 @@ public class ContextGatewayPropertiesManager {
ConcurrentHashMap> newGroupPathRouteMap = new ConcurrentHashMap<>();
ConcurrentHashMap> newGroupWildcardPathRouteMap = new ConcurrentHashMap<>();
+ ConcurrentHashMap> newGroupUnitPathRouteMap = new ConcurrentHashMap<>();
+ ConcurrentHashMap> newGroupUnitWildcardPathRouteMap = new ConcurrentHashMap<>();
+
if (groups != null) {
for (Map.Entry entry : groups.entrySet()) {
GroupContext groupContext = entry.getValue();
Map newGroupPathRoute = new HashMap<>();
Map newGroupWildcardPathRoute = new HashMap<>();
+ Map newGroupUnitPathRoute = new HashMap<>();
+ Map newGroupUnitWildcardPathRoute = new HashMap<>();
+
for (GroupContext.ContextRoute route : groupContext.getRoutes()) {
String path = route.getPath();
// convert path parameter to group wildcard path
if (path.contains("{") && path.contains("}") || path.contains("*") || path.contains("?")) {
newGroupWildcardPathRoute.put(buildPathKey(groupContext, route), route);
+ newGroupUnitWildcardPathRoute.put(buildUnitPathKey(groupContext, route), route);
}
else {
newGroupPathRoute.put(buildPathKey(groupContext, route), route);
+ newGroupUnitPathRoute.put(buildUnitPathKey(groupContext, route), route);
if (StringUtils.isNotEmpty(route.getPathMapping())) {
newGroupPathRoute.put(buildPathMappingKey(groupContext, route), route);
+ newGroupUnitPathRoute.put(buildUnitPathKey(groupContext, route), route);
}
}
}
newGroupWildcardPathRouteMap.put(entry.getKey(), newGroupWildcardPathRoute);
newGroupPathRouteMap.put(entry.getKey(), newGroupPathRoute);
+
+ newGroupUnitWildcardPathRouteMap.put(entry.getKey(), newGroupUnitWildcardPathRoute);
+ newGroupUnitPathRouteMap.put(entry.getKey(), newGroupUnitPathRoute);
}
}
this.groupPathRouteMap = newGroupPathRouteMap;
this.groupWildcardPathRouteMap = newGroupWildcardPathRouteMap;
+
+ this.groupUnitPathRouteMap = newGroupUnitPathRouteMap;
+ this.groupUnitWildcardPathRouteMap = newGroupUnitWildcardPathRouteMap;
+
this.groups = groups;
}
@@ -195,6 +219,24 @@ public class ContextGatewayPropertiesManager {
return null;
}
+ public GroupContext.ContextRoute getGroupUnitPathRoute(String group, String path) {
+ Map groupPathRouteMap = this.groupUnitPathRouteMap.get(group);
+ if (groupPathRouteMap != null && groupPathRouteMap.containsKey(path)) {
+ return groupPathRouteMap.get(path);
+ }
+
+ Map groupWildcardPathRouteMap = this.groupUnitWildcardPathRouteMap.get(group);
+ if (groupWildcardPathRouteMap != null) {
+ for (Map.Entry entry : groupWildcardPathRouteMap.entrySet()) {
+ boolean matched = antPathMatcher.match(entry.getKey(), path);
+ if (matched) {
+ return entry.getValue();
+ }
+ }
+ }
+ return null;
+ }
+
public void eagerLoad(PolarisDiscoveryClient polarisDiscoveryClient,
PolarisReactiveDiscoveryClient polarisReactiveDiscoveryClient) {
for (Map contextRouteMap : groupPathRouteMap.values()) {
@@ -241,6 +283,10 @@ public class ContextGatewayPropertiesManager {
}
}
+ private String buildUnitPathKey(GroupContext groupContext, GroupContext.ContextRoute route) {
+ return String.format("%s|/%s%s", route.getMethod(), route.getService(), route.getPath());
+ }
+
private String buildPathMappingKey(GroupContext groupContext, GroupContext.ContextRoute route) {
return String.format("%s|%s", route.getMethod(), route.getPathMapping());
}
diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/attribute/tsf/TsfSpanAttributesProvider.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/attribute/tsf/TsfSpanAttributesProvider.java
index 3913b8173..d712e735b 100644
--- a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/attribute/tsf/TsfSpanAttributesProvider.java
+++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/attribute/tsf/TsfSpanAttributesProvider.java
@@ -65,14 +65,14 @@ public class TsfSpanAttributesProvider implements SpanAttributesProvider {
}
MetadataObjectValue langTagObject = MetadataContextHolder.get().
- getMetadataContainer(MetadataType.APPLICATION, true).
+ getMetadataContainer(MetadataType.CUSTOM, false).
getMetadataValue(ContextConstant.LANE_TAG);
if (MetadataContextUtils.existMetadataValue(langTagObject)) {
attributes.put(OtUtils.OTEL_LANE_ID_KEY, langTagObject.getObjectValue().get().getValue());
}
MetadataObjectValue