Ryan Baxter
5 years ago
10 changed files with 383 additions and 1 deletions
@ -0,0 +1,82 @@
@@ -0,0 +1,82 @@
|
||||
== Introduction |
||||
|
||||
Spring Cloud Circuit breaker provides an abstraction across different circuit breaker implementations. |
||||
It provides a consistent API to use in your applications allowing you the developer to choose the circuit breaker implementation that best fits your needs for your app. |
||||
|
||||
=== Supported Implementations |
||||
|
||||
* https://github.com/Netflix/Hystrix[Netfix Hystrix] |
||||
* https://github.com/resilience4j/resilience4j[Resilience4J] |
||||
* https://github.com/alibaba/Sentinel[Sentinel] |
||||
* https://github.com/spring-projects/spring-retry[Spring Retry] |
||||
|
||||
== Core Concepts |
||||
|
||||
To create a circuit breaker in your code you can use the `CircuitBreakerFactory` API. When you include a Spring Cloud Circuit Breaker starter on your classpath a bean implementing this API will automatically be created for you. |
||||
A very simple example of using this API is given below |
||||
|
||||
==== |
||||
[source,java] |
||||
---- |
||||
@Service |
||||
public static class DemoControllerService { |
||||
private RestTemplate rest; |
||||
private CircuitBreakerFactory cbFactory; |
||||
|
||||
public DemoControllerService(RestTemplate rest, CircuitBreakerFactory cbFactory) { |
||||
this.rest = rest; |
||||
this.cbFactory = cbFactory; |
||||
} |
||||
|
||||
public String slow() { |
||||
return cbFactory.create("slow").run(() -> rest.getForObject("/slow", String.class), throwable -> "fallback"); |
||||
} |
||||
|
||||
} |
||||
---- |
||||
==== |
||||
|
||||
The `CircuitBreakerFactory.create` API will create an instance of a class called `CircuitBreaker`. |
||||
The `run` method takes a `Supplier` and a `Function`. |
||||
The `Supplier` is the code that you are going to wrap in a circuit breaker. |
||||
The `Function` is the fallback that will be executed if the circuit breaker is tripped. |
||||
The function will be passed the `Throwable` that caused the fallback to be triggered. |
||||
You can optionally exclude the fallback if you do not want to provide one. |
||||
|
||||
=== Circuit Breakers In Reactive Code |
||||
|
||||
If Project Reactor is on the class path then you can also use `ReactiveCircuitBreakerFactory` for your reactive code. |
||||
|
||||
==== |
||||
[source,java] |
||||
---- |
||||
@Service |
||||
public static class DemoControllerService { |
||||
private ReactiveCircuitBreakerFactory cbFactory; |
||||
private WebClient webClient; |
||||
|
||||
|
||||
public DemoControllerService(WebClient webClient, ReactiveCircuitBreakerFactory cbFactory) { |
||||
this.webClient = webClient; |
||||
this.cbFactory = cbFactory; |
||||
} |
||||
|
||||
public Mono<String> slow() { |
||||
return webClient.get().uri("/slow").retrieve().bodyToMono(String.class).transform( |
||||
it -> cbFactory.create("slow").run(it, throwable -> return Mono.just("fallback"))); |
||||
} |
||||
} |
||||
---- |
||||
==== |
||||
|
||||
The `ReactiveCircuitBreakerFactory.create` API will create an instance of a class called `ReactiveCircuitBreaker`. |
||||
The `run` method takes with a `Mono` or `Flux` and wraps it in a circuit breaker. |
||||
You can optionally profile a fallback `Function` which will be called if the circuit breaker is tripped and will be passed the `Throwable` |
||||
that caused the failure. |
||||
|
||||
== Configuration |
||||
|
||||
You can configure your circuit breakers using by creating beans of type `Customizer`. |
||||
The `Customizer` interface has a single method called `customize` that takes in the `Object` to customize. |
||||
|
||||
// TODO link to implementation docs |
@ -0,0 +1,68 @@
@@ -0,0 +1,68 @@
|
||||
/* |
||||
* 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 |
||||
* |
||||
* 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, |
||||
* 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.client.circuitbreaker; |
||||
|
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
import java.util.function.Consumer; |
||||
import java.util.function.Function; |
||||
|
||||
/** |
||||
* Base class for factories which produce circuit breakers. |
||||
* |
||||
* @author Ryan Baxter |
||||
*/ |
||||
public abstract class AbstractCircuitBreakerFactory<CONF, CONFB extends ConfigBuilder<CONF>> { |
||||
|
||||
private final ConcurrentHashMap<String, CONF> configurations = new ConcurrentHashMap<>(); |
||||
|
||||
/** |
||||
* Adds configurations for circuit breakers. |
||||
* @param ids The id of the circuit breaker |
||||
* @param consumer A configuration builder consumer, allows consumers to customize the |
||||
* builder before the configuration is built |
||||
*/ |
||||
public void configure(Consumer<CONFB> consumer, String... ids) { |
||||
for (String id : ids) { |
||||
CONFB builder = configBuilder(id); |
||||
consumer.accept(builder); |
||||
CONF conf = builder.build(); |
||||
getConfigurations().put(id, conf); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Gets the configurations for the circuit breakers. |
||||
* @return The configurations |
||||
*/ |
||||
protected ConcurrentHashMap<String, CONF> getConfigurations() { |
||||
return configurations; |
||||
} |
||||
|
||||
/** |
||||
* Creates a configuration builder for the given id. |
||||
* @param id The id of the circuit breaker |
||||
* @return The configuration builder |
||||
*/ |
||||
protected abstract CONFB configBuilder(String id); |
||||
|
||||
/** |
||||
* Sets the default configuration for circuit breakers. |
||||
* @param defaultConfiguration A function that returns the default configuration |
||||
*/ |
||||
public abstract void configureDefault(Function<String, CONF> defaultConfiguration); |
||||
|
||||
} |
@ -0,0 +1,37 @@
@@ -0,0 +1,37 @@
|
||||
/* |
||||
* 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 |
||||
* |
||||
* 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, |
||||
* 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.client.circuitbreaker; |
||||
|
||||
import java.util.function.Function; |
||||
import java.util.function.Supplier; |
||||
|
||||
/** |
||||
* Spring Cloud circuit breaker. |
||||
* |
||||
* @author Ryan Baxter |
||||
*/ |
||||
public interface CircuitBreaker { |
||||
|
||||
default <T> T run(Supplier<T> toRun) { |
||||
return run(toRun, throwable -> { |
||||
throw new NoFallbackAvailableException("No fallback available.", throwable); |
||||
}); |
||||
}; |
||||
|
||||
<T> T run(Supplier<T> toRun, Function<Throwable, T> fallback); |
||||
|
||||
} |
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
/* |
||||
* 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 |
||||
* |
||||
* 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, |
||||
* 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.client.circuitbreaker; |
||||
|
||||
/** |
||||
* Creates circuit breakers based on the underlying implementation. |
||||
* |
||||
* @author Ryan Baxter |
||||
*/ |
||||
public abstract class CircuitBreakerFactory<CONF, CONFB extends ConfigBuilder<CONF>> |
||||
extends AbstractCircuitBreakerFactory<CONF, CONFB> { |
||||
|
||||
public abstract CircuitBreaker create(String id); |
||||
|
||||
} |
@ -0,0 +1,28 @@
@@ -0,0 +1,28 @@
|
||||
/* |
||||
* 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 |
||||
* |
||||
* 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, |
||||
* 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.client.circuitbreaker; |
||||
|
||||
/** |
||||
* A builder for circuit breaker configurations. |
||||
* |
||||
* @author Ryan Baxter |
||||
*/ |
||||
public interface ConfigBuilder<CONF> { |
||||
|
||||
CONF build(); |
||||
|
||||
} |
@ -0,0 +1,28 @@
@@ -0,0 +1,28 @@
|
||||
/* |
||||
* 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 |
||||
* |
||||
* 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, |
||||
* 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.client.circuitbreaker; |
||||
|
||||
/** |
||||
* Customizes the parameterized class. |
||||
* |
||||
* @author Ryan Baxter |
||||
*/ |
||||
public interface Customizer<TOCUSTOMIZE> { |
||||
|
||||
void customize(TOCUSTOMIZE tocustomize); |
||||
|
||||
} |
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
/* |
||||
* 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 |
||||
* |
||||
* 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, |
||||
* 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.client.circuitbreaker; |
||||
|
||||
/** |
||||
* A runtime exception that tells no fallback is available for the circuit breaker. |
||||
* |
||||
* @author Toshiaki Maki |
||||
*/ |
||||
public class NoFallbackAvailableException extends RuntimeException { |
||||
|
||||
public NoFallbackAvailableException(String message, Throwable cause) { |
||||
super(message, cause); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,47 @@
@@ -0,0 +1,47 @@
|
||||
/* |
||||
* 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 |
||||
* |
||||
* 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, |
||||
* 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.client.circuitbreaker; |
||||
|
||||
import java.util.function.Function; |
||||
|
||||
import reactor.core.publisher.Flux; |
||||
import reactor.core.publisher.Mono; |
||||
|
||||
/** |
||||
* Spring Cloud reactive circuit breaker API. |
||||
* |
||||
* @author Ryan Baxter |
||||
*/ |
||||
public interface ReactiveCircuitBreaker { |
||||
|
||||
default <T> Mono<T> run(Mono<T> toRun) { |
||||
return run(toRun, throwable -> { |
||||
throw new NoFallbackAvailableException("No fallback available.", throwable); |
||||
}); |
||||
} |
||||
|
||||
<T> Mono<T> run(Mono<T> toRun, Function<Throwable, Mono<T>> fallback); |
||||
|
||||
default <T> Flux<T> run(Flux<T> toRun) { |
||||
return run(toRun, throwable -> { |
||||
throw new NoFallbackAvailableException("No fallback available.", throwable); |
||||
}); |
||||
} |
||||
|
||||
<T> Flux<T> run(Flux<T> toRun, Function<Throwable, Flux<T>> fallback); |
||||
|
||||
} |
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
/* |
||||
* 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 |
||||
* |
||||
* 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, |
||||
* 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.client.circuitbreaker; |
||||
|
||||
/** |
||||
* Creates reactive circuit breakers. |
||||
* |
||||
* @author Ryan Baxter |
||||
*/ |
||||
public abstract class ReactiveCircuitBreakerFactory<CONF, CONFB extends ConfigBuilder<CONF>> |
||||
extends AbstractCircuitBreakerFactory<CONF, CONFB> { |
||||
|
||||
public abstract ReactiveCircuitBreaker create(String id); |
||||
|
||||
} |
Loading…
Reference in new issue