Code Monkey home page Code Monkey logo

spring-cloud-circuitbreaker's Introduction

Spring Cloud Connectors

Spring Cloud Connectors provides a simple abstraction that JVM-based applications can use to discover information about the cloud environment on which they are running, connect to services, and have discovered services registered as Spring beans. It provides out-of-the-box support for discovering common services on Heroku and Cloud Foundry cloud platforms, and it supports custom service definitions through Java Service Provider Interfaces (SPI).

Note
This project is in maintenance mode, in favor of the newer Java CFEnv project. We will continue to release security-related updates but will not address enhancement requests.

Learn more

Build

The project is built with Gradle. The Gradle wrapper allows you to build the project on multiple platforms and even if you do not have Gradle installed; run it in place of the gradle command (as ./gradlew) from the root of the main project directory.

To compile the project and run tests

./gradlew build

To build a JAR

./gradlew jar

To generate Javadoc API documentation

./gradlew api

To list all available tasks

./gradlew tasks

Contributing

Spring Cloud is released under the non-restrictive Apache 2.0 license, and follows a very standard Github development process, using Github tracker for issues and merging pull requests into master. If you want to contribute even something trivial please do not hesitate, but follow the guidelines below.

Sign the Contributor License Agreement

Before we accept a non-trivial patch or pull request we will need you to sign the Contributor License Agreement. Signing the contributor’s agreement does not grant anyone commit rights to the main repository, but it does mean that we can accept your contributions, and you will get an author credit if we do. Active contributors might be asked to join the core team, and given the ability to merge pull requests.

Code of Conduct

This project adheres to the Contributor Covenant code of conduct. By participating, you are expected to uphold this code. Please report unacceptable behavior to [email protected].

Code Conventions and Housekeeping

None of these is essential for a pull request, but they will all help. They can also be added after the original pull request but before a merge.

  • Use the Spring Framework code format conventions. If you use Eclipse you can import formatter settings using the eclipse-code-formatter.xml file from the Spring Cloud Build project. If using IntelliJ, you can use the 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 for.

  • Add the ASF license header comment to all new .java files (copy from existing files in the project)

  • Add yourself as an @author to the .java files that you modify substantially (more than cosmetic changes).

  • Add some Javadocs and, if you change the namespace, some XSD doc elements.

  • 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 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).

spring-cloud-circuitbreaker's People

Contributors

ctlove0523 avatar dependabot-preview[bot] avatar dependabot[bot] avatar dowenliu-xyz avatar ebussieres avatar giger85 avatar ian4hu avatar imyzt avatar making avatar marcingrzejszczak avatar mistborn94 avatar olgamaciaszek avatar r1cm3d avatar rajatarora08 avatar rodbate avatar ryanjbaxter avatar sczyh30 avatar spencergibb avatar spring-builds avatar spring-operator avatar srinivasa-vasu avatar thomasvitale avatar wind57 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

spring-cloud-circuitbreaker's Issues

Support integration with Sentinel

Hi, I'd like to propose to add Sentinel integration module (spring-cloud-circuitbreaker-sentinel) to spring-cloud-circuitbreaker. This includes two parts:

  1. non-reactive part: The non-reactive CircuitBreaker adapter of Sentinel has been finished. Sentinel has provided an API SphU.entry(id) and when it throws BlockException, the request is rejected, so I just wrapped the function and fallback with that API. Once I've finished the testing today, a PR will be submitted.
  2. reactive part: As for the ReactiveCircuitBreaker, currently we're working on the reactive support of Sentinel (will be released in Sentinel 1.5.0 as an adapter module sentinel-reactor-adapter). The implementation will resemble this:
public class ReactiveSentinelCircuitBreaker implements ReactiveCircuitBreaker {

    private final String resourceName;

    public ReactiveSentinelCircuitBreaker(String resourceName) {
        this.resourceName = resourceName;
    }

    @Override
    public <T> Mono<T> run(Mono<T> toRun, Function<Throwable, Mono<T>> fallback) {
        return toRun.onErrorResume(fallback)
            .transform(new SentinelReactorTransformer<>(resourceName));
    }
}

