Browse Source

Moving common spring-cloud-circuitbreaker code to commons

pull/599/head
Ryan Baxter 5 years ago
parent
commit
d07fe7b3f5
  1. 82
      docs/src/main/asciidoc/spring-cloud-circuitbreaker.adoc
  2. 6
      docs/src/main/asciidoc/spring-cloud-commons.adoc
  3. 68
      spring-cloud-commons/src/main/java/org/springframework/cloud/client/circuitbreaker/AbstractCircuitBreakerFactory.java
  4. 37
      spring-cloud-commons/src/main/java/org/springframework/cloud/client/circuitbreaker/CircuitBreaker.java
  5. 29
      spring-cloud-commons/src/main/java/org/springframework/cloud/client/circuitbreaker/CircuitBreakerFactory.java
  6. 28
      spring-cloud-commons/src/main/java/org/springframework/cloud/client/circuitbreaker/ConfigBuilder.java
  7. 28
      spring-cloud-commons/src/main/java/org/springframework/cloud/client/circuitbreaker/Customizer.java
  8. 30
      spring-cloud-commons/src/main/java/org/springframework/cloud/client/circuitbreaker/NoFallbackAvailableException.java
  9. 47
      spring-cloud-commons/src/main/java/org/springframework/cloud/client/circuitbreaker/ReactiveCircuitBreaker.java
  10. 29
      spring-cloud-commons/src/main/java/org/springframework/cloud/client/circuitbreaker/ReactiveCircuitBreakerFactory.java

82
docs/src/main/asciidoc/spring-cloud-circuitbreaker.adoc

@ -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

6
docs/src/main/asciidoc/spring-cloud-commons.adoc

@ -767,4 +767,8 @@ If you want to learn more about the Spring Cloud Release train compatibility, yo @@ -767,4 +767,8 @@ If you want to learn more about the Spring Cloud Release train compatibility, yo
In order to disable this feature, set `spring.cloud.compatibility-verifier.enabled` to `false`.
If you want to override the compatible Spring Boot versions, just set the
`spring.cloud.compatibility-verifier.compatible-boot-versions` property with a comma separated list
of compatible Spring Boot versions.
of compatible Spring Boot versions.
== Spring Cloud Circuit Breaker
include::spring-cloud-circuitbreaker.adoc[]

68
spring-cloud-commons/src/main/java/org/springframework/cloud/client/circuitbreaker/AbstractCircuitBreakerFactory.java

@ -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);
}

37
spring-cloud-commons/src/main/java/org/springframework/cloud/client/circuitbreaker/CircuitBreaker.java

@ -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);
}

29
spring-cloud-commons/src/main/java/org/springframework/cloud/client/circuitbreaker/CircuitBreakerFactory.java

@ -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);
}

28
spring-cloud-commons/src/main/java/org/springframework/cloud/client/circuitbreaker/ConfigBuilder.java

@ -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();
}

28
spring-cloud-commons/src/main/java/org/springframework/cloud/client/circuitbreaker/Customizer.java

@ -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);
}

30
spring-cloud-commons/src/main/java/org/springframework/cloud/client/circuitbreaker/NoFallbackAvailableException.java

@ -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);
}
}

47
spring-cloud-commons/src/main/java/org/springframework/cloud/client/circuitbreaker/ReactiveCircuitBreaker.java

@ -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);
}

29
spring-cloud-commons/src/main/java/org/springframework/cloud/client/circuitbreaker/ReactiveCircuitBreakerFactory.java

@ -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…
Cancel
Save