From 25bc8120b7ad701813be528a578f0b94e24c18cc Mon Sep 17 00:00:00 2001
From: shedfreewu <49236872+shedfreewu@users.noreply.github.com>
Date: Wed, 16 Jul 2025 21:04:30 +0800
Subject: [PATCH] feat: support spring-retry and feign config refresh and feign
eager load support schema (#1651)
---
CHANGELOG.md | 1 +
.../feign/FeignEagerLoadSmartLifecycle.java | 2 +-
.../tsf-example/consumer-demo-retry/pom.xml | 35 ++++
.../demo/consumer/ConsumerApplication.java | 41 +++++
.../controller/ConsumerController.java | 170 ++++++++++++++++++
.../demo/consumer/controller/SdkBaseTest.java | 54 ++++++
.../demo/consumer/entity/CustomMetadata.java | 32 ++++
.../consumer/proxy/ProviderDemoService.java | 36 ++++
.../demo/consumer/proxy/ProviderService.java | 44 +++++
.../src/main/resources/application.yml | 20 +++
.../controller/ConsumerController.java | 42 +++++
.../consumer/proxy/ProviderDemoService.java | 2 +-
.../tsf-example/pom.xml | 1 +
.../tsf/demo/provider/ProviderController.java | 22 +++
.../RpcEnhancementAutoConfiguration.java | 12 +-
.../loadbalancer/LoadBalancerUtils.java | 17 ++
16 files changed, 523 insertions(+), 8 deletions(-)
create mode 100644 spring-cloud-tencent-examples/tsf-example/consumer-demo-retry/pom.xml
create mode 100644 spring-cloud-tencent-examples/tsf-example/consumer-demo-retry/src/main/java/com/tencent/cloud/tsf/demo/consumer/ConsumerApplication.java
create mode 100644 spring-cloud-tencent-examples/tsf-example/consumer-demo-retry/src/main/java/com/tencent/cloud/tsf/demo/consumer/controller/ConsumerController.java
create mode 100644 spring-cloud-tencent-examples/tsf-example/consumer-demo-retry/src/main/java/com/tencent/cloud/tsf/demo/consumer/controller/SdkBaseTest.java
create mode 100644 spring-cloud-tencent-examples/tsf-example/consumer-demo-retry/src/main/java/com/tencent/cloud/tsf/demo/consumer/entity/CustomMetadata.java
create mode 100644 spring-cloud-tencent-examples/tsf-example/consumer-demo-retry/src/main/java/com/tencent/cloud/tsf/demo/consumer/proxy/ProviderDemoService.java
create mode 100644 spring-cloud-tencent-examples/tsf-example/consumer-demo-retry/src/main/java/com/tencent/cloud/tsf/demo/consumer/proxy/ProviderService.java
create mode 100644 spring-cloud-tencent-examples/tsf-example/consumer-demo-retry/src/main/resources/application.yml
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7cbe360c1..9eb572b2d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,3 +6,4 @@
- [feat:upgrade to 2023.0.6.](https://github.com/Tencent/spring-cloud-tencent/pull/1646)
- [feat:Add log output and test scenarios in the FaultToleranceService file.](https://github.com/Tencent/spring-cloud-tencent/pull/1652)
- [fix: fix ConfigChangeListener and unit test](https://github.com/Tencent/spring-cloud-tencent/pull/1656)
+- [feat: support spring-retry and feign config refresh and feign eager load support schema](https://github.com/Tencent/spring-cloud-tencent/pull/1651)
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/eager/instrument/feign/FeignEagerLoadSmartLifecycle.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/eager/instrument/feign/FeignEagerLoadSmartLifecycle.java
index 327edb59b..0f7804cc9 100644
--- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/eager/instrument/feign/FeignEagerLoadSmartLifecycle.java
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/eager/instrument/feign/FeignEagerLoadSmartLifecycle.java
@@ -68,7 +68,7 @@ public class FeignEagerLoadSmartLifecycle implements SmartLifecycle {
}
String serviceName = URI.create(url).getHost();
- LOG.info("[{}] eager-load start", serviceName);
+ LOG.info("[{}] eager-load start, feign name: {}", serviceName, hardCodedTarget.name());
if (polarisDiscoveryClient != null) {
polarisDiscoveryClient.getInstances(serviceName);
}
diff --git a/spring-cloud-tencent-examples/tsf-example/consumer-demo-retry/pom.xml b/spring-cloud-tencent-examples/tsf-example/consumer-demo-retry/pom.xml
new file mode 100644
index 000000000..b39c426ed
--- /dev/null
+++ b/spring-cloud-tencent-examples/tsf-example/consumer-demo-retry/pom.xml
@@ -0,0 +1,35 @@
+
+
+ 4.0.0
+
+ tsf-example
+ com.tencent.cloud
+ ${revision}
+ ../pom.xml
+
+ consumer-demo-retry
+
+
+
+ com.tencent.cloud
+ spring-cloud-starter-tencent-all
+
+
+
+ org.springframework.retry
+ spring-retry
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-openfeign
+
+
+
\ No newline at end of file
diff --git a/spring-cloud-tencent-examples/tsf-example/consumer-demo-retry/src/main/java/com/tencent/cloud/tsf/demo/consumer/ConsumerApplication.java b/spring-cloud-tencent-examples/tsf-example/consumer-demo-retry/src/main/java/com/tencent/cloud/tsf/demo/consumer/ConsumerApplication.java
new file mode 100644
index 000000000..87694e5b2
--- /dev/null
+++ b/spring-cloud-tencent-examples/tsf-example/consumer-demo-retry/src/main/java/com/tencent/cloud/tsf/demo/consumer/ConsumerApplication.java
@@ -0,0 +1,41 @@
+/*
+ * 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.tsf.demo.consumer;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.loadbalancer.LoadBalanced;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+import org.springframework.context.annotation.Bean;
+import org.springframework.tsf.annotation.EnableTsf;
+import org.springframework.web.client.RestTemplate;
+
+@SpringBootApplication
+@EnableFeignClients // 使用Feign微服务调用时请启用
+@EnableTsf
+public class ConsumerApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(ConsumerApplication.class, args);
+ }
+
+ @LoadBalanced
+ @Bean
+ public RestTemplate restTemplate() {
+ return new RestTemplate();
+ }
+}
diff --git a/spring-cloud-tencent-examples/tsf-example/consumer-demo-retry/src/main/java/com/tencent/cloud/tsf/demo/consumer/controller/ConsumerController.java b/spring-cloud-tencent-examples/tsf-example/consumer-demo-retry/src/main/java/com/tencent/cloud/tsf/demo/consumer/controller/ConsumerController.java
new file mode 100644
index 000000000..09326b06d
--- /dev/null
+++ b/spring-cloud-tencent-examples/tsf-example/consumer-demo-retry/src/main/java/com/tencent/cloud/tsf/demo/consumer/controller/ConsumerController.java
@@ -0,0 +1,170 @@
+/*
+ * 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.tsf.demo.consumer.controller;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+
+import com.tencent.cloud.common.util.PolarisCompletableFutureUtils;
+import com.tencent.cloud.tsf.demo.consumer.proxy.ProviderDemoService;
+import com.tencent.cloud.tsf.demo.consumer.proxy.ProviderService;
+import com.tencent.polaris.api.utils.StringUtils;
+import com.tencent.polaris.circuitbreak.client.exception.CallAbortedException;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.tsf.core.TsfContext;
+import org.springframework.tsf.core.entity.Tag;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.client.RestTemplate;
+
+@RestController
+public class ConsumerController {
+ @Autowired
+ private RestTemplate restTemplate;
+ @Autowired
+ private ProviderService providerService;
+ @Autowired
+ private ProviderDemoService providerDemoService;
+
+ @RequestMapping(value = "/echo-rest/{str}", method = RequestMethod.GET)
+ public String restProvider(@PathVariable String str,
+ @RequestParam(required = false) String tagName,
+ @RequestParam(required = false) String tagValue) {
+ if (StringUtils.isNotBlank(tagName)) {
+ TsfContext.putTag(tagName, tagValue);
+ }
+ TsfContext.putTag("operation", "rest");
+ Map mTags = new HashMap<>();
+ mTags.put("rest-trace-key1", "value1");
+ mTags.put("rest-trace-key2", "value2");
+ TsfContext.putTags(mTags, Tag.ControlFlag.TRANSITIVE);
+ try {
+ return restTemplate.getForObject("http://provider-demo/echo/" + str, String.class);
+ }
+ catch (CallAbortedException callAbortedException) {
+ return callAbortedException.getMessage();
+ }
+ }
+
+ @RequestMapping(value = "/echo-slow-rest/{str}", method = RequestMethod.GET)
+ public String restSlowProvider(@PathVariable String str,
+ @RequestParam(required = false) String tagName,
+ @RequestParam(required = false) String tagValue) {
+ if (StringUtils.isNotBlank(tagName)) {
+ TsfContext.putTag(tagName, tagValue);
+ }
+ TsfContext.putTag("operation", "rest");
+ Map mTags = new HashMap<>();
+ mTags.put("rest-trace-key1", "value1");
+ mTags.put("rest-trace-key2", "value2");
+ TsfContext.putTags(mTags, Tag.ControlFlag.TRANSITIVE);
+ try {
+ return restTemplate.getForObject("http://provider-demo/echo/slow/" + str, String.class);
+ }
+ catch (CallAbortedException callAbortedException) {
+ return callAbortedException.getMessage();
+ }
+ }
+
+
+ @RequestMapping(value = "/echo-rest-async/{str}", method = RequestMethod.GET)
+ public String restAsync(@PathVariable String str,
+ @RequestParam(required = false) String tagName,
+ @RequestParam(required = false) String tagValue) throws ExecutionException, InterruptedException {
+ if (StringUtils.isNotBlank(tagName)) {
+ TsfContext.putTag(tagName, tagValue);
+ }
+ TsfContext.putTag("operation", "rest");
+ Map mTags = new HashMap<>();
+ mTags.put("rest-trace-key1", "value1");
+ mTags.put("rest-trace-key2", "value2");
+ TsfContext.putTags(mTags, Tag.ControlFlag.TRANSITIVE);
+ CompletableFuture echoFuture = PolarisCompletableFutureUtils.supplyAsync(() -> {
+ try {
+ return restTemplate.getForObject("http://provider-demo/echo/" + str, String.class);
+ }
+ catch (CallAbortedException callAbortedException) {
+ return callAbortedException.getMessage();
+ }
+ });
+ return echoFuture.get();
+ }
+
+ @RequestMapping(value = "/echo-feign/{str}", method = RequestMethod.GET)
+ public String feignProvider(@PathVariable String str,
+ @RequestParam(required = false) String tagName,
+ @RequestParam(required = false) String tagValue) {
+ if (StringUtils.isNotBlank(tagName)) {
+ TsfContext.putTag(tagName, tagValue);
+ }
+ TsfContext.putTag("operation", "feign");
+ Map mTags = new HashMap<>();
+ mTags.put("feign-trace-key1", "value1");
+ mTags.put("feign-trace-key2", "value2");
+ TsfContext.putTags(mTags, Tag.ControlFlag.TRANSITIVE);
+ try {
+ return providerDemoService.echo(str);
+ }
+ catch (CallAbortedException callAbortedException) {
+ return callAbortedException.getMessage();
+ }
+ }
+
+ @RequestMapping(value = "/echo-slow-feign/{str}", method = RequestMethod.GET)
+ public String feignSlowProvider(@PathVariable String str,
+ @RequestParam(required = false) String tagName,
+ @RequestParam(required = false) String tagValue,
+ @RequestParam(required = false) String delay) {
+ if (StringUtils.isNotBlank(tagName)) {
+ TsfContext.putTag(tagName, tagValue);
+ }
+ TsfContext.putTag("operation", "feign");
+ Map mTags = new HashMap<>();
+ mTags.put("feign-trace-key1", "value1");
+ mTags.put("feign-trace-key2", "value2");
+ TsfContext.putTags(mTags, Tag.ControlFlag.TRANSITIVE);
+ int sleepTime = delay == null ? 1000 : Integer.parseInt(delay);
+ try {
+ return providerDemoService.echoSlow(str, sleepTime);
+ }
+ catch (CallAbortedException callAbortedException) {
+ return callAbortedException.getMessage();
+ }
+ }
+
+ @RequestMapping(value = "/echo-feign-url/{str}", method = RequestMethod.GET)
+ public String feignUrlProvider(@PathVariable String str,
+ @RequestParam(required = false) String tagName,
+ @RequestParam(required = false) String tagValue) {
+ if (StringUtils.isNotBlank(tagName)) {
+ TsfContext.putTag(tagName, tagValue);
+ }
+ TsfContext.putTag("operation", "feignUrl");
+ Map mTags = new HashMap<>();
+ mTags.put("feignUrl-trace-key1", "value1");
+ mTags.put("feignUrl-trace-key2", "value2");
+ TsfContext.putTags(mTags, Tag.ControlFlag.TRANSITIVE);
+ return providerService.echo(str);
+ }
+}
diff --git a/spring-cloud-tencent-examples/tsf-example/consumer-demo-retry/src/main/java/com/tencent/cloud/tsf/demo/consumer/controller/SdkBaseTest.java b/spring-cloud-tencent-examples/tsf-example/consumer-demo-retry/src/main/java/com/tencent/cloud/tsf/demo/consumer/controller/SdkBaseTest.java
new file mode 100644
index 000000000..1b68d6777
--- /dev/null
+++ b/spring-cloud-tencent-examples/tsf-example/consumer-demo-retry/src/main/java/com/tencent/cloud/tsf/demo/consumer/controller/SdkBaseTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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.tsf.demo.consumer.controller;
+
+import com.tencent.polaris.api.utils.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.tsf.core.TsfContext;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.client.RestTemplate;
+
+@RestController
+public class SdkBaseTest {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SdkBaseTest.class);
+
+ @Autowired
+ private RestTemplate restTemplate;
+
+ // 调用一次provider接口
+ @RequestMapping(value = "/echo-once/{str}", method = RequestMethod.GET)
+ public String restOnceProvider(@PathVariable String str,
+ @RequestParam(required = false) String tagName,
+ @RequestParam(required = false) String tagValue) {
+ if (!StringUtils.isEmpty(tagName)) {
+ TsfContext.putTag(tagName, tagValue);
+ }
+ LOG.info("start call echo-once");
+ String result = restTemplate.getForObject("http://provider-demo/echo/" + str, String.class);
+ LOG.info("end call echo-once, the result is : " + result);
+ return result;
+ }
+}
diff --git a/spring-cloud-tencent-examples/tsf-example/consumer-demo-retry/src/main/java/com/tencent/cloud/tsf/demo/consumer/entity/CustomMetadata.java b/spring-cloud-tencent-examples/tsf-example/consumer-demo-retry/src/main/java/com/tencent/cloud/tsf/demo/consumer/entity/CustomMetadata.java
new file mode 100644
index 000000000..f8c72a055
--- /dev/null
+++ b/spring-cloud-tencent-examples/tsf-example/consumer-demo-retry/src/main/java/com/tencent/cloud/tsf/demo/consumer/entity/CustomMetadata.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.tsf.demo.consumer.entity;
+
+/**
+ * 用户自定义 Metadata.
+ */
+public class CustomMetadata {
+
+ private String name;
+ private String value;
+
+ public CustomMetadata(String name, String value) {
+ this.name = name;
+ this.value = value;
+ }
+}
diff --git a/spring-cloud-tencent-examples/tsf-example/consumer-demo-retry/src/main/java/com/tencent/cloud/tsf/demo/consumer/proxy/ProviderDemoService.java b/spring-cloud-tencent-examples/tsf-example/consumer-demo-retry/src/main/java/com/tencent/cloud/tsf/demo/consumer/proxy/ProviderDemoService.java
new file mode 100644
index 000000000..d615ff08a
--- /dev/null
+++ b/spring-cloud-tencent-examples/tsf-example/consumer-demo-retry/src/main/java/com/tencent/cloud/tsf/demo/consumer/proxy/ProviderDemoService.java
@@ -0,0 +1,36 @@
+/*
+ * 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.tsf.demo.consumer.proxy;
+
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+
+@FeignClient(name = "${provider.name:provider-demo}")
+public interface ProviderDemoService {
+ @RequestMapping(value = "/echo/{str}", method = RequestMethod.GET)
+ String echo(@PathVariable("str") String str);
+
+ @RequestMapping(value = "/echo/error/{str}", method = RequestMethod.GET)
+ String echoError(@PathVariable("str") String str);
+
+ @RequestMapping(value = "/echo/slow/{str}", method = RequestMethod.GET)
+ String echoSlow(@PathVariable("str") String str, @RequestParam("delay") int delay);
+}
diff --git a/spring-cloud-tencent-examples/tsf-example/consumer-demo-retry/src/main/java/com/tencent/cloud/tsf/demo/consumer/proxy/ProviderService.java b/spring-cloud-tencent-examples/tsf-example/consumer-demo-retry/src/main/java/com/tencent/cloud/tsf/demo/consumer/proxy/ProviderService.java
new file mode 100644
index 000000000..abc552faf
--- /dev/null
+++ b/spring-cloud-tencent-examples/tsf-example/consumer-demo-retry/src/main/java/com/tencent/cloud/tsf/demo/consumer/proxy/ProviderService.java
@@ -0,0 +1,44 @@
+/*
+ * 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.tsf.demo.consumer.proxy;
+
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.stereotype.Component;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+/**
+ * 测试通过URL配置FeignClient
+ * 使用时修改provider-ip:provider-port配置
+ */
+@FeignClient(name = "provider", url = "http://127.0.0.1:18081", fallback = FeignClientFallback.class)
+public interface ProviderService {
+
+ @RequestMapping(value = "/echo/{str}", method = RequestMethod.GET)
+ String echo(@PathVariable("str") String str);
+
+}
+
+@Component
+class FeignClientFallback implements ProviderService {
+ @Override
+ public String echo(String str) {
+ return "tsf-fault-tolerance-" + str;
+ }
+}
diff --git a/spring-cloud-tencent-examples/tsf-example/consumer-demo-retry/src/main/resources/application.yml b/spring-cloud-tencent-examples/tsf-example/consumer-demo-retry/src/main/resources/application.yml
new file mode 100644
index 000000000..eb7a01b09
--- /dev/null
+++ b/spring-cloud-tencent-examples/tsf-example/consumer-demo-retry/src/main/resources/application.yml
@@ -0,0 +1,20 @@
+server:
+ port: 18083
+spring:
+ application:
+ name: consumer-demo
+ config:
+ import: optional:polaris
+
+feign:
+ tsf:
+ enabled: true
+
+#本地测试时打开
+#tsf_namespace_id: default_namespace
+
+logging:
+ file:
+ name: /tsf-demo-logs/${spring.application.name}/root.log
+ level:
+ root: INFO
diff --git a/spring-cloud-tencent-examples/tsf-example/consumer-demo/src/main/java/com/tencent/cloud/tsf/demo/consumer/controller/ConsumerController.java b/spring-cloud-tencent-examples/tsf-example/consumer-demo/src/main/java/com/tencent/cloud/tsf/demo/consumer/controller/ConsumerController.java
index 25e100fe7..09326b06d 100644
--- a/spring-cloud-tencent-examples/tsf-example/consumer-demo/src/main/java/com/tencent/cloud/tsf/demo/consumer/controller/ConsumerController.java
+++ b/spring-cloud-tencent-examples/tsf-example/consumer-demo/src/main/java/com/tencent/cloud/tsf/demo/consumer/controller/ConsumerController.java
@@ -67,6 +67,26 @@ public class ConsumerController {
}
}
+ @RequestMapping(value = "/echo-slow-rest/{str}", method = RequestMethod.GET)
+ public String restSlowProvider(@PathVariable String str,
+ @RequestParam(required = false) String tagName,
+ @RequestParam(required = false) String tagValue) {
+ if (StringUtils.isNotBlank(tagName)) {
+ TsfContext.putTag(tagName, tagValue);
+ }
+ TsfContext.putTag("operation", "rest");
+ Map mTags = new HashMap<>();
+ mTags.put("rest-trace-key1", "value1");
+ mTags.put("rest-trace-key2", "value2");
+ TsfContext.putTags(mTags, Tag.ControlFlag.TRANSITIVE);
+ try {
+ return restTemplate.getForObject("http://provider-demo/echo/slow/" + str, String.class);
+ }
+ catch (CallAbortedException callAbortedException) {
+ return callAbortedException.getMessage();
+ }
+ }
+
@RequestMapping(value = "/echo-rest-async/{str}", method = RequestMethod.GET)
public String restAsync(@PathVariable String str,
@@ -111,6 +131,28 @@ public class ConsumerController {
}
}
+ @RequestMapping(value = "/echo-slow-feign/{str}", method = RequestMethod.GET)
+ public String feignSlowProvider(@PathVariable String str,
+ @RequestParam(required = false) String tagName,
+ @RequestParam(required = false) String tagValue,
+ @RequestParam(required = false) String delay) {
+ if (StringUtils.isNotBlank(tagName)) {
+ TsfContext.putTag(tagName, tagValue);
+ }
+ TsfContext.putTag("operation", "feign");
+ Map mTags = new HashMap<>();
+ mTags.put("feign-trace-key1", "value1");
+ mTags.put("feign-trace-key2", "value2");
+ TsfContext.putTags(mTags, Tag.ControlFlag.TRANSITIVE);
+ int sleepTime = delay == null ? 1000 : Integer.parseInt(delay);
+ try {
+ return providerDemoService.echoSlow(str, sleepTime);
+ }
+ catch (CallAbortedException callAbortedException) {
+ return callAbortedException.getMessage();
+ }
+ }
+
@RequestMapping(value = "/echo-feign-url/{str}", method = RequestMethod.GET)
public String feignUrlProvider(@PathVariable String str,
@RequestParam(required = false) String tagName,
diff --git a/spring-cloud-tencent-examples/tsf-example/consumer-demo/src/main/java/com/tencent/cloud/tsf/demo/consumer/proxy/ProviderDemoService.java b/spring-cloud-tencent-examples/tsf-example/consumer-demo/src/main/java/com/tencent/cloud/tsf/demo/consumer/proxy/ProviderDemoService.java
index d615ff08a..a47ebd428 100644
--- a/spring-cloud-tencent-examples/tsf-example/consumer-demo/src/main/java/com/tencent/cloud/tsf/demo/consumer/proxy/ProviderDemoService.java
+++ b/spring-cloud-tencent-examples/tsf-example/consumer-demo/src/main/java/com/tencent/cloud/tsf/demo/consumer/proxy/ProviderDemoService.java
@@ -23,7 +23,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
-@FeignClient(name = "${provider.name:provider-demo}")
+@FeignClient(name = "${provider.name:http://provider-demo}")
public interface ProviderDemoService {
@RequestMapping(value = "/echo/{str}", method = RequestMethod.GET)
String echo(@PathVariable("str") String str);
diff --git a/spring-cloud-tencent-examples/tsf-example/pom.xml b/spring-cloud-tencent-examples/tsf-example/pom.xml
index a6db70129..979efb5f9 100644
--- a/spring-cloud-tencent-examples/tsf-example/pom.xml
+++ b/spring-cloud-tencent-examples/tsf-example/pom.xml
@@ -15,6 +15,7 @@
provider-demo
+ consumer-demo-retry
consumer-demo
diff --git a/spring-cloud-tencent-examples/tsf-example/provider-demo/src/main/java/com/tencent/cloud/tsf/demo/provider/ProviderController.java b/spring-cloud-tencent-examples/tsf-example/provider-demo/src/main/java/com/tencent/cloud/tsf/demo/provider/ProviderController.java
index eaba3e34e..40c3f0758 100644
--- a/spring-cloud-tencent-examples/tsf-example/provider-demo/src/main/java/com/tencent/cloud/tsf/demo/provider/ProviderController.java
+++ b/spring-cloud-tencent-examples/tsf-example/provider-demo/src/main/java/com/tencent/cloud/tsf/demo/provider/ProviderController.java
@@ -29,7 +29,9 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@@ -52,6 +54,8 @@ public class ProviderController {
@Autowired
private ProviderNameConfig providerNameConfig;
+ private boolean ifBadGateway = false;
+
// 获取本机ip
public static String getInet4Address() {
Enumeration nis;
@@ -85,6 +89,11 @@ public class ProviderController {
@RequestMapping(value = "/echo/{param}", method = RequestMethod.GET)
public ResponseEntity echo(@PathVariable String param) {
+ if (ifBadGateway) {
+ LOG.info("Provider Demo is called wrong.");
+ return new ResponseEntity<>("failed for call provider demo service. Address: " + getInet4Address(), HttpStatus.BAD_GATEWAY);
+ }
+
int status;
String responseBody;
@@ -149,4 +158,17 @@ public class ProviderController {
LOG.info("provider-demo -- unit response info: [" + result + "]");
return result;
}
+
+ @GetMapping("/setBadGateway")
+ public String setBadGateway(@RequestParam boolean param) {
+ this.ifBadGateway = param;
+ if (param) {
+ LOG.info("info is set to return HttpStatus.BAD_GATEWAY.");
+ return "info is set to return HttpStatus.BAD_GATEWAY.";
+ }
+ else {
+ LOG.info("info is set to return HttpStatus.OK.");
+ return "info is set to return HttpStatus.OK.";
+ }
+ }
}
diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/config/RpcEnhancementAutoConfiguration.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/config/RpcEnhancementAutoConfiguration.java
index edda6e380..4e45577cb 100644
--- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/config/RpcEnhancementAutoConfiguration.java
+++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/config/RpcEnhancementAutoConfiguration.java
@@ -115,12 +115,6 @@ public class RpcEnhancementAutoConfiguration {
return new ExceptionPolarisReporter(properties, polarisSDKContextManager.getConsumerAPI());
}
- @Bean
- @ConditionalOnClass(name = "org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor")
- public BlockingLoadBalancerClientBeanPostProcessor loadBalancerInterceptorBeanPostProcessor() {
- return new BlockingLoadBalancerClientBeanPostProcessor();
- }
-
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
protected static class RpcEnhancementServletFilterConfig {
@@ -195,6 +189,12 @@ public class RpcEnhancementAutoConfiguration {
return new PolarisLoadBalancerRequestTransformer();
}
+ @Bean
+ @ConditionalOnClass(name = "org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor")
+ public BlockingLoadBalancerClientBeanPostProcessor loadBalancerInterceptorBeanPostProcessor() {
+ return new BlockingLoadBalancerClientBeanPostProcessor();
+ }
+
}
diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerUtils.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerUtils.java
index df459747f..f9552f798 100644
--- a/spring-cloud-tencent-rpc-enhancement/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerUtils.java
+++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerUtils.java
@@ -1,3 +1,20 @@
+/*
+ * 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 org.springframework.cloud.client.loadbalancer;
import java.lang.reflect.Field;