Once the Sentinel Reactor module is released, we can implement the SentinelReactiveCircuitBreaker and test it. The reactive part is expected to be ready in mid-March.

The implementation will follow the interfaces listed in common module (CircuitBreaker, CircuitBreakerFactory and ConfigBuilder).

Would you like to provide some suggestions? :)

No class org.springframework.boot.actuate.AbstractEndpoint

I'm trying to add circuit breaker to a REST template using the circuit breaker project from the Spring Cloud incubator.

I've added the dependency to my pom.xml. My parent is Spring Boot starter parent version 2.1.5.RELEASE:

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-circuitbreaker-spring-retry</artifactId>
            <version>0.0.1.BUILD-SNAPSHOT</version>
        </dependency>

I've tried both Resilience4J and SpringRetry circuit breakers for my client, but I get an exception at runtime:

java.lang.NoClassDefFoundError: org/springframework/boot/actuate/endpoint/AbstractEndpoint

I see an AbstractExposableEndpoint.class in the spring-boot-starter-actuator.jar. Does the incubator dependency have to be updated to extend this class?

Add distributed tracing support for Circuit Breakers

We would like to see distributed tracing spans for Circuit Breakers via Spring Cloud Sleuth. We have a mix of Hystrix and Resilience4J being used today. Collecting distributed traces from Circuit Breakers will add more observability to our Springboot services. Ideally, traces should be collected via the Spring Cloud Sleuth auto configurations for all supported Circuit Breaker implementations.

We have considered adding custom auto configurations for collecting traces for Hystrix and Resilience4J. But, a standard way of collecting traces that works irrespective of the underlying Circuit Breaker implementation would help.

Expose underlying Circuit Breaker implementation instance to allow for additional configuration

Is your feature request related to a problem? Please describe.
While it certainly is a perfectly defensible position that SCCB (as per its name) should only support the "CircuitBreaker" pattern - it may be more robust to allow for configuration of additional library-specific resilience patterns. For instance Resilience4j enables 7 different resilience patterns of which only CircuitBreaker and TimeLimiter are supported

Describe the solution you'd like
Would love to have a mechanism to more fully configure the underlying circuit breaker's implementation, for instance to also enable Retry.

Can't integrate with Spring Cloud Hoxton.SR3

Describe the bug
The Spring Cloud version is Hoxton.SR3. When I use resilience4j instead of hystrix, I get some error.

java.lang.IllegalStateException: Annotation @EnableCircuitBreaker found, but there are no implementations. Did you forget to include a starter?

my pom.xml:

  <dependencies>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    <dependency>
      <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
      <exclusions>
        <exclusion>
          <artifactId>spring-cloud-netflix-hystrix</artifactId>
          <groupId>org.springframework.cloud</groupId>
        </exclusion>
      </exclusions>
      <groupId>org.springframework.cloud</groupId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId>
    </dependency>
  </dependencies>

Sample
Hytrix spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.netflix.hystrix.HystrixAutoConfiguration,\
org.springframework.cloud.netflix.hystrix.HystrixCircuitBreakerAutoConfiguration,\
org.springframework.cloud.netflix.hystrix.ReactiveHystrixCircuitBreakerAutoConfiguration,\
org.springframework.cloud.netflix.hystrix.security.HystrixSecurityAutoConfiguration

org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker=\
org.springframework.cloud.netflix.hystrix.HystrixCircuitBreakerConfiguration

So I think the fix is:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.circuitbreaker.resilience4j.Resilience4JAutoConfiguration,\
org.springframework.cloud.circuitbreaker.resilience4j.ReactiveResilience4JAutoConfiguration

org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker=\
org.springframework.cloud.circuitbreaker.resilience4j.SomeConfigurationClass

checkstyle-suppressions.xml is missing

Describe the bug
Please provide details of the problem, including the version of Spring Cloud that you
are using.

https://github.com/spring-cloud/spring-cloud-circuitbreaker#251-intellij-idea

2.5. IDE setup

