Skip to content

Commit

Permalink
feat: add dstService path parameter for circuit breaker endpoint (#1159)
Browse files Browse the repository at this point in the history
  • Loading branch information
wenxuan70 authored Oct 8, 2023
1 parent abad0c3 commit 1a8974c
Show file tree
Hide file tree
Showing 13 changed files with 308 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,14 @@
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.util.JacksonUtils;
import com.tencent.cloud.polaris.context.ServiceRuleManager;
import com.tencent.polaris.api.utils.CollectionUtils;
import com.tencent.polaris.specification.api.v1.fault.tolerance.CircuitBreakerProto;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.boot.actuate.endpoint.annotation.Selector;

/**
* Endpoint of polaris circuit breaker, include circuit breaker rules.
Expand All @@ -51,36 +53,38 @@ public PolarisCircuitBreakerEndpoint(ServiceRuleManager serviceRuleManager) {
}

@ReadOperation
public Map<String, Object> circuitBreaker() {
CircuitBreakerProto.CircuitBreaker circuitBreaker = serviceRuleManager.getServiceCircuitBreakerRule(
public Map<String, Object> circuitBreaker(@Selector String dstService) {
List<CircuitBreakerProto.CircuitBreakerRule> rules = serviceRuleManager.getServiceCircuitBreakerRule(
MetadataContext.LOCAL_NAMESPACE,
MetadataContext.LOCAL_SERVICE
MetadataContext.LOCAL_SERVICE,
dstService
);

Map<String, Object> polarisCircuitBreakerInfo = new HashMap<>();

polarisCircuitBreakerInfo.put("namespace", MetadataContext.LOCAL_NAMESPACE);
polarisCircuitBreakerInfo.put("service", MetadataContext.LOCAL_SERVICE);
polarisCircuitBreakerInfo.put("circuitBreakerRules", parseCircuitBreakerRule(circuitBreaker));

return polarisCircuitBreakerInfo;
}
List<Object> circuitBreakerRules = new ArrayList<>();
if (CollectionUtils.isNotEmpty(rules)) {
for (CircuitBreakerProto.CircuitBreakerRule rule : rules) {
circuitBreakerRules.add(parseCircuitBreakerRule(rule));

private List<Object> parseCircuitBreakerRule(CircuitBreakerProto.CircuitBreaker circuitBreaker) {
List<Object> circuitBreakerRuleList = new ArrayList<>();

for (CircuitBreakerProto.CircuitBreakerRule circuitBreakerRule : circuitBreaker.getRulesList()) {
String ruleJson;
try {
ruleJson = JsonFormat.printer().print(circuitBreakerRule);
}
catch (InvalidProtocolBufferException e) {
LOG.error("rule to Json failed. check rule {}.", circuitBreakerRule, e);
throw new RuntimeException("Json failed.", e);
}
circuitBreakerRuleList.add(JacksonUtils.deserialize2Map(ruleJson));
}
polarisCircuitBreakerInfo.put("circuitBreakerRules", circuitBreakerRules);
return polarisCircuitBreakerInfo;
}

return circuitBreakerRuleList;
private Object parseCircuitBreakerRule(CircuitBreakerProto.CircuitBreakerRule circuitBreakerRule) {
String ruleJson;
try {
ruleJson = JsonFormat.printer().print(circuitBreakerRule);
}
catch (InvalidProtocolBufferException e) {
LOG.error("rule to Json failed. check rule {}.", circuitBreakerRule, e);
throw new RuntimeException("Json failed.", e);
}
return JacksonUtils.deserialize2Map(ruleJson);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

package com.tencent.cloud.polaris.circuitbreaker.endpoint;

import com.tencent.cloud.polaris.circuitbreaker.config.PolarisCircuitBreakerAutoConfiguration;
import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementAutoConfiguration;
import org.junit.jupiter.api.Test;

import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;

import static org.assertj.core.api.Assertions.assertThat;

/**
* Test for {@link PolarisCircuitBreakerEndpointAutoConfiguration}.
*
* @author wenxuan70
*/
public class PolarisCircuitBreakerEndpointAutoConfigurationTest {

private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(
PolarisContextAutoConfiguration.class,
RpcEnhancementAutoConfiguration.class,
PolarisCircuitBreakerAutoConfiguration.class,
PolarisCircuitBreakerEndpointAutoConfiguration.class
))
.withPropertyValues("management.endpoints.web.exposure.include=polaris-circuit-breaker");

@Test
public void testEndpointInitialization() {
contextRunner.run(context -> assertThat(context).hasSingleBean(PolarisCircuitBreakerEndpoint.class));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public class PolarisCircuitBreakerEndpointTest {
@BeforeEach
void setUp() {
serviceRuleManager = mock(ServiceRuleManager.class);
when(serviceRuleManager.getServiceCircuitBreakerRule(anyString(), anyString())).thenAnswer(invocation -> {
when(serviceRuleManager.getServiceCircuitBreakerRule(anyString(), anyString(), anyString())).thenAnswer(invocation -> {
CircuitBreakerProto.CircuitBreakerRule.Builder ruleBuilder = CircuitBreakerProto.CircuitBreakerRule.newBuilder();
ruleBuilder.setName("test_for_circuit_breaker");
ruleBuilder.setEnable(true);
Expand All @@ -66,15 +66,15 @@ void setUp() {
ModelProto.MatchString.newBuilder().setValue(StringValue.newBuilder().setValue("*").build()).build()).build());
rmBuilder.setSource(CircuitBreakerProto.RuleMatcher.SourceService.newBuilder().setNamespace("*").setService("*").build());
ruleBuilder.setRuleMatcher(rmBuilder.build());
return CircuitBreakerProto.CircuitBreaker.newBuilder().addRules(ruleBuilder.build()).build();
return CircuitBreakerProto.CircuitBreaker.newBuilder().addRules(ruleBuilder.build()).build().getRulesList();
});
}

@Test
public void testPolarisCircuitBreaker() {
contextRunner.run(context -> {
PolarisCircuitBreakerEndpoint endpoint = new PolarisCircuitBreakerEndpoint(serviceRuleManager);
Map<String, Object> circuitBreakerInfo = endpoint.circuitBreaker();
Map<String, Object> circuitBreakerInfo = endpoint.circuitBreaker("test");
assertThat(circuitBreakerInfo).isNotNull();
assertThat(circuitBreakerInfo.get("namespace")).isNotNull();
assertThat(circuitBreakerInfo.get("service")).isNotNull();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,9 @@ logging:
root: info
com.tencent.cloud: debug

management:
endpoints:
web:
exposure:
include:
- polaris-circuit-breaker
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,9 @@ logging:
com.tencent.polaris.plugins.registry: off
com.tencent.cloud: debug

management:
endpoints:
web:
exposure:
include:
- polaris-circuit-breaker
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,9 @@ logging:
root: info
com.tencent.cloud: debug

management:
endpoints:
web:
exposure:
include:
- polaris-circuit-breaker
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,9 @@ logging:
root: info
com.tencent.cloud: debug

management:
endpoints:
web:
exposure:
include:
- polaris-circuit-breaker
Original file line number Diff line number Diff line change
Expand Up @@ -89,18 +89,30 @@ public List<RoutingProto.Route> getServiceRouterRule(String namespace, String so
return rules;
}

public CircuitBreakerProto.CircuitBreaker getServiceCircuitBreakerRule(String namespace, String service) {
LOG.debug("Get service circuit breaker rules with namespace:{} and service:{}.", namespace, service);
public List<CircuitBreakerProto.CircuitBreakerRule> getServiceCircuitBreakerRule(String namespace, String sourceService, String dstService) {
LOG.debug("Get service circuit breaker rules with namespace:{} and sourceService:{} and dstService:{}.", namespace, sourceService, dstService);

ServiceRule serviceRule = getServiceRule(namespace, service, ServiceEventKey.EventType.CIRCUIT_BREAKING);
if (serviceRule != null) {
Object rule = serviceRule.getRule();
List<CircuitBreakerProto.CircuitBreakerRule> rules = new ArrayList<>();

// get source service circuit breaker rules.
ServiceRule sourceServiceRule = getServiceRule(namespace, sourceService, ServiceEventKey.EventType.CIRCUIT_BREAKING);
if (sourceServiceRule != null) {
Object rule = sourceServiceRule.getRule();
if (rule instanceof CircuitBreakerProto.CircuitBreaker) {
return (CircuitBreakerProto.CircuitBreaker) rule;
rules.addAll(((CircuitBreakerProto.CircuitBreaker) rule).getRulesList());
}
}

return null;
// get peer service circuit breaker rules.
ServiceRule dstServiceRule = getServiceRule(namespace, dstService, ServiceEventKey.EventType.CIRCUIT_BREAKING);
if (dstServiceRule != null) {
Object rule = dstServiceRule.getRule();
if (rule instanceof CircuitBreakerProto.CircuitBreaker) {
rules.addAll(((CircuitBreakerProto.CircuitBreaker) rule).getRulesList());
}
}

return rules;
}

private ServiceRule getServiceRule(String namespace, String service, ServiceEventKey.EventType eventType) {
Expand Down
Loading

0 comments on commit 1a8974c

Please sign in to comment.