From 3f272a79c306cb856b07da1c519148735837806a Mon Sep 17 00:00:00 2001 From: Eric Zhao Date: Fri, 22 Feb 2019 14:46:28 +0800 Subject: [PATCH 01/18] Add spring-cloud-circuitbreaker-sentinel module and update dependency Signed-off-by: Eric Zhao --- pom.xml | 1 + .../pom.xml | 6 +++ spring-cloud-circuitbreaker-sentinel/pom.xml | 45 +++++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 spring-cloud-circuitbreaker-sentinel/pom.xml diff --git a/pom.xml b/pom.xml index 173d2d5..36cb049 100644 --- a/pom.xml +++ b/pom.xml @@ -71,6 +71,7 @@ spring-cloud-circuitbreaker-commons spring-cloud-starter-circuitbreaker spring-cloud-circuitbreaker-hystrix + spring-cloud-circuitbreaker-sentinel diff --git a/spring-cloud-circuitbreaker-dependencies/pom.xml b/spring-cloud-circuitbreaker-dependencies/pom.xml index cad788a..7c9fa72 100644 --- a/spring-cloud-circuitbreaker-dependencies/pom.xml +++ b/spring-cloud-circuitbreaker-dependencies/pom.xml @@ -19,6 +19,7 @@ 0.13.1 + 1.4.2 @@ -38,6 +39,11 @@ resilience4j-reactor ${resilience4j.version} + + com.alibaba.csp + sentinel-core + ${sentinel.version} + org.springframework.cloud spring-cloud-circuitbreaker-resilience4j diff --git a/spring-cloud-circuitbreaker-sentinel/pom.xml b/spring-cloud-circuitbreaker-sentinel/pom.xml new file mode 100644 index 0000000..c8b93c7 --- /dev/null +++ b/spring-cloud-circuitbreaker-sentinel/pom.xml @@ -0,0 +1,45 @@ + + + + spring-cloud-circuitbreaker + org.springframework.cloud + 0.0.1.BUILD-SNAPSHOT + + 4.0.0 + + spring-cloud-circuitbreaker-sentinel + + + + org.springframework.cloud + spring-cloud-circuitbreaker-commons + + + com.alibaba.csp + sentinel-core + + + org.springframework.boot + spring-boot-starter-web + true + + + io.projectreactor + reactor-core + true + + + + org.springframework.boot + spring-boot-starter-webflux + test + + + org.springframework.boot + spring-boot-starter-test + test + + + \ No newline at end of file From 6bcc8636465057c78b8372ce48a16dcff5a7a0c8 Mon Sep 17 00:00:00 2001 From: Eric Zhao Date: Fri, 22 Feb 2019 14:47:01 +0800 Subject: [PATCH 02/18] Add non-reactive circuit breaker implementation of spring-cloud-circuitbreaker-sentinel Signed-off-by: Eric Zhao --- .../sentinel/SentinelCircuitBreaker.java | 90 ++++++++++++ ...ntinelCircuitBreakerAutoConfiguration.java | 59 ++++++++ .../SentinelCircuitBreakerFactory.java | 54 +++++++ .../sentinel/SentinelConfigBuilder.java | 103 +++++++++++++ .../main/resources/META-INF/spring.factories | 2 + ...SentinelCircuitBreakerIntegrationTest.java | 138 ++++++++++++++++++ .../sentinel/SentinelCircuitBreakerTest.java | 41 ++++++ 7 files changed, 487 insertions(+) create mode 100644 spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreaker.java create mode 100644 spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerAutoConfiguration.java create mode 100644 spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerFactory.java create mode 100644 spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelConfigBuilder.java create mode 100644 spring-cloud-circuitbreaker-sentinel/src/main/resources/META-INF/spring.factories create mode 100644 spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerIntegrationTest.java create mode 100644 spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerTest.java diff --git a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreaker.java b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreaker.java new file mode 100644 index 0000000..1127c5e --- /dev/null +++ b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreaker.java @@ -0,0 +1,90 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.circuitbreaker.sentinel; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.Function; +import java.util.function.Supplier; + +import com.alibaba.csp.sentinel.Entry; +import com.alibaba.csp.sentinel.EntryType; +import com.alibaba.csp.sentinel.SphU; +import com.alibaba.csp.sentinel.Tracer; +import com.alibaba.csp.sentinel.slots.block.BlockException; +import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; +import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; + +import org.springframework.cloud.circuitbreaker.commons.CircuitBreaker; +import org.springframework.util.Assert; + +/** + * Sentinel implementation of {@link CircuitBreaker}. + * + * @author Eric Zhao + */ +public class SentinelCircuitBreaker implements CircuitBreaker { + + private final String resourceName; + private final EntryType entryType; + + private final List rules; + + public SentinelCircuitBreaker(String resourceName, EntryType entryType, List rules) { + Assert.hasText(resourceName, "resourceName cannot be blank"); + Assert.notNull(rules, "rules should not be null"); + this.resourceName = resourceName; + this.entryType = entryType; + this.rules = Collections.unmodifiableList(rules); + + applyToSentinelRuleManager(); + } + + public SentinelCircuitBreaker(String resourceName, List rules) { + this(resourceName, EntryType.OUT, rules); + } + + public SentinelCircuitBreaker(String resourceName) { + this(resourceName, EntryType.OUT, Collections.emptyList()); + } + + private void applyToSentinelRuleManager() { + Set ruleSet = new HashSet<>(DegradeRuleManager.getRules()); + ruleSet.addAll(this.rules); + DegradeRuleManager.loadRules(new ArrayList<>(ruleSet)); + } + + @Override + public T run(Supplier toRun, Function fallback) { + Entry entry = null; + try { + entry = SphU.entry(resourceName, entryType); + return toRun.get(); + } catch (BlockException ex) { + return fallback.apply(ex); + } catch (Exception ex) { + Tracer.trace(ex); + return fallback.apply(ex); + } finally { + if (entry != null) { + entry.exit(); + } + } + } +} diff --git a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerAutoConfiguration.java b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerAutoConfiguration.java new file mode 100644 index 0000000..638e436 --- /dev/null +++ b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerAutoConfiguration.java @@ -0,0 +1,59 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.circuitbreaker.sentinel; + +import java.util.ArrayList; +import java.util.List; + +import javax.annotation.PostConstruct; + +import com.alibaba.csp.sentinel.SphU; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.cloud.circuitbreaker.commons.CircuitBreakerFactory; +import org.springframework.cloud.circuitbreaker.commons.Customizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author Eric Zhao + */ +@Configuration +@ConditionalOnClass({ SphU.class }) +public class SentinelCircuitBreakerAutoConfiguration { + + @Bean + @ConditionalOnMissingBean(CircuitBreakerFactory.class) + public CircuitBreakerFactory sentinelCircuitBreakerFactory() { + return new SentinelCircuitBreakerFactory(); + } + + @Configuration + public static class SentinelCustomizerConfiguration { + @Autowired(required = false) + public List> customizers = new ArrayList<>(); + + @Autowired(required = false) + public SentinelCircuitBreakerFactory factory; + + @PostConstruct + public void init() { + customizers.forEach(customizer -> customizer.customize(factory)); + } + } +} \ No newline at end of file diff --git a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerFactory.java b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerFactory.java new file mode 100644 index 0000000..f5186b5 --- /dev/null +++ b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerFactory.java @@ -0,0 +1,54 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.circuitbreaker.sentinel; + +import java.util.ArrayList; +import java.util.function.Function; + +import org.springframework.cloud.circuitbreaker.commons.CircuitBreaker; +import org.springframework.cloud.circuitbreaker.commons.CircuitBreakerFactory; +import org.springframework.cloud.circuitbreaker.sentinel.SentinelConfigBuilder.SentinelCircuitBreakerConfiguration; +import org.springframework.util.Assert; + +/** + * @author Eric Zhao + */ +public class SentinelCircuitBreakerFactory extends CircuitBreakerFactory { + + private Function defaultConfiguration = id -> + new SentinelConfigBuilder() + .resourceName(id) + .rules(new ArrayList<>()) + .build(); + + @Override + public CircuitBreaker create(String id) { + Assert.hasText(id, "A CircuitBreaker must have an id."); + SentinelConfigBuilder.SentinelCircuitBreakerConfiguration conf = getConfigurations() + .computeIfAbsent(id, defaultConfiguration); + return new SentinelCircuitBreaker(id, conf.getEntryType(), conf.getRules()); + } + + @Override + protected SentinelConfigBuilder configBuilder(String id) { + return new SentinelConfigBuilder(id); + } + + @Override + public void configureDefault(Function defaultConfiguration) { + this.defaultConfiguration = defaultConfiguration; + } +} diff --git a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelConfigBuilder.java b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelConfigBuilder.java new file mode 100644 index 0000000..6996e9b --- /dev/null +++ b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelConfigBuilder.java @@ -0,0 +1,103 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.circuitbreaker.sentinel; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import com.alibaba.csp.sentinel.EntryType; +import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; + +import org.springframework.cloud.circuitbreaker.commons.ConfigBuilder; +import org.springframework.util.Assert; + +/** + * @author Eric Zhao + */ +public class SentinelConfigBuilder implements ConfigBuilder { + + private String resourceName; + private EntryType entryType; + private List rules; + + public SentinelConfigBuilder() {} + + public SentinelConfigBuilder(String resourceName) { + this.resourceName = resourceName; + } + + public SentinelConfigBuilder resourceName(String resourceName) { + this.resourceName = resourceName; + return this; + } + + public SentinelConfigBuilder entryType(EntryType entryType) { + this.entryType = entryType; + return this; + } + + public SentinelConfigBuilder rules(List rules) { + this.rules = rules; + return this; + } + + @Override + public SentinelCircuitBreakerConfiguration build() { + Assert.hasText(resourceName, "resourceName cannot be empty"); + List rules = Optional.ofNullable(this.rules).orElse(new ArrayList<>()); + + EntryType entryType = Optional.ofNullable(this.entryType).orElse(EntryType.OUT); + return new SentinelCircuitBreakerConfiguration() + .setResourceName(this.resourceName) + .setEntryType(entryType) + .setRules(rules); + } + + public static class SentinelCircuitBreakerConfiguration { + private String resourceName; + private EntryType entryType; + + private List rules; + + public String getResourceName() { + return resourceName; + } + + public SentinelCircuitBreakerConfiguration setResourceName(String resourceName) { + this.resourceName = resourceName; + return this; + } + + public EntryType getEntryType() { + return entryType; + } + + public SentinelCircuitBreakerConfiguration setEntryType(EntryType entryType) { + this.entryType = entryType; + return this; + } + + public List getRules() { + return rules; + } + + public SentinelCircuitBreakerConfiguration setRules(List rules) { + this.rules = rules; + return this; + } + } +} diff --git a/spring-cloud-circuitbreaker-sentinel/src/main/resources/META-INF/spring.factories b/spring-cloud-circuitbreaker-sentinel/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..490c87e --- /dev/null +++ b/spring-cloud-circuitbreaker-sentinel/src/main/resources/META-INF/spring.factories @@ -0,0 +1,2 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ +org.springframework.cloud.circuitbreaker.sentinel.SentinelCircuitBreakerAutoConfiguration diff --git a/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerIntegrationTest.java b/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerIntegrationTest.java new file mode 100644 index 0000000..a383238 --- /dev/null +++ b/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerIntegrationTest.java @@ -0,0 +1,138 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.circuitbreaker.sentinel; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import com.alibaba.csp.sentinel.slots.block.RuleConstant; +import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; +import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.cloud.circuitbreaker.commons.CircuitBreakerFactory; +import org.springframework.cloud.circuitbreaker.commons.Customizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.stereotype.Service; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import static org.junit.Assert.assertEquals; +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; + +/** + * @author Eric Zhao + */ +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = RANDOM_PORT, classes = SentinelCircuitBreakerIntegrationTest.Application.class) +@DirtiesContext +public class SentinelCircuitBreakerIntegrationTest { + + @Configuration + @EnableAutoConfiguration + @RestController + protected static class Application { + @GetMapping("/slow") + public String slow() throws InterruptedException { + Thread.sleep(500); + return "slow"; + } + + @GetMapping("/normal") + public String normal() { + return "normal"; + } + + @Bean + public Customizer slowCustomizer() { + String slowId = "slow"; + List rules = Collections.singletonList( + new DegradeRule(slowId).setGrade(RuleConstant.DEGRADE_GRADE_RT) + .setCount(100) + .setTimeWindow(10) + ); + return factory -> factory.configure(slowId, builder -> builder.rules(rules)); + } + + @Service + public static class DemoControllerService { + private TestRestTemplate rest; + private CircuitBreakerFactory cbFactory; + + public DemoControllerService(TestRestTemplate rest, CircuitBreakerFactory cbFactory) { + this.rest = rest; + this.cbFactory = cbFactory; + } + + public String slow() { + return cbFactory.create("slow").run(() -> rest.getForObject("/slow", String.class), t -> "fallback"); + } + + public String normal() { + return cbFactory.create("normal").run(() -> rest.getForObject("/normal", String.class), + t -> "fallback"); + } + } + } + + @Autowired + Application.DemoControllerService service; + + @Test + public void testSlow() throws Exception { + // The first 5 requests should pass. + assertEquals("slow", service.slow()); + assertEquals("slow", service.slow()); + assertEquals("slow", service.slow()); + assertEquals("slow", service.slow()); + assertEquals("slow", service.slow()); + + // Then in the next 10s, the fallback method should be called. + for (int i = 0; i < 10; i++) { + assertEquals("fallback", service.slow()); + Thread.sleep(1000); + } + + // Recovered. + assertEquals("slow", service.slow()); + } + + @Test + public void testNormal() { + assertEquals("normal", service.normal()); + } + + + @Before + public void setUp() { + DegradeRuleManager.loadRules(new ArrayList<>()); + } + + @Before + public void tearDown() { + DegradeRuleManager.loadRules(new ArrayList<>()); + } +} diff --git a/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerTest.java b/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerTest.java new file mode 100644 index 0000000..d9b713b --- /dev/null +++ b/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerTest.java @@ -0,0 +1,41 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.circuitbreaker.sentinel; + +import org.junit.Test; +import org.springframework.cloud.circuitbreaker.commons.CircuitBreaker; + +import static org.junit.Assert.*; + +/** + * @author Eric Zhao + */ +public class SentinelCircuitBreakerTest { + + @Test + public void testRun() { + CircuitBreaker cb = new SentinelCircuitBreakerFactory().create("testSentinelRun"); + assertEquals("foobar", cb.run(() -> "foobar")); + } + + @Test + public void testRunWithFallback() { + CircuitBreaker cb = new SentinelCircuitBreakerFactory().create("testSentinelRunWithFallback"); + assertEquals("fallback", cb.run(() -> { + throw new RuntimeException("boom"); + }, t -> "fallback")); + } +} From 548932f24ab5d831e726f6d0306fa53fc093a5ae Mon Sep 17 00:00:00 2001 From: Eric Zhao Date: Fri, 8 Mar 2019 17:08:59 +0800 Subject: [PATCH 03/18] Add starter module for spring-cloud-circuitbreaker-sentinel Signed-off-by: Eric Zhao --- .../pom.xml | 10 ++++++++ spring-cloud-starter-circuitbreaker/pom.xml | 1 + .../pom.xml | 24 +++++++++++++++++++ .../main/resources/META-INF/spring.provides | 1 + 4 files changed, 36 insertions(+) create mode 100644 spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-sentinel/pom.xml create mode 100644 spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-sentinel/src/main/resources/META-INF/spring.provides diff --git a/spring-cloud-circuitbreaker-dependencies/pom.xml b/spring-cloud-circuitbreaker-dependencies/pom.xml index 7c9fa72..5d8c682 100644 --- a/spring-cloud-circuitbreaker-dependencies/pom.xml +++ b/spring-cloud-circuitbreaker-dependencies/pom.xml @@ -54,6 +54,11 @@ spring-cloud-circuitbreaker-hystrix ${project.version} + + org.springframework.cloud + spring-cloud-circuitbreaker-sentinel + ${project.version} + org.springframework.cloud spring-cloud-circuitbreaker-commons @@ -69,6 +74,11 @@ spring-cloud-starter-circuitbreaker-hystrix ${project.version} + + org.springframework.cloud + spring-cloud-starter-circuitbreaker-sentinel + ${project.version} + diff --git a/spring-cloud-starter-circuitbreaker/pom.xml b/spring-cloud-starter-circuitbreaker/pom.xml index 1a7d7e5..9708ce5 100644 --- a/spring-cloud-starter-circuitbreaker/pom.xml +++ b/spring-cloud-starter-circuitbreaker/pom.xml @@ -15,6 +15,7 @@ spring-cloud-starter-circuitbreaker-resilience4j spring-cloud-starter-circuitbreaker-hystrix + spring-cloud-starter-circuitbreaker-sentinel pom diff --git a/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-sentinel/pom.xml b/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-sentinel/pom.xml new file mode 100644 index 0000000..1af9d7a --- /dev/null +++ b/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-sentinel/pom.xml @@ -0,0 +1,24 @@ + + + + spring-cloud-starter-circuitbreaker + org.springframework.cloud + 0.0.1.BUILD-SNAPSHOT + + 4.0.0 + + spring-cloud-starter-circuitbreaker-sentinel + + + + org.springframework.cloud + spring-cloud-starter + + + org.springframework.cloud + spring-cloud-circuitbreaker-sentinel + + + \ No newline at end of file diff --git a/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-sentinel/src/main/resources/META-INF/spring.provides b/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-sentinel/src/main/resources/META-INF/spring.provides new file mode 100644 index 0000000..d9eda04 --- /dev/null +++ b/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-sentinel/src/main/resources/META-INF/spring.provides @@ -0,0 +1 @@ +provides: spring-cloud-circuitbreaker-sentinel \ No newline at end of file From dc3fa4e436676d64c6a60b342fee7ad1fd5fc90a Mon Sep 17 00:00:00 2001 From: Eric Zhao Date: Tue, 12 Mar 2019 11:25:33 +0800 Subject: [PATCH 04/18] Code reformat Signed-off-by: Eric Zhao --- .../sentinel/SentinelCircuitBreaker.java | 81 +++++++------ ...ntinelCircuitBreakerAutoConfiguration.java | 34 +++--- .../SentinelCircuitBreakerFactory.java | 40 +++---- .../sentinel/SentinelConfigBuilder.java | 111 +++++++++--------- 4 files changed, 135 insertions(+), 131 deletions(-) diff --git a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreaker.java b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreaker.java index 1127c5e..35f9052 100644 --- a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreaker.java +++ b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreaker.java @@ -41,50 +41,53 @@ import org.springframework.util.Assert; */ public class SentinelCircuitBreaker implements CircuitBreaker { - private final String resourceName; - private final EntryType entryType; + private final String resourceName; + private final EntryType entryType; - private final List rules; + private final List rules; - public SentinelCircuitBreaker(String resourceName, EntryType entryType, List rules) { - Assert.hasText(resourceName, "resourceName cannot be blank"); - Assert.notNull(rules, "rules should not be null"); - this.resourceName = resourceName; - this.entryType = entryType; - this.rules = Collections.unmodifiableList(rules); + public SentinelCircuitBreaker(String resourceName, EntryType entryType, List rules) { + Assert.hasText(resourceName, "resourceName cannot be blank"); + Assert.notNull(rules, "rules should not be null"); + this.resourceName = resourceName; + this.entryType = entryType; + this.rules = Collections.unmodifiableList(rules); - applyToSentinelRuleManager(); - } + applyToSentinelRuleManager(); + } - public SentinelCircuitBreaker(String resourceName, List rules) { - this(resourceName, EntryType.OUT, rules); - } + public SentinelCircuitBreaker(String resourceName, List rules) { + this(resourceName, EntryType.OUT, rules); + } - public SentinelCircuitBreaker(String resourceName) { - this(resourceName, EntryType.OUT, Collections.emptyList()); - } + public SentinelCircuitBreaker(String resourceName) { + this(resourceName, EntryType.OUT, Collections.emptyList()); + } - private void applyToSentinelRuleManager() { - Set ruleSet = new HashSet<>(DegradeRuleManager.getRules()); - ruleSet.addAll(this.rules); - DegradeRuleManager.loadRules(new ArrayList<>(ruleSet)); - } + private void applyToSentinelRuleManager() { + Set ruleSet = new HashSet<>(DegradeRuleManager.getRules()); + ruleSet.addAll(this.rules); + DegradeRuleManager.loadRules(new ArrayList<>(ruleSet)); + } - @Override - public T run(Supplier toRun, Function fallback) { - Entry entry = null; - try { - entry = SphU.entry(resourceName, entryType); - return toRun.get(); - } catch (BlockException ex) { - return fallback.apply(ex); - } catch (Exception ex) { - Tracer.trace(ex); - return fallback.apply(ex); - } finally { - if (entry != null) { - entry.exit(); - } - } - } + @Override + public T run(Supplier toRun, Function fallback) { + Entry entry = null; + try { + entry = SphU.entry(resourceName, entryType); + return toRun.get(); + } + catch (BlockException ex) { + return fallback.apply(ex); + } + catch (Exception ex) { + Tracer.trace(ex); + return fallback.apply(ex); + } + finally { + if (entry != null) { + entry.exit(); + } + } + } } diff --git a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerAutoConfiguration.java b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerAutoConfiguration.java index 638e436..d6efab7 100644 --- a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerAutoConfiguration.java +++ b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerAutoConfiguration.java @@ -34,26 +34,26 @@ import org.springframework.context.annotation.Configuration; * @author Eric Zhao */ @Configuration -@ConditionalOnClass({ SphU.class }) +@ConditionalOnClass({SphU.class}) public class SentinelCircuitBreakerAutoConfiguration { - @Bean - @ConditionalOnMissingBean(CircuitBreakerFactory.class) - public CircuitBreakerFactory sentinelCircuitBreakerFactory() { - return new SentinelCircuitBreakerFactory(); - } + @Bean + @ConditionalOnMissingBean(CircuitBreakerFactory.class) + public CircuitBreakerFactory sentinelCircuitBreakerFactory() { + return new SentinelCircuitBreakerFactory(); + } - @Configuration - public static class SentinelCustomizerConfiguration { - @Autowired(required = false) - public List> customizers = new ArrayList<>(); + @Configuration + public static class SentinelCustomizerConfiguration { + @Autowired(required = false) + public List> customizers = new ArrayList<>(); - @Autowired(required = false) - public SentinelCircuitBreakerFactory factory; + @Autowired(required = false) + public SentinelCircuitBreakerFactory factory; - @PostConstruct - public void init() { - customizers.forEach(customizer -> customizer.customize(factory)); - } - } + @PostConstruct + public void init() { + customizers.forEach(customizer -> customizer.customize(factory)); + } + } } \ No newline at end of file diff --git a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerFactory.java b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerFactory.java index f5186b5..0d40ef5 100644 --- a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerFactory.java +++ b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerFactory.java @@ -28,27 +28,27 @@ import org.springframework.util.Assert; */ public class SentinelCircuitBreakerFactory extends CircuitBreakerFactory { - private Function defaultConfiguration = id -> - new SentinelConfigBuilder() - .resourceName(id) - .rules(new ArrayList<>()) - .build(); + private Function defaultConfiguration = id -> + new SentinelConfigBuilder() + .resourceName(id) + .rules(new ArrayList<>()) + .build(); - @Override - public CircuitBreaker create(String id) { - Assert.hasText(id, "A CircuitBreaker must have an id."); - SentinelConfigBuilder.SentinelCircuitBreakerConfiguration conf = getConfigurations() - .computeIfAbsent(id, defaultConfiguration); - return new SentinelCircuitBreaker(id, conf.getEntryType(), conf.getRules()); - } + @Override + public CircuitBreaker create(String id) { + Assert.hasText(id, "A CircuitBreaker must have an id."); + SentinelConfigBuilder.SentinelCircuitBreakerConfiguration conf = getConfigurations() + .computeIfAbsent(id, defaultConfiguration); + return new SentinelCircuitBreaker(id, conf.getEntryType(), conf.getRules()); + } - @Override - protected SentinelConfigBuilder configBuilder(String id) { - return new SentinelConfigBuilder(id); - } + @Override + protected SentinelConfigBuilder configBuilder(String id) { + return new SentinelConfigBuilder(id); + } - @Override - public void configureDefault(Function defaultConfiguration) { - this.defaultConfiguration = defaultConfiguration; - } + @Override + public void configureDefault(Function defaultConfiguration) { + this.defaultConfiguration = defaultConfiguration; + } } diff --git a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelConfigBuilder.java b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelConfigBuilder.java index 6996e9b..91bc227 100644 --- a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelConfigBuilder.java +++ b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelConfigBuilder.java @@ -30,74 +30,75 @@ import org.springframework.util.Assert; */ public class SentinelConfigBuilder implements ConfigBuilder { - private String resourceName; - private EntryType entryType; - private List rules; + private String resourceName; + private EntryType entryType; + private List rules; - public SentinelConfigBuilder() {} + public SentinelConfigBuilder() { + } - public SentinelConfigBuilder(String resourceName) { - this.resourceName = resourceName; - } + public SentinelConfigBuilder(String resourceName) { + this.resourceName = resourceName; + } - public SentinelConfigBuilder resourceName(String resourceName) { - this.resourceName = resourceName; - return this; - } + public SentinelConfigBuilder resourceName(String resourceName) { + this.resourceName = resourceName; + return this; + } - public SentinelConfigBuilder entryType(EntryType entryType) { - this.entryType = entryType; - return this; - } + public SentinelConfigBuilder entryType(EntryType entryType) { + this.entryType = entryType; + return this; + } - public SentinelConfigBuilder rules(List rules) { - this.rules = rules; - return this; - } + public SentinelConfigBuilder rules(List rules) { + this.rules = rules; + return this; + } - @Override - public SentinelCircuitBreakerConfiguration build() { - Assert.hasText(resourceName, "resourceName cannot be empty"); - List rules = Optional.ofNullable(this.rules).orElse(new ArrayList<>()); + @Override + public SentinelCircuitBreakerConfiguration build() { + Assert.hasText(resourceName, "resourceName cannot be empty"); + List rules = Optional.ofNullable(this.rules).orElse(new ArrayList<>()); - EntryType entryType = Optional.ofNullable(this.entryType).orElse(EntryType.OUT); - return new SentinelCircuitBreakerConfiguration() - .setResourceName(this.resourceName) - .setEntryType(entryType) - .setRules(rules); - } + EntryType entryType = Optional.ofNullable(this.entryType).orElse(EntryType.OUT); + return new SentinelCircuitBreakerConfiguration() + .setResourceName(this.resourceName) + .setEntryType(entryType) + .setRules(rules); + } - public static class SentinelCircuitBreakerConfiguration { - private String resourceName; - private EntryType entryType; + public static class SentinelCircuitBreakerConfiguration { + private String resourceName; + private EntryType entryType; - private List rules; + private List rules; - public String getResourceName() { - return resourceName; - } + public String getResourceName() { + return resourceName; + } - public SentinelCircuitBreakerConfiguration setResourceName(String resourceName) { - this.resourceName = resourceName; - return this; - } + public SentinelCircuitBreakerConfiguration setResourceName(String resourceName) { + this.resourceName = resourceName; + return this; + } - public EntryType getEntryType() { - return entryType; - } + public EntryType getEntryType() { + return entryType; + } - public SentinelCircuitBreakerConfiguration setEntryType(EntryType entryType) { - this.entryType = entryType; - return this; - } + public SentinelCircuitBreakerConfiguration setEntryType(EntryType entryType) { + this.entryType = entryType; + return this; + } - public List getRules() { - return rules; - } + public List getRules() { + return rules; + } - public SentinelCircuitBreakerConfiguration setRules(List rules) { - this.rules = rules; - return this; - } - } + public SentinelCircuitBreakerConfiguration setRules(List rules) { + this.rules = rules; + return this; + } + } } From 04f5a2b170b1ff293214ab21b46c41947151b52d Mon Sep 17 00:00:00 2001 From: Eric Zhao Date: Wed, 13 Mar 2019 22:52:58 +0800 Subject: [PATCH 05/18] Update comment for SentinelCircuitBreaker Signed-off-by: Eric Zhao --- .../circuitbreaker/sentinel/SentinelCircuitBreaker.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreaker.java b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreaker.java index 35f9052..2dd21a6 100644 --- a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreaker.java +++ b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreaker.java @@ -65,6 +65,9 @@ public class SentinelCircuitBreaker implements CircuitBreaker { } private void applyToSentinelRuleManager() { + if (this.rules == null || this.rules.isEmpty()) { + return; + } Set ruleSet = new HashSet<>(DegradeRuleManager.getRules()); ruleSet.addAll(this.rules); DegradeRuleManager.loadRules(new ArrayList<>(ruleSet)); @@ -75,16 +78,22 @@ public class SentinelCircuitBreaker implements CircuitBreaker { Entry entry = null; try { entry = SphU.entry(resourceName, entryType); + // If the SphU.entry() does not throw `BlockException`, it means that the request can pass. return toRun.get(); } catch (BlockException ex) { + // SphU.entry() may throw BlockException which indicates that + // the request was rejected (flow control or circuit breaking triggered). + // So it should not be counted as the business exception. return fallback.apply(ex); } catch (Exception ex) { + // For other kinds of exceptions, we'll trace the exception count via Tracer.trace(ex). Tracer.trace(ex); return fallback.apply(ex); } finally { + // Guarantee the invocation has been completed. if (entry != null) { entry.exit(); } From 158996fda653a9383bf144be03d5e368b0dd5238 Mon Sep 17 00:00:00 2001 From: Eric Zhao Date: Thu, 14 Mar 2019 11:13:00 +0800 Subject: [PATCH 06/18] Fix for test Signed-off-by: Eric Zhao --- .../sentinel/SentinelCircuitBreakerIntegrationTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerIntegrationTest.java b/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerIntegrationTest.java index a383238..6a5c416 100644 --- a/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerIntegrationTest.java +++ b/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerIntegrationTest.java @@ -74,7 +74,7 @@ public class SentinelCircuitBreakerIntegrationTest { .setCount(100) .setTimeWindow(10) ); - return factory -> factory.configure(slowId, builder -> builder.rules(rules)); + return factory -> factory.configure(builder -> builder.rules(rules), slowId); } @Service From 0ea7e80f3ff8be7e80f860d449a36c7b9fd9489a Mon Sep 17 00:00:00 2001 From: Eric Zhao Date: Thu, 14 Mar 2019 22:27:28 +0800 Subject: [PATCH 07/18] Update document for Sentinel Signed-off-by: Eric Zhao --- .../spring-cloud-circuitbreaker-sentinel.adoc | 44 +++++++++++++++++++ .../asciidoc/spring-cloud-circuitbreaker.adoc | 4 ++ 2 files changed, 48 insertions(+) create mode 100644 docs/src/main/asciidoc/spring-cloud-circuitbreaker-sentinel.adoc diff --git a/docs/src/main/asciidoc/spring-cloud-circuitbreaker-sentinel.adoc b/docs/src/main/asciidoc/spring-cloud-circuitbreaker-sentinel.adoc new file mode 100644 index 0000000..413f217 --- /dev/null +++ b/docs/src/main/asciidoc/spring-cloud-circuitbreaker-sentinel.adoc @@ -0,0 +1,44 @@ +=== Configuring Sentinel Circuit Breakers + +==== Default Configuration + +To provide a default configuration for all of your circuit breakers create a `Customizer` bean that is passed a +`SentinelCircuitBreakerFactory`. +The `configureDefault` method can be used to provide a default configuration. + +==== +[source,java] +---- +@Bean +public Customizer defaultCustomizer() { + return factory -> factory.configureDefault(id -> new SentinelConfigBuilder(id) + .build()); +} +---- +==== + +You can choose to provide default circuit breaking rules via `SentinelConfigBuilder#rules(rules)`. +You can also choose to load circuit breaking rules later elsewhere using +`DegradeRuleManager.loadRules(rules)` API of Sentinel. + + +==== Specific Circuit Breaker Configuration + +Similarly to providing a default configuration, you can create a `Customizer` bean this is passed a +`SentinelCircuitBreakerFactory`. + +==== +[source,java] +---- +@Bean +public Customizer slowCustomizer() { + String slowId = "slow"; + List rules = Collections.singletonList( + new DegradeRule(slowId).setGrade(RuleConstant.DEGRADE_GRADE_RT) + .setCount(100) + .setTimeWindow(10) + ); + return factory -> factory.configure(builder -> builder.rules(rules), slowId); +} +---- +==== \ No newline at end of file diff --git a/docs/src/main/asciidoc/spring-cloud-circuitbreaker.adoc b/docs/src/main/asciidoc/spring-cloud-circuitbreaker.adoc index a1abd0f..f05a062 100755 --- a/docs/src/main/asciidoc/spring-cloud-circuitbreaker.adoc +++ b/docs/src/main/asciidoc/spring-cloud-circuitbreaker.adoc @@ -20,6 +20,7 @@ breaker implementation that best fits your needs for your app. * https://github.com/Netflix/Hystrix[Netfix Hystrix] * https://github.com/resilience4j/resilience4j[Resilience4J] +* https://github.com/alibaba/Sentinel[Sentinel] == Core Concepts @@ -96,6 +97,9 @@ include::spring-cloud-circuitbreaker-hystrix.adoc[] include::spring-cloud-circuitbreaker-resilience4j.adoc[] + +include::spring-cloud-circuitbreaker-sentinel.adoc[] + == Building include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/docs/src/main/asciidoc/building-jdk8.adoc[] From f75dde34c46af3252aa4d32bc3573366bc6c9466 Mon Sep 17 00:00:00 2001 From: Eric Zhao Date: Thu, 14 Mar 2019 22:43:11 +0800 Subject: [PATCH 08/18] Bump Sentinel version to 1.5.0 - Also add sentinel-reactor-adapter dependency management Signed-off-by: Eric Zhao --- spring-cloud-circuitbreaker-dependencies/pom.xml | 7 ++++++- spring-cloud-circuitbreaker-sentinel/pom.xml | 4 ++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/spring-cloud-circuitbreaker-dependencies/pom.xml b/spring-cloud-circuitbreaker-dependencies/pom.xml index cfb412f..e430861 100644 --- a/spring-cloud-circuitbreaker-dependencies/pom.xml +++ b/spring-cloud-circuitbreaker-dependencies/pom.xml @@ -19,7 +19,7 @@ 0.13.1 - 1.4.2 + 1.5.0 @@ -44,6 +44,11 @@ sentinel-core ${sentinel.version} + + com.alibaba.csp + sentinel-reactor-adapter + ${sentinel.version} + org.springframework.cloud spring-cloud-circuitbreaker-resilience4j diff --git a/spring-cloud-circuitbreaker-sentinel/pom.xml b/spring-cloud-circuitbreaker-sentinel/pom.xml index c8b93c7..40441fa 100644 --- a/spring-cloud-circuitbreaker-sentinel/pom.xml +++ b/spring-cloud-circuitbreaker-sentinel/pom.xml @@ -20,6 +20,10 @@ com.alibaba.csp sentinel-core + + com.alibaba.csp + sentinel-reactor-adapter + org.springframework.boot spring-boot-starter-web From cd174f0b762f0a1a5400a130dd42ce9b9f4b50f7 Mon Sep 17 00:00:00 2001 From: Eric Zhao Date: Thu, 14 Mar 2019 23:23:29 +0800 Subject: [PATCH 09/18] Update code according to the checkstyle Signed-off-by: Eric Zhao --- .../sentinel/SentinelCircuitBreaker.java | 12 +- ...ntinelCircuitBreakerAutoConfiguration.java | 16 +- .../SentinelCircuitBreakerFactory.java | 15 +- .../sentinel/SentinelConfigBuilder.java | 16 +- ...SentinelCircuitBreakerIntegrationTest.java | 159 ++++++++++-------- .../sentinel/SentinelCircuitBreakerTest.java | 61 +++++-- 6 files changed, 175 insertions(+), 104 deletions(-) diff --git a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreaker.java b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreaker.java index 2dd21a6..e0cfa38 100644 --- a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreaker.java +++ b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreaker.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.cloud.circuitbreaker.sentinel; import java.util.ArrayList; @@ -42,11 +43,13 @@ import org.springframework.util.Assert; public class SentinelCircuitBreaker implements CircuitBreaker { private final String resourceName; + private final EntryType entryType; private final List rules; - public SentinelCircuitBreaker(String resourceName, EntryType entryType, List rules) { + public SentinelCircuitBreaker(String resourceName, EntryType entryType, + List rules) { Assert.hasText(resourceName, "resourceName cannot be blank"); Assert.notNull(rules, "rules should not be null"); this.resourceName = resourceName; @@ -78,7 +81,8 @@ public class SentinelCircuitBreaker implements CircuitBreaker { Entry entry = null; try { entry = SphU.entry(resourceName, entryType); - // If the SphU.entry() does not throw `BlockException`, it means that the request can pass. + // If the SphU.entry() does not throw `BlockException`, it means that the + // request can pass. return toRun.get(); } catch (BlockException ex) { @@ -88,7 +92,8 @@ public class SentinelCircuitBreaker implements CircuitBreaker { return fallback.apply(ex); } catch (Exception ex) { - // For other kinds of exceptions, we'll trace the exception count via Tracer.trace(ex). + // For other kinds of exceptions, we'll trace the exception count via + // Tracer.trace(ex). Tracer.trace(ex); return fallback.apply(ex); } @@ -99,4 +104,5 @@ public class SentinelCircuitBreaker implements CircuitBreaker { } } } + } diff --git a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerAutoConfiguration.java b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerAutoConfiguration.java index d6efab7..ca42e58 100644 --- a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerAutoConfiguration.java +++ b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerAutoConfiguration.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.cloud.circuitbreaker.sentinel; import java.util.ArrayList; @@ -31,10 +32,12 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** + * Auto configuration for {@link SentinelCircuitBreaker}. + * * @author Eric Zhao */ @Configuration -@ConditionalOnClass({SphU.class}) +@ConditionalOnClass({ SphU.class }) public class SentinelCircuitBreakerAutoConfiguration { @Bean @@ -45,15 +48,18 @@ public class SentinelCircuitBreakerAutoConfiguration { @Configuration public static class SentinelCustomizerConfiguration { - @Autowired(required = false) - public List> customizers = new ArrayList<>(); @Autowired(required = false) - public SentinelCircuitBreakerFactory factory; + private List> customizers = new ArrayList<>(); + + @Autowired(required = false) + private SentinelCircuitBreakerFactory factory; @PostConstruct public void init() { customizers.forEach(customizer -> customizer.customize(factory)); } + } -} \ No newline at end of file + +} diff --git a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerFactory.java b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerFactory.java index 0d40ef5..1a8b5b2 100644 --- a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerFactory.java +++ b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerFactory.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.cloud.circuitbreaker.sentinel; import java.util.ArrayList; @@ -26,13 +27,11 @@ import org.springframework.util.Assert; /** * @author Eric Zhao */ -public class SentinelCircuitBreakerFactory extends CircuitBreakerFactory { +public class SentinelCircuitBreakerFactory extends + CircuitBreakerFactory { - private Function defaultConfiguration = id -> - new SentinelConfigBuilder() - .resourceName(id) - .rules(new ArrayList<>()) - .build(); + private Function defaultConfiguration = id -> new SentinelConfigBuilder() + .resourceName(id).rules(new ArrayList<>()).build(); @Override public CircuitBreaker create(String id) { @@ -48,7 +47,9 @@ public class SentinelCircuitBreakerFactory extends CircuitBreakerFactory defaultConfiguration) { + public void configureDefault( + Function defaultConfiguration) { this.defaultConfiguration = defaultConfiguration; } + } diff --git a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelConfigBuilder.java b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelConfigBuilder.java index 91bc227..560c0fc 100644 --- a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelConfigBuilder.java +++ b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelConfigBuilder.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.cloud.circuitbreaker.sentinel; import java.util.ArrayList; @@ -28,10 +29,13 @@ import org.springframework.util.Assert; /** * @author Eric Zhao */ -public class SentinelConfigBuilder implements ConfigBuilder { +public class SentinelConfigBuilder implements + ConfigBuilder { private String resourceName; + private EntryType entryType; + private List rules; public SentinelConfigBuilder() { @@ -59,17 +63,19 @@ public class SentinelConfigBuilder implements ConfigBuilder rules = Optional.ofNullable(this.rules).orElse(new ArrayList<>()); + List rules = Optional.ofNullable(this.rules) + .orElse(new ArrayList<>()); EntryType entryType = Optional.ofNullable(this.entryType).orElse(EntryType.OUT); return new SentinelCircuitBreakerConfiguration() - .setResourceName(this.resourceName) - .setEntryType(entryType) + .setResourceName(this.resourceName).setEntryType(entryType) .setRules(rules); } public static class SentinelCircuitBreakerConfiguration { + private String resourceName; + private EntryType entryType; private List rules; @@ -100,5 +106,7 @@ public class SentinelConfigBuilder implements ConfigBuilder slowCustomizer() { - String slowId = "slow"; - List rules = Collections.singletonList( - new DegradeRule(slowId).setGrade(RuleConstant.DEGRADE_GRADE_RT) - .setCount(100) - .setTimeWindow(10) - ); - return factory -> factory.configure(builder -> builder.rules(rules), slowId); - } + // Then in the next 10s, the fallback method should be called. + for (int i = 0; i < 10; i++) { + assertThat(service.slow()).isEqualTo("fallback"); + Thread.sleep(1000); + } - @Service - public static class DemoControllerService { - private TestRestTemplate rest; - private CircuitBreakerFactory cbFactory; + // Recovered. + assertThat(service.slow()).isEqualTo("slow"); + } - public DemoControllerService(TestRestTemplate rest, CircuitBreakerFactory cbFactory) { - this.rest = rest; - this.cbFactory = cbFactory; - } + @Test + public void testNormal() { + assertThat(service.normal()).isEqualTo("normal"); + } - public String slow() { - return cbFactory.create("slow").run(() -> rest.getForObject("/slow", String.class), t -> "fallback"); - } + @Before + public void setUp() { + DegradeRuleManager.loadRules(new ArrayList<>()); + } - public String normal() { - return cbFactory.create("normal").run(() -> rest.getForObject("/normal", String.class), - t -> "fallback"); - } - } - } + @Before + public void tearDown() { + DegradeRuleManager.loadRules(new ArrayList<>()); + } - @Autowired - Application.DemoControllerService service; + @Configuration + @EnableAutoConfiguration + @RestController + protected static class Application { - @Test - public void testSlow() throws Exception { - // The first 5 requests should pass. - assertEquals("slow", service.slow()); - assertEquals("slow", service.slow()); - assertEquals("slow", service.slow()); - assertEquals("slow", service.slow()); - assertEquals("slow", service.slow()); + @GetMapping("/slow") + public String slow() throws InterruptedException { + Thread.sleep(500); + return "slow"; + } - // Then in the next 10s, the fallback method should be called. - for (int i = 0; i < 10; i++) { - assertEquals("fallback", service.slow()); - Thread.sleep(1000); - } + @GetMapping("/normal") + public String normal() { + return "normal"; + } - // Recovered. - assertEquals("slow", service.slow()); - } + @Bean + public Customizer slowCustomizer() { + String slowId = "slow"; + List rules = Collections.singletonList( + new DegradeRule(slowId).setGrade(RuleConstant.DEGRADE_GRADE_RT) + .setCount(100).setTimeWindow(10)); + return factory -> { + factory.configure(builder -> builder.rules(rules), slowId); + factory.configureDefault(id -> new SentinelConfigBuilder() + .resourceName(id) + .rules(Collections.singletonList(new DegradeRule(id) + .setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT) + .setCount(0.5).setTimeWindow(10))) + .build()); + }; + } - @Test - public void testNormal() { - assertEquals("normal", service.normal()); - } + @Service + public static class DemoControllerService { + private TestRestTemplate rest; - @Before - public void setUp() { - DegradeRuleManager.loadRules(new ArrayList<>()); - } + private CircuitBreakerFactory cbFactory; + + DemoControllerService(TestRestTemplate rest, + CircuitBreakerFactory cbFactory) { + this.rest = rest; + this.cbFactory = cbFactory; + } + + public String slow() { + return cbFactory.create("slow").run( + () -> rest.getForObject("/slow", String.class), t -> "fallback"); + } + + public String normal() { + return cbFactory.create("normal").run( + () -> rest.getForObject("/normal", String.class), + t -> "fallback"); + } + + } + + } - @Before - public void tearDown() { - DegradeRuleManager.loadRules(new ArrayList<>()); - } } diff --git a/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerTest.java b/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerTest.java index d9b713b..0007903 100644 --- a/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerTest.java +++ b/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerTest.java @@ -13,29 +13,64 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.cloud.circuitbreaker.sentinel; +import java.util.ArrayList; +import java.util.Collections; + +import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; +import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; +import org.junit.After; import org.junit.Test; + import org.springframework.cloud.circuitbreaker.commons.CircuitBreaker; -import static org.junit.Assert.*; +import static org.assertj.core.api.Assertions.assertThat; /** * @author Eric Zhao */ public class SentinelCircuitBreakerTest { - @Test - public void testRun() { - CircuitBreaker cb = new SentinelCircuitBreakerFactory().create("testSentinelRun"); - assertEquals("foobar", cb.run(() -> "foobar")); - } + @After + public void tearDown() { + // Clear the rules. + DegradeRuleManager.loadRules(new ArrayList<>()); + } + + @Test + public void testCreateDirectlyThenRun() { + // Create a circuit breaker without any circuit breaking rules. + CircuitBreaker cb = new SentinelCircuitBreaker( + "testSentinelCreateDirectlyThenRunA"); + assertThat(cb.run(() -> "Sentinel")).isEqualTo("Sentinel"); + assertThat(DegradeRuleManager.hasConfig("testSentinelCreateDirectlyThenRunA")) + .isFalse(); + + CircuitBreaker cb2 = new SentinelCircuitBreaker( + "testSentinelCreateDirectlyThenRunB", + Collections.singletonList( + new DegradeRule("testSentinelCreateDirectlyThenRunB") + .setCount(100).setTimeWindow(10))); + assertThat(cb2.run(() -> "Sentinel")).isEqualTo("Sentinel"); + assertThat(DegradeRuleManager.hasConfig("testSentinelCreateDirectlyThenRunB")) + .isTrue(); + } + + @Test + public void testCreateFromFactoryThenRun() { + CircuitBreaker cb = new SentinelCircuitBreakerFactory().create("testSentinelRun"); + assertThat(cb.run(() -> "foobar")).isEqualTo("foobar"); + } + + @Test + public void testRunWithFallback() { + CircuitBreaker cb = new SentinelCircuitBreakerFactory() + .create("testSentinelRunWithFallback"); + assertThat(cb.run(() -> { + throw new RuntimeException("boom"); + }, t -> "fallback")).isEqualTo("fallback"); + } - @Test - public void testRunWithFallback() { - CircuitBreaker cb = new SentinelCircuitBreakerFactory().create("testSentinelRunWithFallback"); - assertEquals("fallback", cb.run(() -> { - throw new RuntimeException("boom"); - }, t -> "fallback")); - } } From 0d30f1d2877fd001dcdba03e864fefdde9ccf2b3 Mon Sep 17 00:00:00 2001 From: Spring Operator Date: Tue, 19 Mar 2019 20:21:57 -0500 Subject: [PATCH 10/18] URL Cleanup This commit updates URLs to prefer the https protocol. Redirects are not followed to avoid accidentally expanding intentionally shortened URLs (i.e. if using a URL shortener). # Fixed URLs ## Fixed Success These URLs were switched to an https URL with a 2xx status. While the status was successful, your review is still recommended. * http://maven.apache.org/xsd/maven-4.0.0.xsd with 11 occurrences migrated to: https://maven.apache.org/xsd/maven-4.0.0.xsd ([https](https://maven.apache.org/xsd/maven-4.0.0.xsd) result 200). * http://repo.spring.io/libs-milestone-local with 2 occurrences migrated to: https://repo.spring.io/libs-milestone-local ([https](https://repo.spring.io/libs-milestone-local) result 302). * http://repo.spring.io/libs-snapshot-local with 2 occurrences migrated to: https://repo.spring.io/libs-snapshot-local ([https](https://repo.spring.io/libs-snapshot-local) result 302). * http://repo.spring.io/release with 1 occurrences migrated to: https://repo.spring.io/release ([https](https://repo.spring.io/release) result 302). # Ignored These URLs were intentionally ignored. * http://maven.apache.org/POM/4.0.0 with 22 occurrences * http://www.w3.org/2001/XMLSchema-instance with 11 occurrences --- .settings.xml | 10 +++++----- docs/pom.xml | 2 +- pom.xml | 2 +- spring-cloud-circuitbreaker-commons/pom.xml | 2 +- spring-cloud-circuitbreaker-dependencies/pom.xml | 2 +- spring-cloud-circuitbreaker-hystrix/pom.xml | 2 +- spring-cloud-circuitbreaker-resilience4j/pom.xml | 2 +- spring-cloud-circuitbreaker-sentinel/pom.xml | 2 +- spring-cloud-starter-circuitbreaker/pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- 12 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.settings.xml b/.settings.xml index 6c35512..08951ca 100644 --- a/.settings.xml +++ b/.settings.xml @@ -21,7 +21,7 @@ spring-snapshots Spring Snapshots - http://repo.spring.io/libs-snapshot-local + https://repo.spring.io/libs-snapshot-local true @@ -29,7 +29,7 @@ spring-milestones Spring Milestones - http://repo.spring.io/libs-milestone-local + https://repo.spring.io/libs-milestone-local false @@ -37,7 +37,7 @@ spring-releases Spring Releases - http://repo.spring.io/release + https://repo.spring.io/release false @@ -47,7 +47,7 @@ spring-snapshots Spring Snapshots - http://repo.spring.io/libs-snapshot-local + https://repo.spring.io/libs-snapshot-local true @@ -55,7 +55,7 @@ spring-milestones Spring Milestones - http://repo.spring.io/libs-milestone-local + https://repo.spring.io/libs-milestone-local false diff --git a/docs/pom.xml b/docs/pom.xml index ad6ed86..4a34138 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -1,7 +1,7 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> spring-cloud-circuitbreaker org.springframework.cloud diff --git a/pom.xml b/pom.xml index 54902d8..84391c5 100644 --- a/pom.xml +++ b/pom.xml @@ -1,7 +1,7 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 org.springframework.cloud diff --git a/spring-cloud-circuitbreaker-commons/pom.xml b/spring-cloud-circuitbreaker-commons/pom.xml index 18964ef..f430ecd 100644 --- a/spring-cloud-circuitbreaker-commons/pom.xml +++ b/spring-cloud-circuitbreaker-commons/pom.xml @@ -1,7 +1,7 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> spring-cloud-circuitbreaker org.springframework.cloud diff --git a/spring-cloud-circuitbreaker-dependencies/pom.xml b/spring-cloud-circuitbreaker-dependencies/pom.xml index e430861..ca63ecc 100644 --- a/spring-cloud-circuitbreaker-dependencies/pom.xml +++ b/spring-cloud-circuitbreaker-dependencies/pom.xml @@ -1,7 +1,7 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 diff --git a/spring-cloud-circuitbreaker-hystrix/pom.xml b/spring-cloud-circuitbreaker-hystrix/pom.xml index 8278e9f..ca80df0 100644 --- a/spring-cloud-circuitbreaker-hystrix/pom.xml +++ b/spring-cloud-circuitbreaker-hystrix/pom.xml @@ -1,7 +1,7 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> spring-cloud-circuitbreaker org.springframework.cloud diff --git a/spring-cloud-circuitbreaker-resilience4j/pom.xml b/spring-cloud-circuitbreaker-resilience4j/pom.xml index ec65522..a271f52 100644 --- a/spring-cloud-circuitbreaker-resilience4j/pom.xml +++ b/spring-cloud-circuitbreaker-resilience4j/pom.xml @@ -1,7 +1,7 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> spring-cloud-circuitbreaker org.springframework.cloud diff --git a/spring-cloud-circuitbreaker-sentinel/pom.xml b/spring-cloud-circuitbreaker-sentinel/pom.xml index 40441fa..86315b8 100644 --- a/spring-cloud-circuitbreaker-sentinel/pom.xml +++ b/spring-cloud-circuitbreaker-sentinel/pom.xml @@ -1,7 +1,7 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> spring-cloud-circuitbreaker org.springframework.cloud diff --git a/spring-cloud-starter-circuitbreaker/pom.xml b/spring-cloud-starter-circuitbreaker/pom.xml index 9708ce5..f398e43 100644 --- a/spring-cloud-starter-circuitbreaker/pom.xml +++ b/spring-cloud-starter-circuitbreaker/pom.xml @@ -1,7 +1,7 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> spring-cloud-circuitbreaker org.springframework.cloud diff --git a/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-hystrix/pom.xml b/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-hystrix/pom.xml index d61ff1a..ad4b5c9 100644 --- a/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-hystrix/pom.xml +++ b/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-hystrix/pom.xml @@ -1,7 +1,7 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> spring-cloud-starter-circuitbreaker org.springframework.cloud diff --git a/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-resilience4j/pom.xml b/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-resilience4j/pom.xml index 330b588..8ca0b6a 100644 --- a/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-resilience4j/pom.xml +++ b/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-resilience4j/pom.xml @@ -1,7 +1,7 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> spring-cloud-starter-circuitbreaker org.springframework.cloud diff --git a/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-sentinel/pom.xml b/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-sentinel/pom.xml index 1af9d7a..3c00eba 100644 --- a/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-sentinel/pom.xml +++ b/spring-cloud-starter-circuitbreaker/spring-cloud-starter-circuitbreaker-sentinel/pom.xml @@ -1,7 +1,7 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> spring-cloud-starter-circuitbreaker org.springframework.cloud From 32e5e851efab6cbb94e24f5ecb7b19853164896a Mon Sep 17 00:00:00 2001 From: Spring Operator Date: Wed, 20 Mar 2019 15:05:20 -0500 Subject: [PATCH 11/18] URL Cleanup This commit updates URLs to prefer the https protocol. Redirects are not followed to avoid accidentally expanding intentionally shortened URLs (i.e. if using a URL shortener). # Fixed URLs ## Fixed But Review Recommended These URLs were fixed, but the https status was not OK. However, the https status was the same as the http request or http redirected to an https URL, so they were migrated. Your review is recommended. * [ ] http://compose.docker.io/ (UnknownHostException) with 1 occurrences migrated to: https://compose.docker.io/ ([https](https://compose.docker.io/) result UnknownHostException). * [ ] http://www.puppycrawl.com/dtds/suppressions_1_1.dtd (404) with 1 occurrences migrated to: https://www.puppycrawl.com/dtds/suppressions_1_1.dtd ([https](https://www.puppycrawl.com/dtds/suppressions_1_1.dtd) result 404). ## Fixed Success These URLs were switched to an https URL with a 2xx status. While the status was successful, your review is still recommended. * [ ] http://EditorConfig.org with 1 occurrences migrated to: https://EditorConfig.org ([https](https://EditorConfig.org) result 200). * [ ] http://github.com/ with 2 occurrences migrated to: https://github.com/ ([https](https://github.com/) result 200). * [ ] http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html with 1 occurrences migrated to: https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html ([https](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) result 200). * [ ] http://plugins.jetbrains.com/plugin/6546 with 1 occurrences migrated to: https://plugins.jetbrains.com/plugin/6546 ([https](https://plugins.jetbrains.com/plugin/6546) result 301). * [ ] http://raw.github.com/ with 2 occurrences migrated to: https://raw.github.com/ ([https](https://raw.github.com/) result 301). * [ ] http://eclipse.org with 1 occurrences migrated to: https://eclipse.org ([https](https://eclipse.org) result 302). * [ ] http://eclipse.org/m2e/ with 2 occurrences migrated to: https://eclipse.org/m2e/ ([https](https://eclipse.org/m2e/) result 302). * [ ] http://www.springsource.com/developer/sts with 1 occurrences migrated to: https://www.springsource.com/developer/sts ([https](https://www.springsource.com/developer/sts) result 302). # Ignored These URLs were intentionally ignored. * http://localhost with 6 occurrences --- .editorconfig | 2 +- README.adoc | 20 +++++++++---------- .../asciidoc/spring-cloud-circuitbreaker.adoc | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.editorconfig b/.editorconfig index 8c727f3..0d996cf 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,4 +1,4 @@ -# EditorConfig is awesome: http://EditorConfig.org +# EditorConfig is awesome: https://EditorConfig.org # top-most EditorConfig file root = true diff --git a/README.adoc b/README.adoc index 2475709..96d5f6c 100644 --- a/README.adoc +++ b/README.adoc @@ -10,8 +10,8 @@ image::https://api.codacy.com/project/badge/Grade/a6885a06921e4f72a0df0b7aabd6d1 :github-tag: master :github-repo: spring-cloud-incubator/spring-cloud-circuitbreaker -:github-raw: http://raw.github.com/{github-repo}/{github-tag} -:github-code: http://github.com/{github-repo}/tree/{github-tag} +:github-raw: https://raw.github.com/{github-repo}/{github-tag} +:github-code: https://github.com/{github-repo}/tree/{github-tag} :all: {asterisk}{asterisk} :nofooter: :branch: master @@ -290,7 +290,7 @@ credentials and you already have those. The projects that require middleware generally include a `docker-compose.yml`, so consider using -http://compose.docker.io/[Docker Compose] to run the middeware servers +https://compose.docker.io/[Docker Compose] to run the middeware servers in Docker containers. See the README in the https://github.com/spring-cloud-samples/scripts[scripts demo repository] for specific instructions about the common cases of mongo, @@ -312,13 +312,13 @@ a modified file in the correct place. Just commit it and push the change. === Working with the code If you don't have an IDE preference we would recommend that you use -http://www.springsource.com/developer/sts[Spring Tools Suite] or -http://eclipse.org[Eclipse] when working with the code. We use the -http://eclipse.org/m2e/[m2eclipse] eclipse plugin for maven support. Other IDEs and tools +https://www.springsource.com/developer/sts[Spring Tools Suite] or +https://eclipse.org[Eclipse] when working with the code. We use the +https://eclipse.org/m2e/[m2eclipse] eclipse plugin for maven support. Other IDEs and tools should also work without issue as long as they use Maven 3.3.3 or better. ==== Importing into eclipse with m2eclipse -We recommend the http://eclipse.org/m2e/[m2eclipse] eclipse plugin when working with +We recommend the https://eclipse.org/m2e/[m2eclipse] eclipse plugin when working with eclipse. If you don't already have m2eclipse installed it is available from the "eclipse marketplace". @@ -377,7 +377,7 @@ added after the original pull request but before a merge. `eclipse-code-formatter.xml` file from the https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-dependencies-parent/eclipse-code-formatter.xml[Spring Cloud Build] project. If using IntelliJ, you can use the - http://plugins.jetbrains.com/plugin/6546[Eclipse Code Formatter + https://plugins.jetbrains.com/plugin/6546[Eclipse Code Formatter Plugin] to import the same file. * Make sure all new `.java` files to have a simple Javadoc class comment with at least an `@author` tag identifying you, and preferably at least a paragraph on what the class is @@ -390,7 +390,7 @@ added after the original pull request but before a merge. * A few unit tests would help a lot as well -- someone has to do it. * If no-one else is using your branch, please rebase it against the current master (or other target branch in the main project). -* When writing a commit message please follow http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html[these conventions], +* When writing a commit message please follow https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html[these conventions], if you are fixing an existing issue please add `Fixes gh-XXXX` at the end of the commit message (where XXXX is the issue number). @@ -461,7 +461,7 @@ If you need to suppress some rules (e.g. line length needs to be longer), then i + "https://www.puppycrawl.com/dtds/suppressions_1_1.dtd"> diff --git a/docs/src/main/asciidoc/spring-cloud-circuitbreaker.adoc b/docs/src/main/asciidoc/spring-cloud-circuitbreaker.adoc index f05a062..9f01d85 100755 --- a/docs/src/main/asciidoc/spring-cloud-circuitbreaker.adoc +++ b/docs/src/main/asciidoc/spring-cloud-circuitbreaker.adoc @@ -1,7 +1,7 @@ :github-tag: master :github-repo: spring-cloud-incubator/spring-cloud-circuitbreaker -:github-raw: http://raw.github.com/{github-repo}/{github-tag} -:github-code: http://github.com/{github-repo}/tree/{github-tag} +:github-raw: https://raw.github.com/{github-repo}/{github-tag} +:github-code: https://github.com/{github-repo}/tree/{github-tag} :all: {asterisk}{asterisk} :nofooter: :branch: master From bdeb0462dbca163aca817d22d1d20128b3abd5ce Mon Sep 17 00:00:00 2001 From: Spring Operator Date: Thu, 21 Mar 2019 04:42:23 -0500 Subject: [PATCH 12/18] URL Cleanup This commit updates URLs to prefer the https protocol. Redirects are not followed to avoid accidentally expanding intentionally shortened URLs (i.e. if using a URL shortener). # Fixed URLs ## Fixed Success These URLs were switched to an https URL with a 2xx status. While the status was successful, your review is still recommended. * [ ] http://www.apache.org/licenses/ with 1 occurrences migrated to: https://www.apache.org/licenses/ ([https](https://www.apache.org/licenses/) result 200). * [ ] http://www.apache.org/licenses/LICENSE-2.0 with 37 occurrences migrated to: https://www.apache.org/licenses/LICENSE-2.0 ([https](https://www.apache.org/licenses/LICENSE-2.0) result 200). --- .mvn/wrapper/MavenWrapperDownloader.java | 2 +- LICENSE.txt | 4 ++-- .../circuitbreaker/commons/AbstractCircuitBreakerFactory.java | 2 +- .../cloud/circuitbreaker/commons/CircuitBreaker.java | 2 +- .../cloud/circuitbreaker/commons/CircuitBreakerFactory.java | 2 +- .../cloud/circuitbreaker/commons/ConfigBuilder.java | 2 +- .../cloud/circuitbreaker/commons/Customizer.java | 2 +- .../circuitbreaker/commons/NoFallbackAvailableException.java | 2 +- .../cloud/circuitbreaker/commons/ReactiveCircuitBreaker.java | 2 +- .../circuitbreaker/commons/ReactiveCircuitBreakerFactory.java | 2 +- .../circuitbreaker/hystrix/AbstractHystrixConfigBuilder.java | 2 +- .../cloud/circuitbreaker/hystrix/HystrixCircuitBreaker.java | 2 +- .../hystrix/HystrixCircuitBreakerAutoConfiguration.java | 2 +- .../circuitbreaker/hystrix/HystrixCircuitBreakerFactory.java | 2 +- .../circuitbreaker/hystrix/ReactiveHystrixCircuitBreaker.java | 2 +- .../hystrix/ReactiveHystrixCircuitBreakerFactory.java | 2 +- .../hystrix/HystrixCircuitBreakerIntegrationTest.java | 2 +- .../circuitbreaker/hystrix/HystrixCircuitBreakerTest.java | 2 +- .../hystrix/ReactiveHystrixCircuitBreakerIntegrationTest.java | 2 +- .../hystrix/ReactiveHystrixCircuitBreakerTest.java | 2 +- .../resilience4j/ReactiveResilience4JAutoConfiguration.java | 2 +- .../resilience4j/ReactiveResilience4JCircuitBreaker.java | 2 +- .../ReactiveResilience4JCircuitBreakerFactory.java | 2 +- .../resilience4j/Resilience4JAutoConfiguration.java | 2 +- .../resilience4j/Resilience4JCircuitBreaker.java | 2 +- .../resilience4j/Resilience4JCircuitBreakerFactory.java | 2 +- .../resilience4j/Resilience4JConfigBuilder.java | 2 +- .../ReactiveResilience4JCircuitBreakerIntegrationTest.java | 2 +- .../resilience4j/ReactiveResilience4JCircuitBreakerTest.java | 2 +- .../Resilience4JCircuitBreakerIntegrationTest.java | 2 +- .../resilience4j/Resilience4JCircuitBreakerTest.java | 2 +- .../cloud/circuitbreaker/sentinel/SentinelCircuitBreaker.java | 2 +- .../sentinel/SentinelCircuitBreakerAutoConfiguration.java | 2 +- .../sentinel/SentinelCircuitBreakerFactory.java | 2 +- .../cloud/circuitbreaker/sentinel/SentinelConfigBuilder.java | 2 +- .../sentinel/SentinelCircuitBreakerIntegrationTest.java | 2 +- .../circuitbreaker/sentinel/SentinelCircuitBreakerTest.java | 2 +- 37 files changed, 38 insertions(+), 38 deletions(-) diff --git a/.mvn/wrapper/MavenWrapperDownloader.java b/.mvn/wrapper/MavenWrapperDownloader.java index 0cf25d6..474be33 100755 --- a/.mvn/wrapper/MavenWrapperDownloader.java +++ b/.mvn/wrapper/MavenWrapperDownloader.java @@ -7,7 +7,7 @@ to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + https://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an diff --git a/LICENSE.txt b/LICENSE.txt index d645695..62589ed 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,7 +1,7 @@ Apache License Version 2.0, January 2004 - http://www.apache.org/licenses/ + https://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION @@ -193,7 +193,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + https://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-commons/src/main/java/org/springframework/cloud/circuitbreaker/commons/AbstractCircuitBreakerFactory.java b/spring-cloud-circuitbreaker-commons/src/main/java/org/springframework/cloud/circuitbreaker/commons/AbstractCircuitBreakerFactory.java index c7b3296..ceb9f20 100644 --- a/spring-cloud-circuitbreaker-commons/src/main/java/org/springframework/cloud/circuitbreaker/commons/AbstractCircuitBreakerFactory.java +++ b/spring-cloud-circuitbreaker-commons/src/main/java/org/springframework/cloud/circuitbreaker/commons/AbstractCircuitBreakerFactory.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-commons/src/main/java/org/springframework/cloud/circuitbreaker/commons/CircuitBreaker.java b/spring-cloud-circuitbreaker-commons/src/main/java/org/springframework/cloud/circuitbreaker/commons/CircuitBreaker.java index 8cbdf79..5f78fb7 100644 --- a/spring-cloud-circuitbreaker-commons/src/main/java/org/springframework/cloud/circuitbreaker/commons/CircuitBreaker.java +++ b/spring-cloud-circuitbreaker-commons/src/main/java/org/springframework/cloud/circuitbreaker/commons/CircuitBreaker.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-commons/src/main/java/org/springframework/cloud/circuitbreaker/commons/CircuitBreakerFactory.java b/spring-cloud-circuitbreaker-commons/src/main/java/org/springframework/cloud/circuitbreaker/commons/CircuitBreakerFactory.java index 22d092e..55381fe 100644 --- a/spring-cloud-circuitbreaker-commons/src/main/java/org/springframework/cloud/circuitbreaker/commons/CircuitBreakerFactory.java +++ b/spring-cloud-circuitbreaker-commons/src/main/java/org/springframework/cloud/circuitbreaker/commons/CircuitBreakerFactory.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-commons/src/main/java/org/springframework/cloud/circuitbreaker/commons/ConfigBuilder.java b/spring-cloud-circuitbreaker-commons/src/main/java/org/springframework/cloud/circuitbreaker/commons/ConfigBuilder.java index 8957cb8..5a134ec 100644 --- a/spring-cloud-circuitbreaker-commons/src/main/java/org/springframework/cloud/circuitbreaker/commons/ConfigBuilder.java +++ b/spring-cloud-circuitbreaker-commons/src/main/java/org/springframework/cloud/circuitbreaker/commons/ConfigBuilder.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-commons/src/main/java/org/springframework/cloud/circuitbreaker/commons/Customizer.java b/spring-cloud-circuitbreaker-commons/src/main/java/org/springframework/cloud/circuitbreaker/commons/Customizer.java index 6aa1641..340ba7b 100644 --- a/spring-cloud-circuitbreaker-commons/src/main/java/org/springframework/cloud/circuitbreaker/commons/Customizer.java +++ b/spring-cloud-circuitbreaker-commons/src/main/java/org/springframework/cloud/circuitbreaker/commons/Customizer.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-commons/src/main/java/org/springframework/cloud/circuitbreaker/commons/NoFallbackAvailableException.java b/spring-cloud-circuitbreaker-commons/src/main/java/org/springframework/cloud/circuitbreaker/commons/NoFallbackAvailableException.java index dee7f51..4f000f7 100644 --- a/spring-cloud-circuitbreaker-commons/src/main/java/org/springframework/cloud/circuitbreaker/commons/NoFallbackAvailableException.java +++ b/spring-cloud-circuitbreaker-commons/src/main/java/org/springframework/cloud/circuitbreaker/commons/NoFallbackAvailableException.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-commons/src/main/java/org/springframework/cloud/circuitbreaker/commons/ReactiveCircuitBreaker.java b/spring-cloud-circuitbreaker-commons/src/main/java/org/springframework/cloud/circuitbreaker/commons/ReactiveCircuitBreaker.java index 54c0fa6..d4bd2a3 100644 --- a/spring-cloud-circuitbreaker-commons/src/main/java/org/springframework/cloud/circuitbreaker/commons/ReactiveCircuitBreaker.java +++ b/spring-cloud-circuitbreaker-commons/src/main/java/org/springframework/cloud/circuitbreaker/commons/ReactiveCircuitBreaker.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-commons/src/main/java/org/springframework/cloud/circuitbreaker/commons/ReactiveCircuitBreakerFactory.java b/spring-cloud-circuitbreaker-commons/src/main/java/org/springframework/cloud/circuitbreaker/commons/ReactiveCircuitBreakerFactory.java index 1a2a356..cd6bef6 100644 --- a/spring-cloud-circuitbreaker-commons/src/main/java/org/springframework/cloud/circuitbreaker/commons/ReactiveCircuitBreakerFactory.java +++ b/spring-cloud-circuitbreaker-commons/src/main/java/org/springframework/cloud/circuitbreaker/commons/ReactiveCircuitBreakerFactory.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-hystrix/src/main/java/org/springframework/cloud/circuitbreaker/hystrix/AbstractHystrixConfigBuilder.java b/spring-cloud-circuitbreaker-hystrix/src/main/java/org/springframework/cloud/circuitbreaker/hystrix/AbstractHystrixConfigBuilder.java index 86926f8..766c980 100644 --- a/spring-cloud-circuitbreaker-hystrix/src/main/java/org/springframework/cloud/circuitbreaker/hystrix/AbstractHystrixConfigBuilder.java +++ b/spring-cloud-circuitbreaker-hystrix/src/main/java/org/springframework/cloud/circuitbreaker/hystrix/AbstractHystrixConfigBuilder.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-hystrix/src/main/java/org/springframework/cloud/circuitbreaker/hystrix/HystrixCircuitBreaker.java b/spring-cloud-circuitbreaker-hystrix/src/main/java/org/springframework/cloud/circuitbreaker/hystrix/HystrixCircuitBreaker.java index d779905..74b1c47 100644 --- a/spring-cloud-circuitbreaker-hystrix/src/main/java/org/springframework/cloud/circuitbreaker/hystrix/HystrixCircuitBreaker.java +++ b/spring-cloud-circuitbreaker-hystrix/src/main/java/org/springframework/cloud/circuitbreaker/hystrix/HystrixCircuitBreaker.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-hystrix/src/main/java/org/springframework/cloud/circuitbreaker/hystrix/HystrixCircuitBreakerAutoConfiguration.java b/spring-cloud-circuitbreaker-hystrix/src/main/java/org/springframework/cloud/circuitbreaker/hystrix/HystrixCircuitBreakerAutoConfiguration.java index 1411972..9693976 100644 --- a/spring-cloud-circuitbreaker-hystrix/src/main/java/org/springframework/cloud/circuitbreaker/hystrix/HystrixCircuitBreakerAutoConfiguration.java +++ b/spring-cloud-circuitbreaker-hystrix/src/main/java/org/springframework/cloud/circuitbreaker/hystrix/HystrixCircuitBreakerAutoConfiguration.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-hystrix/src/main/java/org/springframework/cloud/circuitbreaker/hystrix/HystrixCircuitBreakerFactory.java b/spring-cloud-circuitbreaker-hystrix/src/main/java/org/springframework/cloud/circuitbreaker/hystrix/HystrixCircuitBreakerFactory.java index 1fce486..856a45d 100644 --- a/spring-cloud-circuitbreaker-hystrix/src/main/java/org/springframework/cloud/circuitbreaker/hystrix/HystrixCircuitBreakerFactory.java +++ b/spring-cloud-circuitbreaker-hystrix/src/main/java/org/springframework/cloud/circuitbreaker/hystrix/HystrixCircuitBreakerFactory.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-hystrix/src/main/java/org/springframework/cloud/circuitbreaker/hystrix/ReactiveHystrixCircuitBreaker.java b/spring-cloud-circuitbreaker-hystrix/src/main/java/org/springframework/cloud/circuitbreaker/hystrix/ReactiveHystrixCircuitBreaker.java index a05f235..e5107b8 100644 --- a/spring-cloud-circuitbreaker-hystrix/src/main/java/org/springframework/cloud/circuitbreaker/hystrix/ReactiveHystrixCircuitBreaker.java +++ b/spring-cloud-circuitbreaker-hystrix/src/main/java/org/springframework/cloud/circuitbreaker/hystrix/ReactiveHystrixCircuitBreaker.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-hystrix/src/main/java/org/springframework/cloud/circuitbreaker/hystrix/ReactiveHystrixCircuitBreakerFactory.java b/spring-cloud-circuitbreaker-hystrix/src/main/java/org/springframework/cloud/circuitbreaker/hystrix/ReactiveHystrixCircuitBreakerFactory.java index 3b75ae0..5ad4b1e 100644 --- a/spring-cloud-circuitbreaker-hystrix/src/main/java/org/springframework/cloud/circuitbreaker/hystrix/ReactiveHystrixCircuitBreakerFactory.java +++ b/spring-cloud-circuitbreaker-hystrix/src/main/java/org/springframework/cloud/circuitbreaker/hystrix/ReactiveHystrixCircuitBreakerFactory.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-hystrix/src/test/java/org/springframework/cloud/circuitbreaker/hystrix/HystrixCircuitBreakerIntegrationTest.java b/spring-cloud-circuitbreaker-hystrix/src/test/java/org/springframework/cloud/circuitbreaker/hystrix/HystrixCircuitBreakerIntegrationTest.java index 8ff19ad..bc6f960 100644 --- a/spring-cloud-circuitbreaker-hystrix/src/test/java/org/springframework/cloud/circuitbreaker/hystrix/HystrixCircuitBreakerIntegrationTest.java +++ b/spring-cloud-circuitbreaker-hystrix/src/test/java/org/springframework/cloud/circuitbreaker/hystrix/HystrixCircuitBreakerIntegrationTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-hystrix/src/test/java/org/springframework/cloud/circuitbreaker/hystrix/HystrixCircuitBreakerTest.java b/spring-cloud-circuitbreaker-hystrix/src/test/java/org/springframework/cloud/circuitbreaker/hystrix/HystrixCircuitBreakerTest.java index e465ee6..19572e8 100644 --- a/spring-cloud-circuitbreaker-hystrix/src/test/java/org/springframework/cloud/circuitbreaker/hystrix/HystrixCircuitBreakerTest.java +++ b/spring-cloud-circuitbreaker-hystrix/src/test/java/org/springframework/cloud/circuitbreaker/hystrix/HystrixCircuitBreakerTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-hystrix/src/test/java/org/springframework/cloud/circuitbreaker/hystrix/ReactiveHystrixCircuitBreakerIntegrationTest.java b/spring-cloud-circuitbreaker-hystrix/src/test/java/org/springframework/cloud/circuitbreaker/hystrix/ReactiveHystrixCircuitBreakerIntegrationTest.java index 4f773b5..8968675 100644 --- a/spring-cloud-circuitbreaker-hystrix/src/test/java/org/springframework/cloud/circuitbreaker/hystrix/ReactiveHystrixCircuitBreakerIntegrationTest.java +++ b/spring-cloud-circuitbreaker-hystrix/src/test/java/org/springframework/cloud/circuitbreaker/hystrix/ReactiveHystrixCircuitBreakerIntegrationTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-hystrix/src/test/java/org/springframework/cloud/circuitbreaker/hystrix/ReactiveHystrixCircuitBreakerTest.java b/spring-cloud-circuitbreaker-hystrix/src/test/java/org/springframework/cloud/circuitbreaker/hystrix/ReactiveHystrixCircuitBreakerTest.java index 9a04501..888b50c 100644 --- a/spring-cloud-circuitbreaker-hystrix/src/test/java/org/springframework/cloud/circuitbreaker/hystrix/ReactiveHystrixCircuitBreakerTest.java +++ b/spring-cloud-circuitbreaker-hystrix/src/test/java/org/springframework/cloud/circuitbreaker/hystrix/ReactiveHystrixCircuitBreakerTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/ReactiveResilience4JAutoConfiguration.java b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/ReactiveResilience4JAutoConfiguration.java index 0612fcf..28bafb7 100644 --- a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/ReactiveResilience4JAutoConfiguration.java +++ b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/ReactiveResilience4JAutoConfiguration.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/ReactiveResilience4JCircuitBreaker.java b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/ReactiveResilience4JCircuitBreaker.java index adb1f24..504227e 100644 --- a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/ReactiveResilience4JCircuitBreaker.java +++ b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/ReactiveResilience4JCircuitBreaker.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/ReactiveResilience4JCircuitBreakerFactory.java b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/ReactiveResilience4JCircuitBreakerFactory.java index 0cb737c..2855fc4 100644 --- a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/ReactiveResilience4JCircuitBreakerFactory.java +++ b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/ReactiveResilience4JCircuitBreakerFactory.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JAutoConfiguration.java b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JAutoConfiguration.java index ed69b27..10af473 100644 --- a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JAutoConfiguration.java +++ b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JAutoConfiguration.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreaker.java b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreaker.java index 8d26498..bf22b3b 100644 --- a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreaker.java +++ b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreaker.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerFactory.java b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerFactory.java index 3197455..fe096d9 100644 --- a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerFactory.java +++ b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerFactory.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JConfigBuilder.java b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JConfigBuilder.java index eb7bfc1..da35968 100644 --- a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JConfigBuilder.java +++ b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JConfigBuilder.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/ReactiveResilience4JCircuitBreakerIntegrationTest.java b/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/ReactiveResilience4JCircuitBreakerIntegrationTest.java index 35bdd79..8febb2b 100644 --- a/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/ReactiveResilience4JCircuitBreakerIntegrationTest.java +++ b/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/ReactiveResilience4JCircuitBreakerIntegrationTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/ReactiveResilience4JCircuitBreakerTest.java b/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/ReactiveResilience4JCircuitBreakerTest.java index 734e400..fd37c81 100644 --- a/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/ReactiveResilience4JCircuitBreakerTest.java +++ b/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/ReactiveResilience4JCircuitBreakerTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerIntegrationTest.java b/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerIntegrationTest.java index 48bbe5e..c0b90f4 100644 --- a/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerIntegrationTest.java +++ b/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerIntegrationTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerTest.java b/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerTest.java index 225ac45..090dc1b 100644 --- a/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerTest.java +++ b/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreaker.java b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreaker.java index e0cfa38..e08fe12 100644 --- a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreaker.java +++ b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreaker.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerAutoConfiguration.java b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerAutoConfiguration.java index ca42e58..db7a968 100644 --- a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerAutoConfiguration.java +++ b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerAutoConfiguration.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerFactory.java b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerFactory.java index 1a8b5b2..2b801d0 100644 --- a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerFactory.java +++ b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerFactory.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelConfigBuilder.java b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelConfigBuilder.java index 560c0fc..9e7398d 100644 --- a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelConfigBuilder.java +++ b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelConfigBuilder.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerIntegrationTest.java b/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerIntegrationTest.java index 37d4f57..6c40fba 100644 --- a/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerIntegrationTest.java +++ b/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerIntegrationTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerTest.java b/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerTest.java index 0007903..1e470a2 100644 --- a/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerTest.java +++ b/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, From 339c4ff51347a66ad7cbe7e809c47afb846c6422 Mon Sep 17 00:00:00 2001 From: Eric Zhao Date: Fri, 22 Mar 2019 11:52:39 +0800 Subject: [PATCH 13/18] Update rule configuration mechanism for SentinelCircuitBreaker Signed-off-by: Eric Zhao --- .../sentinel/SentinelCircuitBreaker.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreaker.java b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreaker.java index e0cfa38..e6aa52d 100644 --- a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreaker.java +++ b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreaker.java @@ -49,7 +49,7 @@ public class SentinelCircuitBreaker implements CircuitBreaker { private final List rules; public SentinelCircuitBreaker(String resourceName, EntryType entryType, - List rules) { + List rules) { Assert.hasText(resourceName, "resourceName cannot be blank"); Assert.notNull(rules, "rules should not be null"); this.resourceName = resourceName; @@ -72,7 +72,13 @@ public class SentinelCircuitBreaker implements CircuitBreaker { return; } Set ruleSet = new HashSet<>(DegradeRuleManager.getRules()); - ruleSet.addAll(this.rules); + for (DegradeRule rule : this.rules) { + if (rule == null) { + continue; + } + rule.setResource(resourceName); + ruleSet.add(rule); + } DegradeRuleManager.loadRules(new ArrayList<>(ruleSet)); } From ec6c9c3bd785f18d551e81452168a17b8638b601 Mon Sep 17 00:00:00 2001 From: Eric Zhao Date: Fri, 22 Mar 2019 13:44:17 +0800 Subject: [PATCH 14/18] Add reactive Sentinel circuit breaker implementation Signed-off-by: Eric Zhao --- spring-cloud-circuitbreaker-sentinel/pom.xml | 6 +- .../ReactiveSentinelCircuitBreaker.java | 104 +++++++++ ...ntinelCircuitBreakerAutoConfiguration.java | 65 ++++++ ...ReactiveSentinelCircuitBreakerFactory.java | 58 +++++ .../main/resources/META-INF/spring.factories | 3 +- ...SentinelCircuitBreakerIntegrationTest.java | 211 ++++++++++++++++++ .../ReactiveSentinelCircuitBreakerTest.java | 67 ++++++ 7 files changed, 512 insertions(+), 2 deletions(-) create mode 100644 spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreaker.java create mode 100644 spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerAutoConfiguration.java create mode 100644 spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerFactory.java create mode 100644 spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerIntegrationTest.java create mode 100644 spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerTest.java diff --git a/spring-cloud-circuitbreaker-sentinel/pom.xml b/spring-cloud-circuitbreaker-sentinel/pom.xml index 40441fa..7b32a66 100644 --- a/spring-cloud-circuitbreaker-sentinel/pom.xml +++ b/spring-cloud-circuitbreaker-sentinel/pom.xml @@ -45,5 +45,9 @@ spring-boot-starter-test test + + io.projectreactor + reactor-test + - \ No newline at end of file + diff --git a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreaker.java b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreaker.java new file mode 100644 index 0000000..c065c58 --- /dev/null +++ b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreaker.java @@ -0,0 +1,104 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.circuitbreaker.sentinel; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.Function; + +import com.alibaba.csp.sentinel.EntryType; +import com.alibaba.csp.sentinel.adapter.reactor.EntryConfig; +import com.alibaba.csp.sentinel.adapter.reactor.SentinelReactorTransformer; +import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; +import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import org.springframework.cloud.circuitbreaker.commons.ReactiveCircuitBreaker; +import org.springframework.util.Assert; + +/** + * Sentinel implementation of {@link ReactiveCircuitBreaker}. + * + * @author Eric Zhao + */ +public class ReactiveSentinelCircuitBreaker implements ReactiveCircuitBreaker { + + private final String resourceName; + + private final EntryType entryType; + + private final List rules; + + public ReactiveSentinelCircuitBreaker(String resourceName, EntryType entryType, + List rules) { + Assert.hasText(resourceName, "resourceName cannot be blank"); + Assert.notNull(rules, "rules should not be null"); + this.resourceName = resourceName; + this.entryType = entryType; + this.rules = Collections.unmodifiableList(rules); + + applyToSentinelRuleManager(); + } + + public ReactiveSentinelCircuitBreaker(String resourceName, List rules) { + this(resourceName, EntryType.OUT, rules); + } + + public ReactiveSentinelCircuitBreaker(String resourceName) { + this(resourceName, EntryType.OUT, Collections.emptyList()); + } + + private void applyToSentinelRuleManager() { + if (this.rules == null || this.rules.isEmpty()) { + return; + } + Set ruleSet = new HashSet<>(DegradeRuleManager.getRules()); + for (DegradeRule rule : this.rules) { + if (rule == null) { + continue; + } + rule.setResource(resourceName); + ruleSet.add(rule); + } + DegradeRuleManager.loadRules(new ArrayList<>(ruleSet)); + } + + @Override + public Mono run(Mono toRun, Function> fallback) { + Mono toReturn = toRun.transform(new SentinelReactorTransformer<>( + new EntryConfig(resourceName, entryType))); + if (fallback != null) { + toReturn = toReturn.onErrorResume(fallback); + } + return toReturn; + } + + @Override + public Flux run(Flux toRun, Function> fallback) { + Flux toReturn = toRun.transform(new SentinelReactorTransformer<>( + new EntryConfig(resourceName, entryType))); + if (fallback != null) { + toReturn = toReturn.onErrorResume(fallback); + } + return toReturn; + } + +} diff --git a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerAutoConfiguration.java b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerAutoConfiguration.java new file mode 100644 index 0000000..cc99f46 --- /dev/null +++ b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerAutoConfiguration.java @@ -0,0 +1,65 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.circuitbreaker.sentinel; + +import java.util.ArrayList; +import java.util.List; + +import javax.annotation.PostConstruct; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.cloud.circuitbreaker.commons.Customizer; +import org.springframework.cloud.circuitbreaker.commons.ReactiveCircuitBreakerFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author Eric Zhao + */ +@Configuration +@ConditionalOnClass(name = { "reactor.core.publisher.Mono", + "reactor.core.publisher.Flux" }) +public class ReactiveSentinelCircuitBreakerAutoConfiguration { + + @Bean + @ConditionalOnMissingBean(ReactiveCircuitBreakerFactory.class) + + public ReactiveCircuitBreakerFactory reactiveSentinelCircuitBreakerFactory() { + return new ReactiveSentinelCircuitBreakerFactory(); + } + + @Configuration + @ConditionalOnClass(name = { "reactor.core.publisher.Mono", + "reactor.core.publisher.Flux" }) + public static class ReactiveSentinelCustomizerConfiguration { + + @Autowired(required = false) + private List> customizers = new ArrayList<>(); + + @Autowired(required = false) + private ReactiveSentinelCircuitBreakerFactory factory; + + @PostConstruct + public void init() { + customizers.forEach(customizer -> customizer.customize(factory)); + } + + } + +} diff --git a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerFactory.java b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerFactory.java new file mode 100644 index 0000000..98a4365 --- /dev/null +++ b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerFactory.java @@ -0,0 +1,58 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.circuitbreaker.sentinel; + +import java.util.ArrayList; +import java.util.function.Function; + +import org.springframework.cloud.circuitbreaker.commons.ReactiveCircuitBreaker; +import org.springframework.cloud.circuitbreaker.commons.ReactiveCircuitBreakerFactory; +import org.springframework.cloud.circuitbreaker.sentinel.SentinelConfigBuilder.SentinelCircuitBreakerConfiguration; +import org.springframework.util.Assert; + +/** + * Factory for {@link ReactiveSentinelCircuitBreaker}. + * + * @author Eric Zhao + */ +public class ReactiveSentinelCircuitBreakerFactory extends + ReactiveCircuitBreakerFactory { + + private Function defaultConfiguration = id -> new SentinelConfigBuilder() + .resourceName(id).rules(new ArrayList<>()).build(); + + @Override + public ReactiveCircuitBreaker create(String id) { + Assert.hasText(id, "A CircuitBreaker must have an id."); + SentinelConfigBuilder.SentinelCircuitBreakerConfiguration conf = getConfigurations() + .computeIfAbsent(id, defaultConfiguration); + return new ReactiveSentinelCircuitBreaker(id, conf.getEntryType(), + conf.getRules()); + } + + @Override + protected SentinelConfigBuilder configBuilder(String id) { + return new SentinelConfigBuilder(id); + } + + @Override + public void configureDefault( + Function defaultConfiguration) { + this.defaultConfiguration = defaultConfiguration; + } + +} diff --git a/spring-cloud-circuitbreaker-sentinel/src/main/resources/META-INF/spring.factories b/spring-cloud-circuitbreaker-sentinel/src/main/resources/META-INF/spring.factories index 490c87e..67343b1 100644 --- a/spring-cloud-circuitbreaker-sentinel/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-circuitbreaker-sentinel/src/main/resources/META-INF/spring.factories @@ -1,2 +1,3 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -org.springframework.cloud.circuitbreaker.sentinel.SentinelCircuitBreakerAutoConfiguration +org.springframework.cloud.circuitbreaker.sentinel.SentinelCircuitBreakerAutoConfiguration,\ +org.springframework.cloud.circuitbreaker.sentinel.ReactiveSentinelCircuitBreakerAutoConfiguration diff --git a/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerIntegrationTest.java b/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerIntegrationTest.java new file mode 100644 index 0000000..2e262a1 --- /dev/null +++ b/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerIntegrationTest.java @@ -0,0 +1,211 @@ +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.circuitbreaker.sentinel; + +import java.time.Duration; +import java.util.Collections; + +import com.alibaba.csp.sentinel.slots.block.RuleConstant; +import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import reactor.test.StepVerifier; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.cloud.circuitbreaker.commons.Customizer; +import org.springframework.cloud.circuitbreaker.commons.ReactiveCircuitBreakerFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.stereotype.Service; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.reactive.function.client.WebClient; + +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; + +/** + * @author Ryan Baxter + */ +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = RANDOM_PORT, classes = ReactiveSentinelCircuitBreakerIntegrationTest.Application.class) +@DirtiesContext +public class ReactiveSentinelCircuitBreakerIntegrationTest { + + @LocalServerPort + private int port = 0; + + @Autowired + private ReactiveSentinelCircuitBreakerIntegrationTest.Application.DemoControllerService service; + + @Before + public void setup() { + service.setPort(port); + } + + @Test + public void test() throws Exception { + StepVerifier.create(service.normal()).expectNext("normal").verifyComplete(); + StepVerifier.create(service.slow()).expectNext("slow").verifyComplete(); + StepVerifier.create(service.slow()).expectNext("slow").verifyComplete(); + StepVerifier.create(service.slow()).expectNext("slow").verifyComplete(); + StepVerifier.create(service.slow()).expectNext("slow").verifyComplete(); + StepVerifier.create(service.slow()).expectNext("slow").verifyComplete(); + + // Then in the next 5s, the fallback method should be called. + for (int i = 0; i < 5; i++) { + StepVerifier.create(service.slow()).expectNext("fallback").verifyComplete(); + Thread.sleep(1000); + } + + // Recovered. + StepVerifier.create(service.slow()).expectNext("slow").verifyComplete(); + + StepVerifier.create(service.normalFlux()).expectNext("normalflux") + .verifyComplete(); + StepVerifier.create(service.slowFlux()).expectNext("slowflux").verifyComplete(); + StepVerifier.create(service.slowFlux()).expectNext("slowflux").verifyComplete(); + StepVerifier.create(service.slowFlux()).expectNext("slowflux").verifyComplete(); + StepVerifier.create(service.slowFlux()).expectNext("slowflux").verifyComplete(); + StepVerifier.create(service.slowFlux()).expectNext("slowflux").verifyComplete(); + // Then in the next 5s, the fallback method should be called. + for (int i = 0; i < 5; i++) { + StepVerifier.create(service.slowFlux()).expectNext("flux_fallback") + .verifyComplete(); + Thread.sleep(1000); + } + + // Recovered. + StepVerifier.create(service.slowFlux()).expectNext("slowflux").verifyComplete(); + } + + @Configuration + @EnableAutoConfiguration + @RestController + protected static class Application { + + @GetMapping("/slow") + public Mono slow() { + return Mono.just("slow").delayElement(Duration.ofMillis(500)); + } + + @GetMapping("/normal") + public Mono normal() { + return Mono.just("normal"); + } + + @GetMapping("/slow_flux") + public Flux slowFlux() { + return Flux.just("slow", "flux").delayElements(Duration.ofMillis(500)); + } + + @GetMapping("normal_flux") + public Flux normalFlux() { + return Flux.just("normal", "flux"); + } + + @Bean + public Customizer slowCustomizer() { + return factory -> { + factory.configure(builder -> builder + .rules(Collections.singletonList(new DegradeRule("slow_mono") + .setGrade(RuleConstant.DEGRADE_GRADE_RT).setCount(100) + .setTimeWindow(5))), + "slow_mono"); + factory.configure(builder -> builder + .rules(Collections.singletonList(new DegradeRule("slow_flux") + .setGrade(RuleConstant.DEGRADE_GRADE_RT).setCount(100) + .setTimeWindow(5))), + "slow_flux"); + factory.configureDefault(id -> new SentinelConfigBuilder() + .resourceName(id) + .rules(Collections.singletonList(new DegradeRule(id) + .setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT) + .setCount(0.5).setTimeWindow(10))) + .build()); + }; + } + + @Service + public static class DemoControllerService { + + private int port = 0; + + private ReactiveCircuitBreakerFactory cbFactory; + + DemoControllerService(ReactiveCircuitBreakerFactory cbFactory) { + this.cbFactory = cbFactory; + } + + public Mono slow() { + return cbFactory.create("slow_mono").run( + WebClient.builder().baseUrl("http://localhost:" + port).build() + .get().uri("/slow").retrieve().bodyToMono(String.class), + t -> { + t.printStackTrace(); + return Mono.just("fallback"); + }); + } + + public Mono normal() { + return cbFactory.create("normal_mono").run( + WebClient.builder().baseUrl("http://localhost:" + port).build() + .get().uri("/normal").retrieve().bodyToMono(String.class), + t -> { + t.printStackTrace(); + return Mono.just("fallback"); + }); + } + + public Flux slowFlux() { + return cbFactory.create("slow_flux") + .run(WebClient.builder().baseUrl("http://localhost:" + port) + .build().get().uri("/slow_flux").retrieve() + .bodyToFlux(new ParameterizedTypeReference() { + }), t -> { + t.printStackTrace(); + return Flux.just("flux_fallback"); + }); + } + + public Flux normalFlux() { + return cbFactory.create("normal_flux") + .run(WebClient.builder().baseUrl("http://localhost:" + port) + .build().get().uri("/normal_flux").retrieve() + .bodyToFlux(String.class), t -> { + t.printStackTrace(); + return Flux.just("flux_fallback"); + }); + } + + public void setPort(int port) { + this.port = port; + } + + } + + } + +} diff --git a/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerTest.java b/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerTest.java new file mode 100644 index 0000000..d0e4b5d --- /dev/null +++ b/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerTest.java @@ -0,0 +1,67 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.circuitbreaker.sentinel; + +import java.util.Arrays; + +import org.junit.Test; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import org.springframework.cloud.circuitbreaker.commons.ReactiveCircuitBreaker; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Eric Zhao + */ +public class ReactiveSentinelCircuitBreakerTest { + + @Test + public void runMono() { + ReactiveCircuitBreaker cb = new ReactiveSentinelCircuitBreakerFactory() + .create("foo"); + assertThat(cb.run(Mono.just("foobar")).block()).isEqualTo("foobar"); + } + + @Test + public void runMonoWithFallback() { + ReactiveCircuitBreaker cb = new ReactiveSentinelCircuitBreakerFactory() + .create("foo"); + assertThat(cb + .run(Mono.error(new RuntimeException("boom")), t -> Mono.just("fallback")) + .block()).isEqualTo("fallback"); + } + + @Test + public void runFlux() { + ReactiveCircuitBreaker cb = new ReactiveSentinelCircuitBreakerFactory() + .create("foo"); + assertThat(cb.run(Flux.just("foobar", "hello world")).collectList().block()) + .isEqualTo(Arrays.asList("foobar", "hello world")); + } + + @Test + public void runFluxWithFallback() { + ReactiveCircuitBreaker cb = new ReactiveSentinelCircuitBreakerFactory() + .create("foo"); + assertThat(cb + .run(Flux.error(new RuntimeException("boom")), t -> Flux.just("fallback")) + .collectList().block()).isEqualTo(Arrays.asList("fallback")); + } + +} From 4b030bc4dbe046137a6256515641ab556d447fd6 Mon Sep 17 00:00:00 2001 From: Eric Zhao Date: Fri, 22 Mar 2019 16:49:58 +0800 Subject: [PATCH 15/18] Add document for reactive Sentinel circuit breaker and fix checkstyle Signed-off-by: Eric Zhao --- .../spring-cloud-circuitbreaker-sentinel.adoc | 35 +++++++++++++++++-- .../ReactiveSentinelCircuitBreaker.java | 2 +- ...ntinelCircuitBreakerAutoConfiguration.java | 2 +- ...ReactiveSentinelCircuitBreakerFactory.java | 2 +- ...SentinelCircuitBreakerIntegrationTest.java | 2 +- .../ReactiveSentinelCircuitBreakerTest.java | 2 +- 6 files changed, 38 insertions(+), 7 deletions(-) diff --git a/docs/src/main/asciidoc/spring-cloud-circuitbreaker-sentinel.adoc b/docs/src/main/asciidoc/spring-cloud-circuitbreaker-sentinel.adoc index 413f217..b86cc4f 100644 --- a/docs/src/main/asciidoc/spring-cloud-circuitbreaker-sentinel.adoc +++ b/docs/src/main/asciidoc/spring-cloud-circuitbreaker-sentinel.adoc @@ -3,7 +3,7 @@ ==== Default Configuration To provide a default configuration for all of your circuit breakers create a `Customizer` bean that is passed a -`SentinelCircuitBreakerFactory`. +`SentinelCircuitBreakerFactory` or `ReactiveSentinelCircuitBreakerFactory`. The `configureDefault` method can be used to provide a default configuration. ==== @@ -22,6 +22,20 @@ You can also choose to load circuit breaking rules later elsewhere using `DegradeRuleManager.loadRules(rules)` API of Sentinel. +===== Reactive Example + +==== +[source,java] +---- +@Bean +public Customizer defaultCustomizer() { + return factory -> factory.configureDefault(id -> new SentinelConfigBuilder(id) + .build()); +} +---- +==== + + ==== Specific Circuit Breaker Configuration Similarly to providing a default configuration, you can create a `Customizer` bean this is passed a @@ -41,4 +55,21 @@ public Customizer slowCustomizer() { return factory -> factory.configure(builder -> builder.rules(rules), slowId); } ---- -==== \ No newline at end of file +==== + +===== Reactive Example + +==== +[source,java] +---- +@Bean +public Customizer customizer() { + List rules = Collections.singletonList( + new DegradeRule().setGrade(RuleConstant.DEGRADE_GRADE_RT) + .setCount(100) + .setTimeWindow(10) + ); + return factory -> factory.configure(builder -> builder.rules(rules), "foo", "bar"); +} +---- +==== diff --git a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreaker.java b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreaker.java index c065c58..b87807d 100644 --- a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreaker.java +++ b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreaker.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerAutoConfiguration.java b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerAutoConfiguration.java index cc99f46..b554e06 100644 --- a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerAutoConfiguration.java +++ b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerAutoConfiguration.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerFactory.java b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerFactory.java index 98a4365..807fe7e 100644 --- a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerFactory.java +++ b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerFactory.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerIntegrationTest.java b/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerIntegrationTest.java index 2e262a1..f4be5f2 100644 --- a/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerIntegrationTest.java +++ b/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerIntegrationTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerTest.java b/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerTest.java index d0e4b5d..ae76c04 100644 --- a/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerTest.java +++ b/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, From 64dc6b7f611a249a89b868a69fb416233521ab42 Mon Sep 17 00:00:00 2001 From: George Harley Date: Wed, 27 Mar 2019 17:53:34 +0000 Subject: [PATCH 16/18] Stop lengthy requests blocking subsequent circuit breaker calls * Replace choice of ExecutorService in Resilience4JCircuitBreakerFactory with cached thread pool alternative * Added failing test to demonstrate the problem * Fixes issue gh-25 --- .../Resilience4JCircuitBreakerFactory.java | 2 +- ...lience4JCircuitBreakerIntegrationTest.java | 47 +++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerFactory.java b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerFactory.java index fe096d9..bc798a4 100644 --- a/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerFactory.java +++ b/spring-cloud-circuitbreaker-resilience4j/src/main/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerFactory.java @@ -45,7 +45,7 @@ public class Resilience4JCircuitBreakerFactory extends private CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry .ofDefaults(); - private ExecutorService executorService = Executors.newSingleThreadExecutor(); + private ExecutorService executorService = Executors.newCachedThreadPool(); private Map> circuitBreakerCustomizers = new HashMap<>(); diff --git a/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerIntegrationTest.java b/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerIntegrationTest.java index c0b90f4..5312ec1 100644 --- a/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerIntegrationTest.java +++ b/spring-cloud-circuitbreaker-resilience4j/src/test/java/org/springframework/cloud/circuitbreaker/resilience4j/Resilience4JCircuitBreakerIntegrationTest.java @@ -35,10 +35,14 @@ import org.springframework.cloud.circuitbreaker.commons.CircuitBreakerFactory; import org.springframework.cloud.circuitbreaker.commons.Customizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; import org.springframework.stereotype.Service; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RestController; import static org.assertj.core.api.Assertions.assertThat; @@ -84,6 +88,12 @@ public class Resilience4JCircuitBreakerIntegrationTest { verify(normalSuccessConsumer, times(1)).consumeEvent(any()); } + @Test + public void testSlowResponsesDontFailSubsequentGoodRequests() { + assertThat(service.slowOnDemand(5000)).isEqualTo("fallback"); + assertThat(service.slowOnDemand(0)).isEqualTo("normal"); + } + @Configuration @EnableAutoConfiguration @RestController @@ -100,6 +110,23 @@ public class Resilience4JCircuitBreakerIntegrationTest { return "normal"; } + @GetMapping("/slowOnDemand") + public String slowOnDemand(@RequestHeader HttpHeaders headers) { + if (headers.containsKey("delayInMilliseconds")) { + String delayString = headers.getFirst("delayInMilliseconds"); + if (delayString != null) { + try { + Thread.sleep(Integer.parseInt(delayString)); + } + catch (NumberFormatException | InterruptedException e) { + e.printStackTrace(); + } + } + } + + return "normal"; + } + @Bean public Customizer slowCustomizer() { return factory -> { @@ -146,6 +173,26 @@ public class Resilience4JCircuitBreakerIntegrationTest { t -> "fallback"); } + public String slowOnDemand(int delayInMilliseconds) { + return cbFactory.create("slow") + .run(() -> rest + .exchange("/slowOnDemand", HttpMethod.GET, + createEntityWithOptionalDelayHeader( + delayInMilliseconds), + String.class) + .getBody(), t -> "fallback"); + } + + private HttpEntity createEntityWithOptionalDelayHeader( + int delayInMilliseconds) { + HttpHeaders headers = new HttpHeaders(); + if (delayInMilliseconds > 0) { + headers.set("delayInMilliseconds", + Integer.toString(delayInMilliseconds)); + } + return new HttpEntity<>(null, headers); + } + } } From 30df06ab4783c2d1e59fb05651422b7270a7181d Mon Sep 17 00:00:00 2001 From: Eric Zhao Date: Tue, 2 Apr 2019 21:23:04 +0800 Subject: [PATCH 17/18] Update test cases and doc Signed-off-by: Eric Zhao --- .../spring-cloud-circuitbreaker-sentinel.adoc | 2 +- .../SentinelCircuitBreakerFactory.java | 13 ++++++---- .../ReactiveSentinelCircuitBreakerTest.java | 10 ++++++++ .../sentinel/SentinelCircuitBreakerTest.java | 24 ++++++++++++------- 4 files changed, 36 insertions(+), 13 deletions(-) diff --git a/docs/src/main/asciidoc/spring-cloud-circuitbreaker-sentinel.adoc b/docs/src/main/asciidoc/spring-cloud-circuitbreaker-sentinel.adoc index b86cc4f..6671dff 100644 --- a/docs/src/main/asciidoc/spring-cloud-circuitbreaker-sentinel.adoc +++ b/docs/src/main/asciidoc/spring-cloud-circuitbreaker-sentinel.adoc @@ -19,7 +19,7 @@ public Customizer defaultCustomizer() { You can choose to provide default circuit breaking rules via `SentinelConfigBuilder#rules(rules)`. You can also choose to load circuit breaking rules later elsewhere using -`DegradeRuleManager.loadRules(rules)` API of Sentinel. +`DegradeRuleManager.loadRules(rules)` API of Sentinel, or via Sentinel dashboard. ===== Reactive Example diff --git a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerFactory.java b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerFactory.java index 2b801d0..66b5167 100644 --- a/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerFactory.java +++ b/spring-cloud-circuitbreaker-sentinel/src/main/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerFactory.java @@ -19,6 +19,8 @@ package org.springframework.cloud.circuitbreaker.sentinel; import java.util.ArrayList; import java.util.function.Function; +import com.alibaba.csp.sentinel.EntryType; + import org.springframework.cloud.circuitbreaker.commons.CircuitBreaker; import org.springframework.cloud.circuitbreaker.commons.CircuitBreakerFactory; import org.springframework.cloud.circuitbreaker.sentinel.SentinelConfigBuilder.SentinelCircuitBreakerConfiguration; @@ -28,16 +30,19 @@ import org.springframework.util.Assert; * @author Eric Zhao */ public class SentinelCircuitBreakerFactory extends - CircuitBreakerFactory { + CircuitBreakerFactory { private Function defaultConfiguration = id -> new SentinelConfigBuilder() - .resourceName(id).rules(new ArrayList<>()).build(); + .resourceName(id) + .entryType(EntryType.OUT) + .rules(new ArrayList<>()) + .build(); @Override public CircuitBreaker create(String id) { Assert.hasText(id, "A CircuitBreaker must have an id."); SentinelConfigBuilder.SentinelCircuitBreakerConfiguration conf = getConfigurations() - .computeIfAbsent(id, defaultConfiguration); + .computeIfAbsent(id, defaultConfiguration); return new SentinelCircuitBreaker(id, conf.getEntryType(), conf.getRules()); } @@ -48,7 +53,7 @@ public class SentinelCircuitBreakerFactory extends @Override public void configureDefault( - Function defaultConfiguration) { + Function defaultConfiguration) { this.defaultConfiguration = defaultConfiguration; } diff --git a/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerTest.java b/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerTest.java index ae76c04..0e66998 100644 --- a/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerTest.java +++ b/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerTest.java @@ -17,7 +17,9 @@ package org.springframework.cloud.circuitbreaker.sentinel; import java.util.Arrays; +import java.util.Collections; +import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; import org.junit.Test; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -31,6 +33,14 @@ import static org.assertj.core.api.Assertions.assertThat; */ public class ReactiveSentinelCircuitBreakerTest { + @Test + public void testCreateWithNullRule() { + String id = "testCreateReactiveCbWithNullRule"; + ReactiveSentinelCircuitBreaker cb = new ReactiveSentinelCircuitBreaker(id, Collections.singletonList(null)); + assertThat(cb.run(Mono.just("foobar")).block()).isEqualTo("foobar"); + assertThat(DegradeRuleManager.hasConfig(id)).isFalse(); + } + @Test public void runMono() { ReactiveCircuitBreaker cb = new ReactiveSentinelCircuitBreakerFactory() diff --git a/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerTest.java b/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerTest.java index 1e470a2..4f436fb 100644 --- a/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerTest.java +++ b/spring-cloud-circuitbreaker-sentinel/src/test/java/org/springframework/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerTest.java @@ -43,19 +43,27 @@ public class SentinelCircuitBreakerTest { public void testCreateDirectlyThenRun() { // Create a circuit breaker without any circuit breaking rules. CircuitBreaker cb = new SentinelCircuitBreaker( - "testSentinelCreateDirectlyThenRunA"); + "testSentinelCreateDirectlyThenRunA"); assertThat(cb.run(() -> "Sentinel")).isEqualTo("Sentinel"); assertThat(DegradeRuleManager.hasConfig("testSentinelCreateDirectlyThenRunA")) - .isFalse(); + .isFalse(); CircuitBreaker cb2 = new SentinelCircuitBreaker( - "testSentinelCreateDirectlyThenRunB", - Collections.singletonList( - new DegradeRule("testSentinelCreateDirectlyThenRunB") - .setCount(100).setTimeWindow(10))); + "testSentinelCreateDirectlyThenRunB", + Collections.singletonList( + new DegradeRule("testSentinelCreateDirectlyThenRunB") + .setCount(100).setTimeWindow(10))); assertThat(cb2.run(() -> "Sentinel")).isEqualTo("Sentinel"); assertThat(DegradeRuleManager.hasConfig("testSentinelCreateDirectlyThenRunB")) - .isTrue(); + .isTrue(); + } + + @Test + public void testCreateWithNullRule() { + String id = "testCreateCbWithNullRule"; + CircuitBreaker cb = new SentinelCircuitBreaker(id, Collections.singletonList(null)); + assertThat(cb.run(() -> "Sentinel")).isEqualTo("Sentinel"); + assertThat(DegradeRuleManager.hasConfig(id)).isFalse(); } @Test @@ -67,7 +75,7 @@ public class SentinelCircuitBreakerTest { @Test public void testRunWithFallback() { CircuitBreaker cb = new SentinelCircuitBreakerFactory() - .create("testSentinelRunWithFallback"); + .create("testSentinelRunWithFallback"); assertThat(cb.run(() -> { throw new RuntimeException("boom"); }, t -> "fallback")).isEqualTo("fallback"); From 9a6c53cb81cb7ec988c7abb718aadd68066f8e73 Mon Sep 17 00:00:00 2001 From: Eric Zhao Date: Tue, 2 Apr 2019 23:18:39 +0800 Subject: [PATCH 18/18] Fix test dependency and update Sentinel version to 1.5.1 Signed-off-by: Eric Zhao --- spring-cloud-circuitbreaker-dependencies/pom.xml | 4 ++-- spring-cloud-circuitbreaker-sentinel/pom.xml | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/spring-cloud-circuitbreaker-dependencies/pom.xml b/spring-cloud-circuitbreaker-dependencies/pom.xml index ca63ecc..b105ff3 100644 --- a/spring-cloud-circuitbreaker-dependencies/pom.xml +++ b/spring-cloud-circuitbreaker-dependencies/pom.xml @@ -19,7 +19,7 @@ 0.13.1 - 1.5.0 + 1.5.1 @@ -143,4 +143,4 @@ - \ No newline at end of file + diff --git a/spring-cloud-circuitbreaker-sentinel/pom.xml b/spring-cloud-circuitbreaker-sentinel/pom.xml index eb3cae7..b5de5b1 100644 --- a/spring-cloud-circuitbreaker-sentinel/pom.xml +++ b/spring-cloud-circuitbreaker-sentinel/pom.xml @@ -48,6 +48,7 @@ io.projectreactor reactor-test + test