...
...

checkstyle.additional.suppressions.file - this variable corresponds to suppressions in your local project. E.g. you’re working on spring-cloud-contract. Then point to the project-root/src/checkstyle/checkstyle-suppressions.xml folder. Example for spring-cloud-contract would be: /home/username/spring-cloud-contract/src/checkstyle/checkstyle-suppressions.xml.

The document above indicates to specify checkstyle-suppressions.xml but I could not find the file in spring-cloud-circuitbreaker.

$ pwd
/Users/akihito.nakano/src/github.com/spring-cloud/spring-cloud-circuitbreaker

$ git ls-files | grep checkstyle

Proceeding the configuration without checkstyle-suppressions.xml, I got the error.

image

Spring Cloud CircuitBreaker Release

Hi,
We are very interested on including spring cloud circuit breaker as part of our developments, do you have an estimate about when it can be generally available?
Thanks

Resilience4j circuit breaker factory uses single threaded executor

When using a Resilience4J circuit breaker configured with a timeout I've noticed that if the call to the managed method takes a long time to complete then the request times out as expected but subsequent calls will also time out until the original long running request completes, which was not expected.

This was seen when using a Resilience4JCircuitBreakerFactory to configure a circuit breaker as shown below. A timeout of 2 seconds was specified for the circuit breaker. Not shown below, the method managed/wrapped by the circuit breaker myMethod() can be made to sleep for a configurable amount of time in order to simulate a very slow operation.

    . . .

    @Autowired
    private final CircuitBreakerFactory cbFactory;

    @Bean
    public Customizer<Resilience4JCircuitBreakerFactory> myCBCustomizer() {
        return factory -> factory
                .configure(
                        builder -> builder
                                .circuitBreakerConfig(CircuitBreakerConfig.ofDefaults())
                                .timeLimiterConfig(custom().timeoutDuration(ofMillis(2000)).build())
                                .build(),
                        “myCB”);
    }

    @GetMapping(“/call”)
    public String myHandler() {
        return cbFactory
                .create(“myCB”)
                .run(() -> myMethod(), throwable -> “Fallback response”);
    }

If, when the @GetMapping handler is first called, it is arranged for the execution of myMethod() to take 10 seconds then the circuit breaker’s timeout of 2 seconds kicks in and the caller gets the “Fallback response” which is great. However, if a new request is immediately sent to the @GetMapping handler then the upstream caller also sees a 2 second wait before receiving the “Fallback response” and the managed method myMethod() doesn’t seem to be invoked. This keeps happening for all sent requests until 10 seconds have expired since the first call was made. After that the circuit breaker appears to start letting calls through to myMethod() once again.

If the above is repeated but the first call to myMethod() is made to have a 30 seconds delay then the same behaviour occurs but now all subsequent requests time out with the fallback response until 30 seconds have expired since the first slow request. It looks as if the first request sent to the (deliberately) very slow method appears to block all subsequent requests until the first request eventually completes.

The only thing I can see that might explain this behaviour is the use of a single thread executor service in the Resilience4JCircuitBreakerFactory. The Javadoc for that method states that it creates an ExecutorService that “uses a single worker thread operating off an unbounded queue” and that “no more than one task will be active at any given time.”

What I believe I’m seeing is the very slow first request described above time out from the caller’s perspective but then actually remain running on the executor service’s single worker thread until it eventually completes (10 seconds or 30 seconds later in the above description). All requests that arrive at the circuit breaker’s executor service over that time get queued but never get the chance to actually execute since the circuit breaker times them out.

Changing the choice of executor service in Resilience4JCircuitBreakerFactory to be something other than single threaded appears to sort things out and provide what I assume is the expected behaviour. Using a cached thread pool alternative seems to work but there are other options.

Will supply a failing test and a modified Resilience4JCircuitBreakerFactory for your consideration in a follow-up PR.

Using CircuitBreaker in Spring Cloud Gateway overrides route timeout properties

I am using Spring Cloud Gateway, based on Hoxton.SR3.

