diff --git a/CHANGELOG.md b/CHANGELOG.md index b5ca0356..8176614f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,3 +3,4 @@ - [fix: fix log feign response stream close bug.](https://github.com/Tencent/spring-cloud-tencent/pull/898) - [fix:remove the secondary report.](https://github.com/Tencent/spring-cloud-tencent/pull/901) +- [fix:optimize instance circuit beaker.](https://github.com/Tencent/spring-cloud-tencent/pull/910) diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/pom.xml b/spring-cloud-starter-tencent-polaris-circuitbreaker/pom.xml index 6ce29236..58a68a42 100644 --- a/spring-cloud-starter-tencent-polaris-circuitbreaker/pom.xml +++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/pom.xml @@ -80,6 +80,20 @@ + + com.tencent.polaris + healthchecker-http + + + + com.tencent.polaris + healthchecker-udp + + + + com.tencent.polaris + healthchecker-tcp + diff --git a/spring-cloud-starter-tencent-polaris-ratelimit/pom.xml b/spring-cloud-starter-tencent-polaris-ratelimit/pom.xml index 0dd4540f..5df5c018 100644 --- a/spring-cloud-starter-tencent-polaris-ratelimit/pom.xml +++ b/spring-cloud-starter-tencent-polaris-ratelimit/pom.xml @@ -17,7 +17,7 @@ com.tencent.cloud - spring-cloud-tencent-polaris-context + spring-cloud-tencent-rpc-enhancement diff --git a/spring-cloud-tencent-dependencies/pom.xml b/spring-cloud-tencent-dependencies/pom.xml index 94ba1724..07eda3bd 100644 --- a/spring-cloud-tencent-dependencies/pom.xml +++ b/spring-cloud-tencent-dependencies/pom.xml @@ -73,7 +73,7 @@ 1.11.0-2022.0.1-SNAPSHOT - 1.11.1 + 1.11.2 31.1-jre 4.9.0 1.12.19 diff --git a/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-callee-service2/src/main/java/com/tencent/cloud/polaris/ciruitbreaker/example/ServiceBController.java b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-callee-service2/src/main/java/com/tencent/cloud/polaris/ciruitbreaker/example/ServiceBController.java index 38416781..21325f7e 100644 --- a/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-callee-service2/src/main/java/com/tencent/cloud/polaris/ciruitbreaker/example/ServiceBController.java +++ b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-callee-service2/src/main/java/com/tencent/cloud/polaris/ciruitbreaker/example/ServiceBController.java @@ -18,10 +18,14 @@ package com.tencent.cloud.polaris.ciruitbreaker.example; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; /** @@ -33,14 +37,47 @@ import org.springframework.web.bind.annotation.RestController; @RequestMapping("/example/service/b") public class ServiceBController { + private static final Logger LOG = LoggerFactory.getLogger(ServiceBController.class); + + private boolean ifBadGateway = true; + + private boolean ifDelay = true; + + @GetMapping("/setBadGateway") + public void setBadGateway(@RequestParam boolean param) { + if (param) { + LOG.info("info is set to return HttpStatus.BAD_GATEWAY."); + } + else { + LOG.info("info is set to return HttpStatus.OK."); + } + this.ifBadGateway = param; + } + + @GetMapping("/setDelay") + public void setDelay(@RequestParam boolean param) { + if (param) { + LOG.info("info is set to delay 100ms."); + } + else { + LOG.info("info is set to no delay."); + } + this.ifDelay = param; + } + /** * Get service information. * * @return service information */ @GetMapping("/info") - @ResponseStatus(value = HttpStatus.BAD_GATEWAY, reason = "failed for call my service") - public String info() { - return "failed for call service B2"; + public ResponseEntity info() throws InterruptedException { + if (ifBadGateway) { + return new ResponseEntity<>("failed for call my service", HttpStatus.BAD_GATEWAY); + } + if (ifDelay) { + Thread.sleep(100); + } + return new ResponseEntity<>("hello world ! I'm a service B2", HttpStatus.OK); } } diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignClient.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignClient.java index 4bdf14ef..b01850d4 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignClient.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignClient.java @@ -40,7 +40,7 @@ public class EnhancedFeignClient implements Client { private final Client delegate; - private EnhancedFeignPluginRunner pluginRunner; + private final EnhancedFeignPluginRunner pluginRunner; public EnhancedFeignClient(Client target, EnhancedFeignPluginRunner pluginRunner) { this.delegate = checkNotNull(target, "target"); @@ -56,7 +56,9 @@ public class EnhancedFeignClient implements Client { // Run pre enhanced feign plugins. pluginRunner.run(PRE, enhancedFeignContext); try { + long startMillis = System.currentTimeMillis(); Response response = delegate.execute(request, options); + enhancedFeignContext.setDelay(System.currentTimeMillis() - startMillis); enhancedFeignContext.setResponse(response); // Run post enhanced feign plugins. diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/plugin/EnhancedFeignContext.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/plugin/EnhancedFeignContext.java index e6f3be61..d1d9aded 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/plugin/EnhancedFeignContext.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/plugin/EnhancedFeignContext.java @@ -35,6 +35,8 @@ public class EnhancedFeignContext { private Exception exception; + private long delay; + public Request getRequest() { return request; } @@ -66,4 +68,12 @@ public class EnhancedFeignContext { public void setException(Exception exception) { this.exception = exception; } + + public long getDelay() { + return delay; + } + + public void setDelay(long delay) { + this.delay = delay; + } } diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/plugin/reporter/ExceptionPolarisReporter.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/plugin/reporter/ExceptionPolarisReporter.java index a1496fa1..b46f1435 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/plugin/reporter/ExceptionPolarisReporter.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/plugin/reporter/ExceptionPolarisReporter.java @@ -72,12 +72,13 @@ public class ExceptionPolarisReporter implements EnhancedFeignPlugin { Response response = context.getResponse(); Exception exception = context.getException(); RetStatus retStatus = RetStatus.RetFail; + long delay = context.getDelay(); if (exception instanceof SocketTimeoutException) { retStatus = RetStatus.RetTimeout; } - LOG.debug("Will report result of {}. Request=[{} {}]. Response=[{}].", retStatus.name(), request.httpMethod() - .name(), request.url(), response.status()); - ServiceCallResult resultRequest = ReporterUtils.createServiceCallResult(request, retStatus); + LOG.debug("Will report result of {}. Request=[{} {}]. Response=[{}]. Delay=[{}]ms.", retStatus.name(), request.httpMethod() + .name(), request.url(), response.status(), delay); + ServiceCallResult resultRequest = ReporterUtils.createServiceCallResult(request, response, delay, retStatus); consumerAPI.updateServiceCallResult(resultRequest); } } diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/plugin/reporter/ReporterUtils.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/plugin/reporter/ReporterUtils.java index 289a3d5e..d56ecf32 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/plugin/reporter/ReporterUtils.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/plugin/reporter/ReporterUtils.java @@ -30,6 +30,7 @@ import com.tencent.polaris.api.rpc.ServiceCallResult; import com.tencent.polaris.api.utils.CollectionUtils; import feign.Request; import feign.RequestTemplate; +import feign.Response; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -48,7 +49,7 @@ public final class ReporterUtils { private ReporterUtils() { } - public static ServiceCallResult createServiceCallResult(final Request request, RetStatus retStatus) { + public static ServiceCallResult createServiceCallResult(final Request request, final Response response, long delay, RetStatus retStatus) { ServiceCallResult resultRequest = new ServiceCallResult(); resultRequest.setNamespace(MetadataContext.LOCAL_NAMESPACE); @@ -68,7 +69,9 @@ public final class ReporterUtils { } URI uri = URI.create(request.url()); resultRequest.setMethod(uri.getPath()); + resultRequest.setRetCode(response.status()); resultRequest.setRetStatus(retStatus); + resultRequest.setDelay(delay); String sourceNamespace = MetadataContext.LOCAL_NAMESPACE; String sourceService = MetadataContext.LOCAL_SERVICE; if (StringUtils.isNotBlank(sourceNamespace) && StringUtils.isNotBlank(sourceService)) { diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/plugin/reporter/SuccessPolarisReporter.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/plugin/reporter/SuccessPolarisReporter.java index cc009d1b..54a389c8 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/plugin/reporter/SuccessPolarisReporter.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/plugin/reporter/SuccessPolarisReporter.java @@ -69,12 +69,13 @@ public class SuccessPolarisReporter extends AbstractPolarisReporterAdapter imple Request request = context.getRequest(); Response response = context.getResponse(); RetStatus retStatus = RetStatus.RetSuccess; + long delay = context.getDelay(); if (apply(HttpStatus.resolve(response.status()))) { retStatus = RetStatus.RetFail; } - LOG.debug("Will report result of {}. Request=[{} {}]. Response=[{}].", retStatus.name(), request.httpMethod() - .name(), request.url(), response.status()); - ServiceCallResult resultRequest = ReporterUtils.createServiceCallResult(request, retStatus); + LOG.debug("Will report result of {}. Request=[{} {}]. Response=[{}]. Delay=[{}]ms.", retStatus.name(), request.httpMethod() + .name(), request.url(), response.status(), delay); + ServiceCallResult resultRequest = ReporterUtils.createServiceCallResult(request, response, delay, retStatus); consumerAPI.updateServiceCallResult(resultRequest); } } diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/EnhancedRestTemplateReporter.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/EnhancedRestTemplateReporter.java index 627d402e..ccbbe22f 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/EnhancedRestTemplateReporter.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/EnhancedRestTemplateReporter.java @@ -119,12 +119,14 @@ public class EnhancedRestTemplateReporter extends AbstractPolarisReporterAdapter } private void reportResult(URI url, ClientHttpResponse response) { - ServiceCallResult resultRequest = createServiceCallResult(url); try { + ServiceCallResult resultRequest = createServiceCallResult(url, response); Map loadBalancerContext = MetadataContextHolder.get().getLoadbalancerMetadata(); String targetHost = loadBalancerContext.get("host"); String targetPort = loadBalancerContext.get("port"); + String startMillis = loadBalancerContext.get("startMillis"); + long delay = System.currentTimeMillis() - Long.parseLong(startMillis); if (StringUtils.isBlank(targetHost) || StringUtils.isBlank(targetPort)) { LOGGER.warn("Can not get target host or port from metadata context. host = {}, port = {}", targetHost, targetPort); @@ -133,6 +135,7 @@ public class EnhancedRestTemplateReporter extends AbstractPolarisReporterAdapter resultRequest.setHost(targetHost); resultRequest.setPort(Integer.parseInt(targetPort)); + resultRequest.setDelay(delay); // checking response http status code HttpStatusCode httpStatusCode = response.getStatusCode(); @@ -154,8 +157,8 @@ public class EnhancedRestTemplateReporter extends AbstractPolarisReporterAdapter } // processing report with consumerAPI . - LOGGER.debug("Will report result of {}. URL=[{}]. Response=[{}].", resultRequest.getRetStatus().name(), - url, response); + LOGGER.debug("Will report result of {}. Request=[{}]. Response=[{}]. Delay=[{}]ms.", resultRequest.getRetStatus() + .name(), url, httpStatusCode.value(), delay); consumerAPI.updateServiceCallResult(resultRequest); } catch (Exception e) { @@ -197,12 +200,13 @@ public class EnhancedRestTemplateReporter extends AbstractPolarisReporterAdapter response.getHeaders().remove(HEADER_HAS_ERROR); } - private ServiceCallResult createServiceCallResult(URI uri) { + private ServiceCallResult createServiceCallResult(URI uri, ClientHttpResponse response) throws IOException { ServiceCallResult resultRequest = new ServiceCallResult(); String serviceName = uri.getHost(); resultRequest.setService(serviceName); resultRequest.setNamespace(MetadataContext.LOCAL_NAMESPACE); resultRequest.setMethod(uri.getPath()); + resultRequest.setRetCode(response.getStatusCode().value()); resultRequest.setRetStatus(RetStatus.RetSuccess); String sourceNamespace = MetadataContext.LOCAL_NAMESPACE; String sourceService = MetadataContext.LOCAL_SERVICE; diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/LoadBalancerClientAspectUtils.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/LoadBalancerClientAspectUtils.java index 1b9f1163..ff44d659 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/LoadBalancerClientAspectUtils.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/LoadBalancerClientAspectUtils.java @@ -38,6 +38,7 @@ public final class LoadBalancerClientAspectUtils { ServiceInstance instance = (ServiceInstance) server; MetadataContextHolder.get().setLoadbalancer("host", instance.getHost()); MetadataContextHolder.get().setLoadbalancer("port", String.valueOf(instance.getPort())); + MetadataContextHolder.get().setLoadbalancer("startMillis", String.valueOf(System.currentTimeMillis())); } } } diff --git a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/feign/plugin/reporter/ExceptionPolarisReporterTest.java b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/feign/plugin/reporter/ExceptionPolarisReporterTest.java index 997f9b37..9e926703 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/feign/plugin/reporter/ExceptionPolarisReporterTest.java +++ b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/feign/plugin/reporter/ExceptionPolarisReporterTest.java @@ -39,6 +39,7 @@ import org.mockito.junit.jupiter.MockitoExtension; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; @@ -63,7 +64,7 @@ public class ExceptionPolarisReporterTest { @BeforeAll static void beforeAll() { mockedReporterUtils = Mockito.mockStatic(ReporterUtils.class); - mockedReporterUtils.when(() -> ReporterUtils.createServiceCallResult(any(Request.class), any(RetStatus.class))) + mockedReporterUtils.when(() -> ReporterUtils.createServiceCallResult(any(Request.class), any(Response.class), anyLong(), any(RetStatus.class))) .thenReturn(mock(ServiceCallResult.class)); } diff --git a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/feign/plugin/reporter/ReporterUtilsTest.java b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/feign/plugin/reporter/ReporterUtilsTest.java index c39dd163..409ac5f8 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/feign/plugin/reporter/ReporterUtilsTest.java +++ b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/feign/plugin/reporter/ReporterUtilsTest.java @@ -27,6 +27,7 @@ import com.tencent.polaris.api.pojo.RetStatus; import com.tencent.polaris.api.rpc.ServiceCallResult; import feign.Request; import feign.RequestTemplate; +import feign.Response; import feign.Target; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -94,7 +95,11 @@ public class ReporterUtilsTest { doReturn(requestTemplate).when(request).requestTemplate(); doReturn("http://1.1.1.1:2345/path").when(request).url(); - ServiceCallResult serviceCallResult = ReporterUtils.createServiceCallResult(request, RetStatus.RetSuccess); + // mock request + Response response = mock(Response.class); + doReturn(502).when(response).status(); + + ServiceCallResult serviceCallResult = ReporterUtils.createServiceCallResult(request, response, 10L, RetStatus.RetSuccess); assertThat(serviceCallResult.getNamespace()).isEqualTo(NAMESPACE_TEST); assertThat(serviceCallResult.getService()).isEqualTo(SERVICE_PROVIDER); assertThat(serviceCallResult.getHost()).isEqualTo("1.1.1.1"); @@ -104,5 +109,7 @@ public class ReporterUtilsTest { assertThat(serviceCallResult.getCallerService().getNamespace()).isEqualTo(NAMESPACE_TEST); assertThat(serviceCallResult.getCallerService().getService()).isEqualTo(SERVICE_PROVIDER); assertThat(serviceCallResult.getLabels()).isEqualTo("k1:v1|k2:v2"); + assertThat(serviceCallResult.getRetCode()).isEqualTo(502); + assertThat(serviceCallResult.getDelay()).isEqualTo(10L); } } diff --git a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/feign/plugin/reporter/SuccessPolarisReporterTest.java b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/feign/plugin/reporter/SuccessPolarisReporterTest.java index 2970baa8..b82eac46 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/feign/plugin/reporter/SuccessPolarisReporterTest.java +++ b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/feign/plugin/reporter/SuccessPolarisReporterTest.java @@ -39,6 +39,7 @@ import org.mockito.junit.jupiter.MockitoExtension; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; @@ -63,7 +64,7 @@ public class SuccessPolarisReporterTest { @BeforeAll static void beforeAll() { mockedReporterUtils = Mockito.mockStatic(ReporterUtils.class); - mockedReporterUtils.when(() -> ReporterUtils.createServiceCallResult(any(Request.class), any(RetStatus.class))) + mockedReporterUtils.when(() -> ReporterUtils.createServiceCallResult(any(Request.class), any(Response.class), anyLong(), any(RetStatus.class))) .thenReturn(mock(ServiceCallResult.class)); } diff --git a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/resttemplate/EnhancedRestTemplateReporterTest.java b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/resttemplate/EnhancedRestTemplateReporterTest.java index a431fbdb..c28f3c6e 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/resttemplate/EnhancedRestTemplateReporterTest.java +++ b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/resttemplate/EnhancedRestTemplateReporterTest.java @@ -89,6 +89,7 @@ public class EnhancedRestTemplateReporterTest { Map loadBalancerContext = new HashMap<>(); loadBalancerContext.put("host", "1.1.1.1"); loadBalancerContext.put("port", "8080"); + loadBalancerContext.put("startMillis", String.valueOf(System.currentTimeMillis())); when(metadataContext.getLoadbalancerMetadata()).thenReturn(loadBalancerContext); mockedMetadataContextHolder = Mockito.mockStatic(MetadataContextHolder.class);