在Spring Cloud Gateway中使用Resilience4j为路由配置特定的断路器

时间:2019-11-15 14:37:05

标签: spring-cloud-gateway resilience4j

我尝试在我的spring cloud网关中配置Resilience4j,但没有成功。 我发现的只是Hystrix或纯Java。

我已将网关配置为在我的服务上传输请求,没关系。

但是无法在其上配置resilience4j。我在R4J的反应式中有很好的工件。

Resilience4j的配置在Spring Cloud API和网关中有所不同吗?

查看我的配置文件。

spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: helloworld_service
          uri: "https://localhost:8080"
          predicates:
            - Path=/helloworld/**
          filters:
            - RewritePath=/helloworld/(?<segment>.*), /$\{segment}
            - name: CircuitBreaker
              args:
                name: helloworld
      httpclient:
        ssl:
          useInsecureTrustManager: true

# RESILIENCE4J PROPERTIES
resilience4j:
  circuitbreaker:
    configs:
      default:
        #registerHealthIndicator: true
        ringBufferSizeInClosedState: 10
        ringBufferSizeInHalfOpenState: 3
        automaticTransitionFromOpenToHalfOpenEnabled: true
        waitDurationInOpenStateMillis: 2000
        failureRateThreshold: 50
        eventConsumerBufferSize: 10
    instances:
      helloworld:
        baseConfig: default
        ringBufferSizeInClosedState: 5

我的依赖项:

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

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

并生成错误:

reactor.core.Exceptions$ErrorCallbackNotImplemented: java.lang.IllegalArgumentException: Unable to find GatewayFilterFactory with name CircuitBreaker
Caused by: java.lang.IllegalArgumentException: Unable to find GatewayFilterFactory with name CircuitBreaker

非常感谢您的帮助。

3 个答案:

答案 0 :(得分:1)

当前的spring-cloud-gateway Hoxton.RELEASE自动配置存在问题。您可以通过以下配置解决该问题。

@Configuration
public class Resilience4JConfiguration {

    @Bean
    public FallbackHeadersGatewayFilterFactory fallbackHeadersGatewayFilterFactory() {
        return new FallbackHeadersGatewayFilterFactory();
    }

    @Bean
    public SpringCloudCircuitBreakerFilterFactory resilience4JCircuitBreakerFactory(
            ReactiveResilience4JCircuitBreakerFactory reactiveCircuitBreakerFactory,
            ObjectProvider<DispatcherHandler> dispatcherHandlers) {
        return new SpringCloudCircuitBreakerResilience4JFilterFactory(reactiveCircuitBreakerFactory, dispatcherHandlers);
    }

}

答案 1 :(得分:1)

感谢比拉克的耐心。

我的Resilience4j配置:

host-manager

我的application.yaml:

@Configuration
public class Resilience4JConfiguration {

    /**
     * Default Resilience4j circuit breaker configuration
     */
    @Bean
    public Customizer<ReactiveResilience4JCircuitBreakerFactory> defaultCustomizer() {
        return factory -> factory.configureDefault(id -> new Resilience4JConfigBuilder(id)
                .circuitBreakerConfig(CircuitBreakerConfig.custom().minimumNumberOfCalls(5).failureRateThreshold(20).build())
                .build());
    }

    @Bean
    public Customizer<ReactiveResilience4JCircuitBreakerFactory> helloworldCircuitBreaker(){
        return factory -> {
          factory.configure(builder -> builder.circuitBreakerConfig(CircuitBreakerConfig.ofDefaults()).build()
                  .setCircuitBreakerConfig(CircuitBreakerConfig.custom().minimumNumberOfCalls(10).failureRateThreshold(20).build())
                  , "helloworldCircuitBreaker");
        };
    }

    @Bean
    public Customizer<ReactiveResilience4JCircuitBreakerFactory> accountCircuitBreaker(){
        return factory -> {
            factory.configure(builder -> builder.circuitBreakerConfig(CircuitBreakerConfig.ofDefaults()).build(), "accountCircuitBreaker");
        };
    }

    @Bean
    public FallbackHeadersGatewayFilterFactory fallbackHeadersGatewayFilterFactory() {
        return new FallbackHeadersGatewayFilterFactory();
    }

    @Bean
    public SpringCloudCircuitBreakerFilterFactory resilience4JCircuitBreakerFactory(
            ReactiveCircuitBreakerFactory reactiveCircuitBreakerFactory,
            ObjectProvider<DispatcherHandler> dispatcherHandlers) {
        return new SpringCloudCircuitBreakerResilience4JFilterFactory(reactiveCircuitBreakerFactory, dispatcherHandlers);
    }
}

使用此配置,它将正确使用默认配置。

但是,如果我尝试调整特定的断路器,则不会使用任何配置(没有默认设置,也没有helloworldCircuitBreaker)

使用特定断路器的配置:

spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: helloworld_service
          uri: "https://localhost:8080"
          predicates:
            - Path=/helloworldservice/**
          filters:
            - CircuitBreaker

答案 2 :(得分:1)

如果要对Resiulience4j断路器使用外部配置,则需要添加以下依赖项:

<dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-starter-gateway</artifactId>
       </dependency>
       <dependency>
           <groupId>io.github.resilience4j</groupId>
           <artifactId>resilience4j-spring-boot2</artifactId>
           <version>1.1.0</version>
       </dependency>
       <dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId>
       </dependency>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-actuator</artifactId>
       </dependency>

然后在您的spring网关应用程序中,将加载的Circuitbreaker注册到您在spring cloud factory中的外部配置:

    @Bean
    public ReactiveResilience4JCircuitBreakerFactory reactiveResilience4JCircuitBreakerFactory(CircuitBreakerRegistry circuitBreakerRegistry) {
        ReactiveResilience4JCircuitBreakerFactory reactiveResilience4JCircuitBreakerFactory = new ReactiveResilience4JCircuitBreakerFactory();
        reactiveResilience4JCircuitBreakerFactory.configureCircuitBreakerRegistry(circuitBreakerRegistry);
        return reactiveResilience4JCircuitBreakerFactory;
    }

然后将其外部断路器配置添加到applciation yml文件中,例如:

esilience4j.circuitbreaker:
  configs:
    default:
      slidingWindowSize: 10
      minimumNumberOfCalls: 5
      permittedNumberOfCallsInHalfOpenState: 3
      automaticTransitionFromOpenToHalfOpenEnabled: true
      waitDurationInOpenState: 2s
      failureRateThreshold: 50
      eventConsumerBufferSize: 10
      recordExceptions:
        - org.springframework.web.client.HttpServerErrorException
        - java.io.IOException
      ignoreExceptions:
        - java.lang.IllegalStateException
    shared:
      slidingWindowSize: 100
      permittedNumberOfCallsInHalfOpenState: 30
      waitDurationInOpenState: 1s
      failureRateThreshold: 50
      eventConsumerBufferSize: 10
      ignoreExceptions:
        - java.lang.IllegalStateException
  instances:
    backendA:
      baseConfig: default

在路由中使用已配置的断路器名称启用断路器过滤器,例如:

spring:
  application:
    name: gateway-service
  output.ansi.enabled: ALWAYS
  cloud:
    gateway:
      routes:
        - id: test-service-withResilient4j
          uri: http://localhost:8091
          predicates:
            - Path=/testService/**
          filters:
            - CircuitBreaker=backendA
            - RewritePath=/testService/(?<path>.*), /$\{path}

并且现在应该使用您的外部配置的断路器对其进行保护,否则,您只需使用定制工具通过代码配置方法对其进行配置