When I use the metadata timeout settings to manage my connections and then add a circuit breaker filter, the timeout value set in metadata is overridden by the default timeout use in the resilience4j TimeLimiter (1s).

Here's my route config:

        - id: test_route
          uri: http://localhost:8992
          predicates:
            - Host=testsvc
          filters:
            - CircuitBreaker=pocCircuitBreaker
          metadata:
            response-timeout: 2000

My test service simple sleeps for 2500ms, so I expect a timeout after 2s. Instead the request times out after only 1s.

I have figured out a workaround by setting the TimeLimiter to a ridiculously large value, in which case the route response-timeout triggers first, but I don't know if that will be reliable as I will need to support several different circuit breaker/timeout configurations.

    @Bean
    public Customizer<ReactiveResilience4JCircuitBreakerFactory> defaultCustomizer() {
        return factory -> factory.configureDefault(id -> new Resilience4JConfigBuilder(id)
            .circuitBreakerConfig(CircuitBreakerConfig.custom()
                .slidingWindow(50, 50, CircuitBreakerConfig.SlidingWindowType.COUNT_BASED)
                .build())
            .timeLimiterConfig(TimeLimiterConfig.custom()
                .timeoutDuration(Duration.ofMinutes(5L)) 
                .cancelRunningFuture(false)
                .build())
            .build());
    }

Is there any way to completely suppress the TimeLimiter so I don't have to worry about this? I've tried omitting it from the above Customizer, but then the 1s default kicked in.

Support resilience4j retry module [spring-cloud-circuitbreaker-resilience4j]

Describe the bug
Please add a possibility to configure and support of resilience4j retry https://resilience4j.readme.io/docs/retry

There is a problem in the case of using together Spring Cloud Gateway 'retry' and resilience4j 'fallback'.

Sample
Using spring-cloud-circuitbreaker-resilience4j with Spring Cloud Gateway.
If resilience4j fallback is configured it breaks Gateway 'retry'.
Without fallback, retry works well.
Simple application:

@SpringBootApplication
@EnableDiscoveryClient
public class DemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}
	
	@Bean
	public RouteLocator testRouteLocator(final RouteLocatorBuilder routeLocatorBuilder) {
		return routeLocatorBuilder.routes()
				.route("test Route", p -> p.path("/test-route")
						.filters(f -> f.rewritePath("/test-route", "/v1/test-route")
								.retry(3)
								.circuitBreaker(c -> c.setName("testCircuitBreaker")
										.setFallbackUri("forward:/fallback/test")
								)
						)
						.uri("lb://test-service")).build();
	}
}
// .. endpoint @RequestMapping("/fallback/test")

In this example, retry(3) does not work.

'springCloudVersion', "Hoxton.SR1"
'org.springframework.cloud:spring-cloud-starter-gateway'
'org.springframework.cloud:spring-cloud-starter-circuitbreaker-reactor-resilience4j'

Use resilience4j-bom for dependency management

Is your feature request related to a problem? Please describe.
Currently spring-cloud-circuitbreaker-dependencies only provides dependency management for a couple of resilience4j artifacts.

Describe the solution you'd like
With resilience4j 1.5.0 a resilience4j-bom was published, which provides dependency management for all resilience4j artifacts: resilience4j/resilience4j#310

It would be good to import this BOM instead of providing dependency management for only a couple of resilience4j artifacts, so any other resilience4j artifacts in a project will be managed with the sam version.

Provide a monitoring interface for circuit-breakers

To be able to monitor the circuit breakers effectively it would be good to expose their state (closed, open, half-open) as of Spring Actuator endpoints without additional effort.

Monitoring the state of circuit breakers would allow discovering that a upstream dependency suddenly becomes unavailable. It is essential for applications used in production.

Spring Cloud Sleuth Tracing info not passing to downstream services when using spring-cloud-circuitbreaker with resilience4j

I have microservices setup using SpringBoot and I have distributed tracing setup using SpringCloud Sleuth and Zipkin and the tracing is working as expected.

However, when I start using Spring Cloud CircuitBreaker while calling the downstream services using RestTemplate then tracing is broken ie the parent traceId is not passed to downstream service.

