From 7547377101002e9b14d477a0876ced7a6044866d Mon Sep 17 00:00:00 2001 From: weihu Date: Tue, 21 Jun 2022 19:18:22 +0800 Subject: [PATCH] add restTemplate Report Polaris --- .../PolarisResponseErrorHandler.java | 11 +++ ...larisRestTemplateResponseErrorHandler.java | 91 +++++++++++++++++++ .../circuitbreaker/example/ServiceA.java | 10 +- .../example/ServiceAController.java | 5 + 4 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/PolarisResponseErrorHandler.java create mode 100644 spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/PolarisRestTemplateResponseErrorHandler.java diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/PolarisResponseErrorHandler.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/PolarisResponseErrorHandler.java new file mode 100644 index 000000000..b793f5a61 --- /dev/null +++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/PolarisResponseErrorHandler.java @@ -0,0 +1,11 @@ +package com.tencent.cloud.polaris.circuitbreaker; + +import org.springframework.web.client.ResponseErrorHandler; + +/** + * @author : wh + * @date : 2022/6/21 19:12 + * @description: + */ +public interface PolarisResponseErrorHandler extends ResponseErrorHandler { +} diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/PolarisRestTemplateResponseErrorHandler.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/PolarisRestTemplateResponseErrorHandler.java new file mode 100644 index 000000000..22aeb5728 --- /dev/null +++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/PolarisRestTemplateResponseErrorHandler.java @@ -0,0 +1,91 @@ +package com.tencent.cloud.polaris.circuitbreaker; + +import com.tencent.cloud.common.metadata.MetadataContext; +import com.tencent.cloud.common.util.ReflectionUtils; +import com.tencent.polaris.api.core.ConsumerAPI; +import com.tencent.polaris.api.pojo.RetStatus; +import com.tencent.polaris.api.pojo.ServiceKey; +import com.tencent.polaris.api.rpc.ServiceCallResult; +import com.tencent.polaris.api.utils.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpMethod; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.web.client.ResponseErrorHandler; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.URL; +import java.util.Objects; + +/** + * @author : wh + * @date : 2022/6/21 17:25 + * @description: + */ +public class PolarisRestTemplateResponseErrorHandler implements ResponseErrorHandler { + + private static final Logger LOG = LoggerFactory.getLogger(PolarisRestTemplateResponseErrorHandler.class); + + private static final String FileName = "connection"; + + private final ConsumerAPI consumerAPI; + + private final PolarisResponseErrorHandler polarisResponseErrorHandler; + + + public PolarisRestTemplateResponseErrorHandler(ConsumerAPI consumerAPI, PolarisResponseErrorHandler polarisResponseErrorHandler) { + this.consumerAPI = consumerAPI; + this.polarisResponseErrorHandler = polarisResponseErrorHandler; + } + + @Override + public boolean hasError(ClientHttpResponse response) { + return true; + } + + @Override + public void handleError(ClientHttpResponse response) throws IOException{ + if (Objects.nonNull(polarisResponseErrorHandler)) { + if (polarisResponseErrorHandler.hasError(response)) { + polarisResponseErrorHandler.handleError(response); + } + } + } + + public void handleError(URI url, HttpMethod method, ClientHttpResponse response) { + ServiceCallResult resultRequest = null; + try { + resultRequest = builderServiceCallResult(url, method, response); + } catch (IOException e) { + LOG.error("Will report response of {} url {}", response, url, e); + throw new RuntimeException(e); + } finally { + consumerAPI.updateServiceCallResult(resultRequest); + } + } + + private ServiceCallResult builderServiceCallResult(URI url, HttpMethod method, ClientHttpResponse response) throws IOException { + ServiceCallResult resultRequest = new ServiceCallResult(); + String serviceName = url.getHost(); + resultRequest.setService(serviceName); + resultRequest.setNamespace(MetadataContext.LOCAL_NAMESPACE); + resultRequest.setMethod(url.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)); + } + HttpURLConnection connection = (HttpURLConnection) ReflectionUtils.getFieldValue(response, FileName); + URL url1 = connection.getURL(); + resultRequest.setHost(url1.getHost()); + resultRequest.setPort(url1.getPort()); + if (response.getStatusCode().is5xxServerError()) { + resultRequest.setRetStatus(RetStatus.RetFail); + } + return resultRequest; + } + +} diff --git a/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-example-a/src/main/java/com/tencent/cloud/polaris/circuitbreaker/example/ServiceA.java b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-example-a/src/main/java/com/tencent/cloud/polaris/circuitbreaker/example/ServiceA.java index 1c96db6c9..40d825072 100644 --- a/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-example-a/src/main/java/com/tencent/cloud/polaris/circuitbreaker/example/ServiceA.java +++ b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-example-a/src/main/java/com/tencent/cloud/polaris/circuitbreaker/example/ServiceA.java @@ -18,6 +18,10 @@ package com.tencent.cloud.polaris.circuitbreaker.example; +import com.tencent.cloud.polaris.circuitbreaker.PolarisResponseErrorHandler; +import com.tencent.cloud.polaris.circuitbreaker.PolarisRestTemplateResponseErrorHandler; +import com.tencent.polaris.api.core.ConsumerAPI; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.loadbalancer.LoadBalanced; @@ -40,8 +44,10 @@ public class ServiceA { @Bean @LoadBalanced - public RestTemplate restTemplate() { - return new RestTemplate(); + public RestTemplate restTemplate(ConsumerAPI consumerAPI, @Autowired(required = false) PolarisResponseErrorHandler polarisResponseErrorHandler) { + RestTemplate restTemplate = new RestTemplate(); + restTemplate.setErrorHandler(new PolarisRestTemplateResponseErrorHandler(consumerAPI, polarisResponseErrorHandler)); + return restTemplate; } } diff --git a/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-example-a/src/main/java/com/tencent/cloud/polaris/circuitbreaker/example/ServiceAController.java b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-example-a/src/main/java/com/tencent/cloud/polaris/circuitbreaker/example/ServiceAController.java index d9d2e4370..f491b4dd4 100644 --- a/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-example-a/src/main/java/com/tencent/cloud/polaris/circuitbreaker/example/ServiceAController.java +++ b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-example-a/src/main/java/com/tencent/cloud/polaris/circuitbreaker/example/ServiceAController.java @@ -48,6 +48,11 @@ public class ServiceAController { return polarisServiceB.info(); } + @GetMapping("/getBServiceInfo1") + public String rest() { + return restTemplate.getForObject("http://polaris-circuitbreaker-example-b//example/service/b/info",String.class); + } + /** * Get info of Service B by RestTemplate. * @return info of Service B