diff --git a/polaris-common/polaris-config-default/src/main/resources/conf/default-config.yml b/polaris-common/polaris-config-default/src/main/resources/conf/default-config.yml index 38549d5ec..e74eb4d93 100644 --- a/polaris-common/polaris-config-default/src/main/resources/conf/default-config.yml +++ b/polaris-common/polaris-config-default/src/main/resources/conf/default-config.yml @@ -248,6 +248,16 @@ consumer: #描述:熔断策略,SDK会根据策略名称加载对应的熔断器插件(已注册的熔断器插件名) chain: - composite + # 描述:是否启用默认熔断规则 + defaultRuleEnable: true + # 描述:连续错误数熔断器默认连续错误数 + defaultErrorCount: 10 + # 描述:错误率熔断器默认错误率 + defaultErrorPercent: 50 + # 描述:错误率熔断器默认统计周期(单位:毫秒) + defaultInterval: 60000 + # 描述:错误率熔断器默认最小请求数 + defaultMinimumRequest: 10 #描述: 熔断插件配置 plugin: #描述:基于周期连续错误数熔断策略配置 diff --git a/polaris-common/polaris-config/src/main/java/com/tencent/polaris/api/config/consumer/CircuitBreakerConfig.java b/polaris-common/polaris-config/src/main/java/com/tencent/polaris/api/config/consumer/CircuitBreakerConfig.java index 4e5016822..d1ab890a8 100644 --- a/polaris-common/polaris-config/src/main/java/com/tencent/polaris/api/config/consumer/CircuitBreakerConfig.java +++ b/polaris-common/polaris-config/src/main/java/com/tencent/polaris/api/config/consumer/CircuitBreakerConfig.java @@ -19,6 +19,7 @@ import com.tencent.polaris.api.config.plugin.PluginConfig; import com.tencent.polaris.api.config.verify.Verifier; + import java.util.List; /** @@ -84,5 +85,39 @@ public interface CircuitBreakerConfig extends PluginConfig, Verifier { */ long getCountersExpireInterval(); + /** + * 是否启用默认规则 + * + * @return boolean + */ + boolean isDefaultRuleEnable(); + + /** + * 连续错误数熔断器默认连续错误数 + * + * @return 连续错误数 + */ + int getDefaultErrorCount(); + + /** + * 错误率熔断器默认错误率 + * + * @return 错误率 + */ + int getDefaultErrorPercent(); + + /** + * 错误率熔断器默认统计周期 + * + * @return 统计周期 + */ + int getDefaultInterval(); + + /** + * 错误率熔断器默认最小请求数 + * + * @return 最小请求数 + */ + int getDefaultMinimumRequest(); } diff --git a/polaris-common/polaris-config/src/main/java/com/tencent/polaris/factory/config/consumer/CircuitBreakerConfigImpl.java b/polaris-common/polaris-config/src/main/java/com/tencent/polaris/factory/config/consumer/CircuitBreakerConfigImpl.java index a61979e98..c3a4be2e4 100644 --- a/polaris-common/polaris-config/src/main/java/com/tencent/polaris/factory/config/consumer/CircuitBreakerConfigImpl.java +++ b/polaris-common/polaris-config/src/main/java/com/tencent/polaris/factory/config/consumer/CircuitBreakerConfigImpl.java @@ -24,6 +24,7 @@ import com.tencent.polaris.factory.config.plugin.PluginConfigImpl; import com.tencent.polaris.factory.util.ConfigUtils; import com.tencent.polaris.factory.util.TimeStrJsonDeserializer; + import java.util.List; /** @@ -61,6 +62,21 @@ public class CircuitBreakerConfigImpl extends PluginConfigImpl implements Circui @JsonDeserialize(using = TimeStrJsonDeserializer.class) private Long countersExpireInterval; + @JsonProperty + private Boolean defaultRuleEnable; + + @JsonProperty + private Integer defaultErrorCount; + + @JsonProperty + private Integer defaultErrorPercent; + + @JsonProperty + private Integer defaultInterval; + + @JsonProperty + private Integer defaultMinimumRequest; + @Override public boolean isEnable() { if (null == enable) { @@ -148,6 +164,54 @@ public void setEnableRemotePull(boolean enableRemotePull) { this.enableRemotePull = enableRemotePull; } + @Override + public boolean isDefaultRuleEnable() { + if (null == defaultRuleEnable) { + defaultRuleEnable = true; + } + return defaultRuleEnable; + } + + public void setDefaultRuleEnable(Boolean defaultRuleEnable) { + this.defaultRuleEnable = defaultRuleEnable; + } + + @Override + public int getDefaultErrorCount() { + return defaultErrorCount; + } + + public void setDefaultErrorCount(Integer defaultErrorCount) { + this.defaultErrorCount = defaultErrorCount; + } + + @Override + public int getDefaultErrorPercent() { + return defaultErrorPercent; + } + + public void setDefaultErrorPercent(Integer defaultErrorPercent) { + this.defaultErrorPercent = defaultErrorPercent; + } + + @Override + public int getDefaultInterval() { + return defaultInterval; + } + + public void setDefaultInterval(Integer defaultInterval) { + this.defaultInterval = defaultInterval; + } + + @Override + public int getDefaultMinimumRequest() { + return defaultMinimumRequest; + } + + public void setDefaultMinimumRequest(Integer defaultMinimumRequest) { + this.defaultMinimumRequest = defaultMinimumRequest; + } + @Override public void verify() { ConfigUtils.validateNull(enable, "circuitBreaker.enable"); @@ -163,6 +227,11 @@ public void verify() { ConfigUtils.validatePositive(requestCountAfterHalfOpen, "circuitBreaker.requestCountAfterHalfOpen"); ConfigUtils.validatePositive(successCountAfterHalfOpen, "circuitBreaker.successCountAfterHalfOpen"); ConfigUtils.validateNull(enableRemotePull, "circuitBreaker.enableRemotePull"); + ConfigUtils.validateNull(defaultRuleEnable, "circuitBreaker.defaultRuleEnable"); + ConfigUtils.validatePositive(defaultErrorCount, "circuitBreaker.defaultErrorCount"); + ConfigUtils.validatePositive(defaultErrorPercent, "circuitBreaker.defaultErrorPercent"); + ConfigUtils.validatePositive(defaultInterval, "circuitBreaker.defaultInterval"); + ConfigUtils.validatePositive(defaultMinimumRequest, "circuitBreaker.defaultMinimumRequest"); verifyPluginConfig(); } @@ -194,6 +263,21 @@ public void setDefault(Object defaultObject) { if (null == enableRemotePull) { setEnableRemotePull(circuitBreakerConfig.isEnableRemotePull()); } + if (null == defaultRuleEnable) { + setDefaultRuleEnable(circuitBreakerConfig.isDefaultRuleEnable()); + } + if (null == defaultErrorCount) { + setDefaultErrorCount(circuitBreakerConfig.getDefaultErrorCount()); + } + if (null == defaultErrorPercent) { + setDefaultErrorPercent(circuitBreakerConfig.getDefaultErrorPercent()); + } + if (null == defaultInterval) { + setDefaultInterval(circuitBreakerConfig.getDefaultInterval()); + } + if (null == defaultMinimumRequest) { + setDefaultMinimumRequest(circuitBreakerConfig.getDefaultMinimumRequest()); + } if (enable) { setDefaultPluginConfig(circuitBreakerConfig); } @@ -211,6 +295,11 @@ public String toString() { ", successCountAfterHalfOpen=" + successCountAfterHalfOpen + ", enableRemotePull=" + enableRemotePull + ", countersExpireInterval=" + countersExpireInterval + + ", defaultRuleEnable=" + defaultRuleEnable + + ", defaultErrorCount=" + defaultErrorCount + + ", defaultErrorPercent=" + defaultErrorPercent + + ", defaultInterval=" + defaultInterval + + ", defaultMinimumRequest=" + defaultMinimumRequest + '}'; } } diff --git a/polaris-plugins/polaris-plugins-circuitbreaker/circuitbreaker-composite/src/main/java/com/tencent/polaris/plugins/circuitbreaker/composite/PolarisCircuitBreaker.java b/polaris-plugins/polaris-plugins-circuitbreaker/circuitbreaker-composite/src/main/java/com/tencent/polaris/plugins/circuitbreaker/composite/PolarisCircuitBreaker.java index 8a5715fef..e8e4e3011 100644 --- a/polaris-plugins/polaris-plugins-circuitbreaker/circuitbreaker-composite/src/main/java/com/tencent/polaris/plugins/circuitbreaker/composite/PolarisCircuitBreaker.java +++ b/polaris-plugins/polaris-plugins-circuitbreaker/circuitbreaker-composite/src/main/java/com/tencent/polaris/plugins/circuitbreaker/composite/PolarisCircuitBreaker.java @@ -37,8 +37,8 @@ import com.tencent.polaris.api.plugin.compose.Extensions; import com.tencent.polaris.api.plugin.detect.HealthChecker; import com.tencent.polaris.api.pojo.*; -import com.tencent.polaris.api.utils.TrieUtil; import com.tencent.polaris.api.utils.CollectionUtils; +import com.tencent.polaris.api.utils.TrieUtil; import com.tencent.polaris.client.flow.DefaultServiceResourceProvider; import com.tencent.polaris.client.util.NamedThreadFactory; import com.tencent.polaris.logging.LoggerFactory; @@ -241,6 +241,8 @@ private Optional initResourceCounter(Resource resource) throws throw t; } + cbSvcRule = CircuitBreakerUtils.fillDefaultCircuitBreakerRuleInNeeded(resource, cbSvcRule, circuitBreakerConfig); + // pull fd rule ServiceEventKey fdEventKey = new ServiceEventKey(resource.getService(), ServiceEventKey.EventType.FAULT_DETECTING); diff --git a/polaris-plugins/polaris-plugins-circuitbreaker/circuitbreaker-composite/src/main/java/com/tencent/polaris/plugins/circuitbreaker/composite/utils/CircuitBreakerUtils.java b/polaris-plugins/polaris-plugins-circuitbreaker/circuitbreaker-composite/src/main/java/com/tencent/polaris/plugins/circuitbreaker/composite/utils/CircuitBreakerUtils.java index 552cafdd9..d0b0c1c20 100644 --- a/polaris-plugins/polaris-plugins-circuitbreaker/circuitbreaker-composite/src/main/java/com/tencent/polaris/plugins/circuitbreaker/composite/utils/CircuitBreakerUtils.java +++ b/polaris-plugins/polaris-plugins-circuitbreaker/circuitbreaker-composite/src/main/java/com/tencent/polaris/plugins/circuitbreaker/composite/utils/CircuitBreakerUtils.java @@ -17,23 +17,34 @@ package com.tencent.polaris.plugins.circuitbreaker.composite.utils; +import com.google.common.collect.Lists; +import com.google.protobuf.StringValue; import com.tencent.polaris.api.config.consumer.CircuitBreakerConfig; import com.tencent.polaris.api.plugin.circuitbreaker.ResourceStat; +import com.tencent.polaris.api.plugin.circuitbreaker.entity.Resource; import com.tencent.polaris.api.plugin.event.FlowEventConstants; import com.tencent.polaris.api.pojo.CircuitBreakerStatus; import com.tencent.polaris.api.pojo.RetStatus; +import com.tencent.polaris.api.pojo.ServiceRule; import com.tencent.polaris.api.utils.CollectionUtils; import com.tencent.polaris.api.utils.IPAddressUtils; import com.tencent.polaris.api.utils.RuleUtils; +import com.tencent.polaris.client.pojo.ServiceRuleByProto; +import com.tencent.polaris.logging.LoggerFactory; import com.tencent.polaris.specification.api.v1.fault.tolerance.CircuitBreakerProto; import com.tencent.polaris.specification.api.v1.model.ModelProto; +import org.slf4j.Logger; import java.util.List; import java.util.function.Function; import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.IntStream; public class CircuitBreakerUtils { + private static final Logger LOG = LoggerFactory.getLogger(CircuitBreakerUtils.class); + public static long DEFAULT_ERROR_RATE_INTERVAL_MS = 60 * 1000; public static long MIN_CLEANUP_INTERVAL = 60 * 1000; @@ -142,4 +153,94 @@ public static String getInstanceCircuitBreakerName(String host, int port) { public static String getServiceCircuitBreakerName(String targetNamespaceId, String serviceName) { return targetNamespaceId + "#" + serviceName; } + + public static ServiceRule fillDefaultCircuitBreakerRuleInNeeded(Resource resource, ServiceRule serviceRule, CircuitBreakerConfig circuitBreakerConfig) { + if (serviceRule instanceof ServiceRuleByProto && serviceRule.getRule() instanceof CircuitBreakerProto.CircuitBreaker) { + List rules = ((CircuitBreakerProto.CircuitBreaker) serviceRule.getRule()).getRulesList(); + if (shouldFilled(circuitBreakerConfig, rules)) { + CircuitBreakerProto.CircuitBreaker.Builder newCircuitBreakerBuilder = CircuitBreakerProto.CircuitBreaker.newBuilder().mergeFrom((CircuitBreakerProto.CircuitBreaker) serviceRule.getRule()); + CircuitBreakerProto.CircuitBreakerRule.Builder defaultCircuitBreakerRuleBuilder = CircuitBreakerProto.CircuitBreakerRule.newBuilder(); + // set name + defaultCircuitBreakerRuleBuilder.setName("default-polaris-instance-circuit-breaker"); + // set enable + defaultCircuitBreakerRuleBuilder.setEnable(true); + // set level + defaultCircuitBreakerRuleBuilder.setLevel(CircuitBreakerProto.Level.INSTANCE); + // build ruleMatcher + CircuitBreakerProto.RuleMatcher.Builder ruleMatcher = CircuitBreakerProto.RuleMatcher.newBuilder(); + CircuitBreakerProto.RuleMatcher.SourceService.Builder sourceServiceBuilder = CircuitBreakerProto.RuleMatcher.SourceService.newBuilder(); + sourceServiceBuilder.setNamespace(resource.getCallerService().getNamespace()); + sourceServiceBuilder.setService(resource.getCallerService().getService()); + ruleMatcher.setSource(sourceServiceBuilder); + CircuitBreakerProto.RuleMatcher.DestinationService.Builder destinationServiceBuilder = CircuitBreakerProto.RuleMatcher.DestinationService.newBuilder(); + destinationServiceBuilder.setNamespace(resource.getService().getNamespace()); + destinationServiceBuilder.setService(resource.getService().getService()); + ruleMatcher.setDestination(destinationServiceBuilder); + defaultCircuitBreakerRuleBuilder.setRuleMatcher(ruleMatcher); + // build blockConfigs + List blockConfigList = Lists.newArrayList(); + // build failure block config + CircuitBreakerProto.BlockConfig.Builder failureBlockConfigBuilder = CircuitBreakerProto.BlockConfig.newBuilder(); + failureBlockConfigBuilder.setName("failure-block-config"); + // build ret code error condition + CircuitBreakerProto.ErrorCondition.Builder errorConditionBuilder = CircuitBreakerProto.ErrorCondition.newBuilder(); + errorConditionBuilder.setInputType(CircuitBreakerProto.ErrorCondition.InputType.RET_CODE); + ModelProto.MatchString.Builder codeMatchStringBuilder = ModelProto.MatchString.newBuilder(); + codeMatchStringBuilder.setType(ModelProto.MatchString.MatchStringType.IN); + String statusCodes = IntStream.range(500, 600) + .mapToObj(String::valueOf) + .collect(Collectors.joining(",")); + codeMatchStringBuilder.setValue(StringValue.of(statusCodes)); + errorConditionBuilder.setCondition(codeMatchStringBuilder); + failureBlockConfigBuilder.addErrorConditions(errorConditionBuilder); + // build failure trigger conditions + // build error rate trigger condition + CircuitBreakerProto.TriggerCondition.Builder errorRateTriggerConditionBuilder = CircuitBreakerProto.TriggerCondition.newBuilder(); + errorRateTriggerConditionBuilder.setTriggerType(CircuitBreakerProto.TriggerCondition.TriggerType.ERROR_RATE); + errorRateTriggerConditionBuilder.setErrorPercent(circuitBreakerConfig.getDefaultErrorPercent()); + errorRateTriggerConditionBuilder.setInterval(circuitBreakerConfig.getDefaultInterval() / 1000); + errorRateTriggerConditionBuilder.setMinimumRequest(circuitBreakerConfig.getDefaultMinimumRequest()); + failureBlockConfigBuilder.addTriggerConditions(errorRateTriggerConditionBuilder); + // build consecutive error trigger condition + CircuitBreakerProto.TriggerCondition.Builder consecutiveErrorTriggerConditionBuilder = CircuitBreakerProto.TriggerCondition.newBuilder(); + consecutiveErrorTriggerConditionBuilder.setTriggerType(CircuitBreakerProto.TriggerCondition.TriggerType.CONSECUTIVE_ERROR); + consecutiveErrorTriggerConditionBuilder.setErrorCount(circuitBreakerConfig.getDefaultErrorCount()); + failureBlockConfigBuilder.addTriggerConditions(consecutiveErrorTriggerConditionBuilder); + blockConfigList.add(failureBlockConfigBuilder.build()); + defaultCircuitBreakerRuleBuilder.addAllBlockConfigs(blockConfigList); + // build recoverCondition + CircuitBreakerProto.RecoverCondition.Builder recoverConditionBuilder = CircuitBreakerProto.RecoverCondition.newBuilder(); + recoverConditionBuilder.setSleepWindow((int) circuitBreakerConfig.getSleepWindow() / 1000); + recoverConditionBuilder.setConsecutiveSuccess(circuitBreakerConfig.getSuccessCountAfterHalfOpen()); + defaultCircuitBreakerRuleBuilder.setRecoverCondition(recoverConditionBuilder); + newCircuitBreakerBuilder.addRules(defaultCircuitBreakerRuleBuilder); + CircuitBreakerProto.CircuitBreaker newCircuitBreaker = newCircuitBreakerBuilder.build(); + if (LOG.isDebugEnabled()) { + LOG.debug("Resource {} set default circuit breaker rule {}", resource, newCircuitBreaker); + } else { + LOG.info("Resource {} set default circuit breaker rule with DefaultErrorCount:{}, " + + "DefaultErrorPercent:{}, DefaultInterval:{}, DefaultMinimumRequest:{}", + resource, circuitBreakerConfig.getDefaultErrorCount(), circuitBreakerConfig.getDefaultErrorPercent(), + circuitBreakerConfig.getDefaultInterval(), circuitBreakerConfig.getDefaultMinimumRequest()); + } + return new ServiceRuleByProto(newCircuitBreaker, serviceRule.getRevision(), ((ServiceRuleByProto) serviceRule).isLoadedFromFile(), ((ServiceRuleByProto) serviceRule).getEventType()); + } + } + return serviceRule; + } + + private static boolean shouldFilled(CircuitBreakerConfig circuitBreakerConfig, List rules) { + if (!circuitBreakerConfig.isDefaultRuleEnable()) { + return false; + } + if (CollectionUtils.isEmpty(rules)) { + return true; + } + for (CircuitBreakerProto.CircuitBreakerRule rule : rules) { + if (rule.getEnable() && CircuitBreakerUtils.checkRule(rule)) { + return false; + } + } + return true; + } } diff --git a/polaris-plugins/polaris-plugins-circuitbreaker/circuitbreaker-composite/src/test/java/com/tencent/polaris/plugins/circuitbreaker/composite/utils/CircuitBreakerUtilsTest.java b/polaris-plugins/polaris-plugins-circuitbreaker/circuitbreaker-composite/src/test/java/com/tencent/polaris/plugins/circuitbreaker/composite/utils/CircuitBreakerUtilsTest.java index 3149784a0..b9d198fbe 100644 --- a/polaris-plugins/polaris-plugins-circuitbreaker/circuitbreaker-composite/src/test/java/com/tencent/polaris/plugins/circuitbreaker/composite/utils/CircuitBreakerUtilsTest.java +++ b/polaris-plugins/polaris-plugins-circuitbreaker/circuitbreaker-composite/src/test/java/com/tencent/polaris/plugins/circuitbreaker/composite/utils/CircuitBreakerUtilsTest.java @@ -18,11 +18,14 @@ package com.tencent.polaris.plugins.circuitbreaker.composite.utils; import com.google.protobuf.StringValue; +import com.tencent.polaris.api.config.consumer.CircuitBreakerConfig; import com.tencent.polaris.api.plugin.circuitbreaker.ResourceStat; import com.tencent.polaris.api.plugin.circuitbreaker.entity.InstanceResource; import com.tencent.polaris.api.plugin.circuitbreaker.entity.Resource; import com.tencent.polaris.api.pojo.RetStatus; import com.tencent.polaris.api.pojo.ServiceKey; +import com.tencent.polaris.api.pojo.ServiceRule; +import com.tencent.polaris.client.pojo.ServiceRuleByProto; import com.tencent.polaris.specification.api.v1.fault.tolerance.CircuitBreakerProto; import com.tencent.polaris.specification.api.v1.model.ModelProto; import org.junit.Assert; @@ -30,6 +33,10 @@ import java.util.regex.Pattern; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + /** * Test for {@link CircuitBreakerUtils}. * @@ -81,4 +88,71 @@ public void testParseStatus() { nextStatus = CircuitBreakerUtils.parseRetStatus(stat3, rule.getBlockConfigsList().get(0).getErrorConditionsList(), Pattern::compile); Assert.assertEquals(RetStatus.RetSuccess, nextStatus); } + + @Test + public void testFillDefaultCircuitBreakerRuleInNeeded() { + // 初始化测试依赖 + Resource resource = mock(Resource.class); + ServiceKey callerService = mock(ServiceKey.class); + ServiceKey targetService = mock(ServiceKey.class); + + when(resource.getCallerService()).thenReturn(callerService); + when(resource.getService()).thenReturn(targetService); + when(callerService.getNamespace()).thenReturn("testNamespace"); + when(callerService.getService()).thenReturn("testCallerService"); + when(targetService.getNamespace()).thenReturn("testNamespace"); + when(targetService.getService()).thenReturn("testTargetService"); + + CircuitBreakerConfig circuitBreakerConfig = mock(CircuitBreakerConfig.class); + + when(circuitBreakerConfig.getSleepWindow()).thenReturn(30000L); + when(circuitBreakerConfig.getSuccessCountAfterHalfOpen()).thenReturn(3); + when(circuitBreakerConfig.isDefaultRuleEnable()).thenReturn(true); + when(circuitBreakerConfig.getDefaultErrorCount()).thenReturn(10); + when(circuitBreakerConfig.getDefaultErrorPercent()).thenReturn(50); + when(circuitBreakerConfig.getDefaultInterval()).thenReturn(60000); + when(circuitBreakerConfig.getDefaultMinimumRequest()).thenReturn(10); + + // 准备空规则 + CircuitBreakerProto.CircuitBreaker emptyCircuitBreaker = CircuitBreakerProto.CircuitBreaker.newBuilder().build(); + ServiceRuleByProto originalRule = new ServiceRuleByProto(emptyCircuitBreaker, "revision", false, null); + + // 执行方法 + ServiceRule result = CircuitBreakerUtils.fillDefaultCircuitBreakerRuleInNeeded(resource, originalRule, circuitBreakerConfig); + + // 验证结果 + assertThat(result).isInstanceOf(ServiceRuleByProto.class); + CircuitBreakerProto.CircuitBreaker resultRule = (CircuitBreakerProto.CircuitBreaker) result.getRule(); + assertThat(resultRule.getRulesCount()).isEqualTo(1); + + CircuitBreakerProto.CircuitBreakerRule addedRule = resultRule.getRules(0); + // 验证规则基本信息 + assertThat(addedRule.getName()).isEqualTo("default-polaris-instance-circuit-breaker"); + assertThat(addedRule.getLevel()).isEqualTo(CircuitBreakerProto.Level.INSTANCE); + // 验证匹配规则 + assertThat(addedRule.getRuleMatcher().getSource().getNamespace()).isEqualTo("testNamespace"); + assertThat(addedRule.getRuleMatcher().getSource().getService()).isEqualTo("testCallerService"); + // 验证错误条件 + assertThat(addedRule.getBlockConfigs(0).getErrorConditions(0).getCondition().getValue().getValue()) + .isEqualTo("500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599"); + // 验证触发条件 + assertThat(addedRule.getBlockConfigs(0).getTriggerConditions(0).getTriggerType()).isEqualTo(CircuitBreakerProto.TriggerCondition.TriggerType.ERROR_RATE); + assertThat(addedRule.getBlockConfigs(0).getTriggerConditions(0).getErrorPercent()).isEqualTo(50); + assertThat(addedRule.getBlockConfigs(0).getTriggerConditions(0).getInterval()).isEqualTo(60); + assertThat(addedRule.getBlockConfigs(0).getTriggerConditions(0).getMinimumRequest()).isEqualTo(10); + assertThat(addedRule.getBlockConfigs(0).getTriggerConditions(1).getTriggerType()).isEqualTo(CircuitBreakerProto.TriggerCondition.TriggerType.CONSECUTIVE_ERROR); + assertThat(addedRule.getBlockConfigs(0).getTriggerConditions(1).getErrorCount()).isEqualTo(10); + // 验证恢复条件 + assertThat(addedRule.getRecoverCondition().getSleepWindow()).isEqualTo(30); + assertThat(addedRule.getRecoverCondition().getConsecutiveSuccess()).isEqualTo(3); + + // 改为不开启默认规则 + when(circuitBreakerConfig.isDefaultRuleEnable()).thenReturn(false); + // 执行方法 + ServiceRule emptyResult = CircuitBreakerUtils.fillDefaultCircuitBreakerRuleInNeeded(resource, originalRule, circuitBreakerConfig); + // 验证结果 + assertThat(emptyResult).isInstanceOf(ServiceRuleByProto.class); + CircuitBreakerProto.CircuitBreaker emptyResultRule = (CircuitBreakerProto.CircuitBreaker) emptyResult.getRule(); + assertThat(emptyResultRule.getRulesCount()).isEqualTo(0); + } } diff --git a/polaris-plugins/polaris-plugins-connector/connector-consul/src/main/java/com/tencent/polaris/plugins/connector/consul/service/circuitbreaker/CircuitBreakingService.java b/polaris-plugins/polaris-plugins-connector/connector-consul/src/main/java/com/tencent/polaris/plugins/connector/consul/service/circuitbreaker/CircuitBreakingService.java index 0fe098621..32aebf0af 100644 --- a/polaris-plugins/polaris-plugins-connector/connector-consul/src/main/java/com/tencent/polaris/plugins/connector/consul/service/circuitbreaker/CircuitBreakingService.java +++ b/polaris-plugins/polaris-plugins-connector/connector-consul/src/main/java/com/tencent/polaris/plugins/connector/consul/service/circuitbreaker/CircuitBreakingService.java @@ -208,6 +208,7 @@ private List parseResponse(String decode destinationServiceBuilder.setNamespace(namespace); destinationServiceBuilder.setService(service); ruleMatcher.setDestination(destinationServiceBuilder); + circuitBreakerRuleBuilder.setRuleMatcher(ruleMatcher); // build blockConfigs List blockConfigList = Lists.newArrayList();