cbFactory.create("getProductById").run(() -> restTemplate.getForObject(catalogSvcUrl+"api/products/"+id, Product.class))

But if I don't apply CircuitBreaker then Slueth tracing is working fine.

restTemplate.getForObject(catalogSvcUrl+"api/products/"+id, Product.class)) //this is working fine.

Is there any way to make the sleuth tracing info (headers) pass to downstream services while using Spring Cloud CurcuitBreaker?

Event Consumer executing multiple times for same event

My code for CircuitBreaker setup:

@Bean
    public Customizer<ReactiveResilience4JCircuitBreakerFactory> slowCusomtizer(
            @Qualifier("cbConfigRegistry") ConcurrentMap<String, CircuitBreakerConfig> registry,
            @Qualifier("defaultCBConfig") CircuitBreakerConfig defaultConfig,
            GatewayProperties gatewayProperties
    ) {
        return factory -> {
            Set<String> requiredCBs = gatewayProperties.getRoutes().stream()
                    .flatMap(e -> e.getFilters().stream()
                            .filter(x -> x.getName().equals("CircuitBreaker"))
                            .map(x -> x.getArgs().get("_genkey_0")))
                    .collect(Collectors.toSet());
            requiredCBs.forEach(entry -> {
                CircuitBreakerConfig config = registry.getOrDefault(entry, defaultConfig);
                factory.configure(builder -> builder
                        .timeLimiterConfig(TimeLimiterConfig.custom().timeoutDuration(Duration.ofSeconds(2)).build())
                        .circuitBreakerConfig(config), entry);
                factory.addCircuitBreakerCustomizer(circuitBreaker -> circuitBreaker.getEventPublisher()
                        .onSuccess(event -> {
                            LOGGER.info("CB : {} Event:{}", event.getCircuitBreakerName(), event.getEventType());
                        }), entry);
            });

        };
    }

Logs:

First Request :

2020-05-03 03:09:56.142  INFO 24720 --- [ctor-http-nio-5] com.meesho.edgeproxy.configs.CBConfig    : CB : qwest::cb1 Event:SUCCESS

Second Request

2020-05-03 03:11:14.419  INFO 24720 --- [ctor-http-nio-7] com.meesho.edgeproxy.configs.CBConfig    : CB : qwest::cb1 Event:SUCCESS
2020-05-03 03:11:14.419  INFO 24720 --- [ctor-http-nio-7] com.meesho.edgeproxy.configs.CBConfig    : CB : qwest::cb1 Event:SUCCESS

Third Request

2020-05-03 03:12:14.236  INFO 24720 --- [ctor-http-nio-7] com.meesho.edgeproxy.configs.CBConfig    : CB : qwest::cb1 Event:SUCCESS
2020-05-03 03:12:14.236  INFO 24720 --- [ctor-http-nio-7] com.meesho.edgeproxy.configs.CBConfig    : CB : qwest::cb1 Event:SUCCESS
2020-05-03 03:12:14.236  INFO 24720 --- [ctor-http-nio-7] com.meesho.edgeproxy.configs.CBConfig    : CB : qwest::cb1 Event:SUCCESS

I am not sure, if I am missing something or it is some kind of bug.

Dependency:

<groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId>
  <version>1.0.2.RELEASE</version>

Problems with factory initialisation order in bean resolution

Updating a code example from Hystrix to Spring Cloud Circuit Breaker using Resilience4J.
It did not work, at first.
After couple of hours of debugging, managed to find a (ugly) workaround.
Not sure if this is a bug, or intended behaviour. But, in this latter case, the examples and documentation should be improved to avoid others like me having the same issue.

Code snippets in Kotlin. Full code example can be found here

Using Spring Cloud Hoxton.RELEASE.

Assume a custom default configuration, defined in a @SpringBootApplication

    @Bean
    fun globalCustomConfiguration(): Customizer<Resilience4JCircuitBreakerFactory> {

Now, injecting a factory in a Rest controller:

@RestController
class YRest(private val circuitBreakerFactory : Resilience4JCircuitBreakerFactory){ 

      private  var cb : CircuitBreaker? =null

to instantiate the CircuitBreaker cb only once, I thought I could do something like:

   @PostConstruct
    fun init(){
        cb = circuitBreakerFactory.create("circuitBreakerToX")
    }

Unfortunately, that does not work, as by the time it is called, globalCustomConfiguration has not even been instantiated.
Adding something like @DependsOn("globalCustomConfiguration") did not help either.

However, the workaround was, before calling cb.run, to instantiate it if null, ie.:

if (cb == null)
            cb = circuitBreakerFactory.create("circuitBreakerToX")

cb!!.run //...

Add Failsafe

There is another Failure handling and resilience patterns for the JVM - Failsafe, I would like to help to make a implementation based on it.

Creating circuit breakers in advance

Hi,

All of the demo code and documentation examples favour creating circuit breakers every time the protected method is called. That feels like it might not be efficient and earlier this year there seemed to be an admission that it is not the best approach.

Creating circuit breakers in advance seems to work fine but I've found that trying to configure them using Customizer beans has no effect. That appears to be because Customizer beans update the circuit breaker factory in auto-configuration code that runs after the circuit breaker factory has been used to create circuit breakers in the constructors of other components. The only way I've found to configure circuit breakers created in advance of any method calls is to provide a custom CircuitBreakerFactory bean that includes the desired customisations. Here's an example where the circuit breaker factory's defaults are configured along with some custom set-up for a particular circuit breaker named "myCircuitBreaker" that is created elsewhere (in the constructor of the bean that uses it):

    @Bean
    public CircuitBreakerFactory circuitBreakerFactory() {
        Resilience4JCircuitBreakerFactory factory = new Resilience4JCircuitBreakerFactory();

        factory.configureDefault(id -> new Resilience4JConfigBuilder(id)
                .circuitBreakerConfig(
                        CircuitBreakerConfig.custom()
                                .failureRateThreshold(50)
                                .waitDurationInOpenState(ofMillis(10000))
                                .slidingWindow(20, 20, COUNT_BASED)
                                .build())
                .timeLimiterConfig(
                        TimeLimiterConfig.custom()
                                .timeoutDuration(ofMillis(5000))
                                .build())
                .build());

        factory.configure(configBuilder -> configBuilder
                        .circuitBreakerConfig(
                                CircuitBreakerConfig.custom()
                                        .failureRateThreshold(33)
                                        .waitDurationInOpenState(ofMillis(5000))
                                        .slidingWindow(10, 10, COUNT_BASED)
                                        .build())
                        .timeLimiterConfig(
                                TimeLimiterConfig.custom()
                                        .timeoutDuration(ofMillis(2000))
                                        .build())
                        .build(),
                "myCircuitBreaker");

        return factory;
    }

Are there any guidelines or recommendations about whether it is better to create circuit breakers inside every method call or in advance? If creation in advance is supported then is it a bug that Customizer beans appears to have no effect on circuit breakers unless they are created in every method call - or is it just an omission in the documentation and examples?

Update to latest resilience4j 1.5.0

Describe the bug
can you please update resilience4j from 1.3.1 to 1.4.0 before introducing the new release of spring cloud circuit breaker ?

Add an option to integrate with micrometer out of the box

if I didn't do sth wrong then currently we need to pass quite a few setup for micrometer and resilience4j integration. It would great to have an option to allow adding a customization to any circuitbreaker (regardless of the id).

This is how I worked this around ATM:

pom.xml


		<dependency>
			<groupId>io.micrometer</groupId>
			<artifactId>micrometer-registry-prometheus</artifactId>
			<version>${micrometer-registry-prometheus.version}</version>
		</dependency>
<!-- I had to manually pass the version of resilience4j -->
		<dependency>
			<groupId>io.github.resilience4j</groupId>
			<artifactId>resilience4j-micrometer</artifactId>
			<version>${resilience4j.version}</version>
		</dependency>

Configuration class

@Bean
	Customizer<Resilience4JCircuitBreakerFactory> defaultCustomizer(CircuitBreakerRegistry circuitBreakerRegistry, MeterRegistry meterRegistry) {
		return factory -> {
			factory.configureDefault(id -> new Resilience4JConfigBuilder(id)
					.timeLimiterConfig(TimeLimiterConfig.custom()
							.timeoutDuration(Duration.ofSeconds(2))
							.build())
					.circuitBreakerConfig(CircuitBreakerConfig.ofDefaults())
					.build());
			// for metrics
			factory.configureCircuitBreakerRegistry(circuitBreakerRegistry);
			// we need to allow adding those customizers regardless of the id
			factory.addCircuitBreakerCustomizer(circuitBreaker -> {
				CircuitBreakerMetrics
						.ofCircuitBreakerRegistry(circuitBreakerRegistry)
						.bindTo(meterRegistry);
			}, "verifyNewUser");
		};
	}

	@Bean
	CircuitBreakerRegistry resilience4JCircuitBreakerRegistry() {
		return CircuitBreakerRegistry.ofDefaults();
	}

Circuit breaker

circuitBreakerFactory.create("verifyNewUser")
					.run(() -> restTemplate.getForObject(uriComponentsBuilder.toUriString(),
							VerificationResult.class), throwable -> userRejected(userUuid, userAge));

addCircuitBreakerCustomizer register events in each time when method called

When you use Resilience4JCircuitBreakerFactory.addCircuitBreakerCustomizer() to customize an event, this event will be added in every call of the method.

We customize circuitBreaker each time when calling a method. But circuitBreaker is stored in circuitBreakerRegistry. so each time we add an event to this circuitBreaker.

In Resilience4j events store as map, that why it possible:
EventProcessor

Unit test that shows defect:
defectTwoSlowCircuitBreakerConsumerShouldBeCalledTwoTimesButCalledThreeTimes

Unable to access resilience4j metrics via actuator.

I am unable to access resilience4j metrics in my spring boot project via actuator .
I have added the following dependencies

              `<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
		<version>1.0.4.RELEASE</version>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-actuator</artifactId>
		<version>2.3.5.RELEASE</version>
	</dependency>
	<dependency>
		<groupId>io.github.resilience4j</groupId>
		<artifactId>resilience4j-micrometer</artifactId>
		<version>1.6.1</version>
	</dependency>
	<dependency>
		<groupId>io.github.resilience4j</groupId>
		<artifactId>resilience4j-circuitbreaker</artifactId>
		<version>1.6.1</version>
	</dependency>`

ReactiveResilience4JCircuitBreakerFactory not found

During app startup, the following exception is thrown :

2020-09-16 10:11:01.663  WARN 12516 --- [           main] onfigReactiveWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'xxxxxx' defined in class path resource [xxxxxxxx/ResilienceConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.cloud.gateway.route.RouteLocator]: Factory method 'xxxxxxx' threw exception; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.cloud.gateway.filter.factory.SpringCloudCircuitBreakerFilterFactory' available: There needs to be a circuit breaker implementation on the classpath that supports reactive APIs.
2020-09-16 10:11:01.684  INFO 12516 --- [           main] ConditionEvaluationReportLoggingListener : 

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2020-09-16 10:11:01.913 ERROR 12516 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

Method routeLocator in xxxxxxxxx required a bean of type 'org.springframework.cloud.gateway.filter.factory.SpringCloudCircuitBreakerFilterFactory' that could not be found.

The following candidates were found but could not be injected:
	- Bean method 'springCloudCircuitBreakerHystrixFilterFactory' in 'GatewayHystrixCircuitBreakerAutoConfiguration' not loaded because @ConditionalOnClass did not find required class 'org.springframework.cloud.netflix.hystrix.HystrixCircuitBreakerAutoConfiguration'
	- Bean method 'springCloudCircuitBreakerResilience4JFilterFactory' in 'GatewayResilience4JCircuitBreakerAutoConfiguration' not loaded because @ConditionalOnBean (types: org.springframework.cloud.circuitbreaker.resilience4j.ReactiveResilience4JCircuitBreakerFactory; SearchStrategy: all) did not find any beans of type org.springframework.cloud.circuitbreaker.resilience4j.ReactiveResilience4JCircuitBreakerFactory


Action:

Consider revisiting the entries above or defining a bean of type 'org.springframework.cloud.gateway.filter.factory.SpringCloudCircuitBreakerFilterFactory' in your configuration.


Process finished with exit code 1

my configuration beans (inside of a class annotated with @configuration):

    @Bean("config")
    public Customizer<ReactiveResilience4JCircuitBreakerFactory> defaultCustomizer() {

        return factory -> factory.configureDefault(id -> new Resilience4JConfigBuilder(id)                
                .circuitBreakerConfig(  CircuitBreakerConfig
                                        .custom()
                                        .minimumNumberOfCalls(1)
                                        .slidingWindowType(SlidingWindowType.COUNT_BASED)
                                        .slidingWindowSize(1)
                                        .waitDurationInOpenState(Duration.ofMillis(100))
                                        .slowCallDurationThreshold(Duration.ofMinutes(1))
                                        .slowCallRateThreshold(1f)
                                        .failureRateThreshold(1f)
                        .build())
                .build());
    }

    @Bean
    public DiscoveryClientRouteDefinitionLocator
    discoveryClientRouteLocator(ReactiveDiscoveryClient discoveryClient, DiscoveryLocatorProperties props) {
        return new DiscoveryClientRouteDefinitionLocator(discoveryClient, props);
    }

    @Bean
    RouteLocator routeLocator(RouteLocatorBuilder rlb)
    {
        return  rlb
                .routes()
                .route(this::getRoute).build();
    }

    private Route.AsyncBuilder getRoute(PredicateSpec spec)
    {
        return spec
                .path("/**")
                .filters(this::getFilter)
                .uri("http://no/op");    //nicht relevant
    }

    private UriSpec getFilter(GatewayFilterSpec spec)
    {
        return spec
                .circuitBreaker(config -> config.setFallbackUri("redirect:/fallback"));
    }

the majority of my POM.xml :

 <properties>
        <java.version>11</java.version>
        <spring-cloud.version>Hoxton.SR8</spring-cloud.version>
    </properties>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId>
        </dependency>
       
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

Resilience4J Configurations from application.yml aren't Supported

Description:

Application: spring-cloud-gateway:Hoxton.SR3
Circuit-Breaker version: 1.0.2.RELEASE

As far as I can tell, yaml configurations are ignored. The provided ReactiveResilience4JCircuitBreakerFactory bean uses the default CircuitBreakerRegistry which only uses the hard-coded defaults. I tried creating my own ReactiveResilience4JCircuitBreakerFactory bean which uses the CircuitBreakerRegistry from here. However, spring-cloud-circuit-breaker seems to ignore resiliency4j configurations defined for the registry. I think that is because of this logic which pulls configurations from here; but it seems like configure is never called, so that configurations map is always empty. Therefore, it always falls back to the defaults.
As a result, every CircuitBreaker is created with those defaults. Does anyone know why the circuitBreaker(id, configs) method is being used instead of one of the other methods like circuitBreaker(id) which uses the configurations set for the CircuitBreakerRegistry?

Is there some existing logic I'm missing? If not would it be possible to change the implementation to support providing resilience4J configurations from application.yml?

Annotation based Spring Cloud Circuit breaker

Is your feature request related to a problem? Please describe.
Problem: This project is amazing. However, currently, the application layer have to have code tied with the business logic to perform circuit breaker. The Spring Boot Starter Resilience4J project offers a very interesting set of annotations where methods can be annotated, and the decoration pattern will apply, making the code and understand of overall classes much clearer.

Describe the solution you'd like
A possibility to have annotations @CIRCUITBREAKER @Retry @timeout like Spring Boot Starter Resilience4J project, but for Spring-Cloud-CircuitBreaker. It is a very clean and nice feature

Describe alternatives you've considered
Well, right now, it is just a lot of code within the classes.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.