带有Resilience4j断路器的Spring云网关 - rome

19-12-27 banq

该文介绍如何利用Spring Cloud网关将resilience4j断路器与网关后面的后端服务结合使用,方法如下:

整个代码示例在github中

需要向您的Spring Cloud Gateway应用程序添加以下依赖项,以启用Resilience4j断路器集成:

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

现在,Spring Cloud断路器starter允许您通过Customizer用法来配置Resilience4j断路器定义,这是代码优先的方法(通过代码进行定制是默认优先,而不是通过配置定制),但是如果要对其从外部进行配置,这样可以通过分布式配置服务从外部控制其配置,那么就使用Resilience4j spring boot starter发挥作用,它使断路器的外部SpringBoot配置成为可能。

Resilience4j的Spring Boot Starter将根据您的外部配置创建CircuitBreakerRegistery bean,然后您可以将其注入Spring Cloud Starter的resilience4j工厂以实现集成,就是这样!

Resilience4j的外部配置将类似于:

resilience4j.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
    backendB:
      slidingWindowSize: 10
      minimumNumberOfCalls: 10
      permittedNumberOfCallsInHalfOpenState: 3
      waitDurationInOpenState: 1s
      failureRateThreshold: 50
      eventConsumerBufferSize: 10

加载Resilience4j的断路器注册表与Spring Cloud ReactiveResilience4JCircuitBreakerFactory之间的集成将如下进行:

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

现在是时候测试该集成并查看其工作原理:

  • 我们将使用模拟服务器测试容器模拟通过网关提供的目标后端服务
  • 我们将存根一些回应
  • 然后触发测试并监视日志,以了解ciruitbreaker的反应以及偏离路线,您可以通过Resilience4j支持的指标暴露和事件获取大量指标

添加以下依赖项以启用模拟Mock服务器的使用:

<dependency>
     <groupId>org.testcontainers</groupId>
     <artifactId>mockserver</artifactId>
     <version>1.12.3</version>
     <scope>test</scope>
 </dependency>
 <dependency>
     <groupId>org.mock-server</groupId>
     <artifactId>mockserver-client-java</artifactId>
     <version>3.10.8</version>
     <scope>test</scope>
 </dependency>

现在,您需要配置测试容器starup,并在模拟服务器启动后注入路由的自定义配置:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@RunWith(SpringRunner.class)
@ContextConfiguration(initializers = {GatewayCircuitBreakerTest.Initializer.class})
public class GatewayCircuitBreakerTest {
 
    private static final Logger LOGGER = LoggerFactory.getLogger(GatewayCircuitBreakerTest.class);
    private static MockServerContainer mockServerContainer;
 
    static {
        mockServerContainer = new MockServerContainer();
        mockServerContainer.start();
 
    }
 
    static class Initializer
            implements ApplicationContextInitializer<ConfigurableApplicationContext> {
        public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
            TestPropertyValues.of(
                    "spring.cloud.gateway.routes[0].id=test-service-withResilient4j",
                    "spring.cloud.gateway.routes[0].uri=" + mockServerContainer.getEndpoint(),
                    "spring.cloud.gateway.routes[0].predicates[0]=" + "Path=/testService/**",
                    "spring.cloud.gateway.routes[0].filters[0]=" + "RewritePath=/testService/(?<path>.*), /$\\{path}",
                    "spring.cloud.gateway.routes[0].filters[1].name=" + "CircuitBreaker",
                    "spring.cloud.gateway.routes[0].filters[1].args.name=" + "backendA",
                    "spring.cloud.gateway.routes[0].filters[1].args.fallbackUri=" + "forward:/fallback/testService"
            ).applyTo(configurableApplicationContext.getEnvironment());
        }
    }
 
    private MockServerClient client = new MockServerClient(mockServerContainer.getContainerIpAddress(), mockServerContainer.getServerPort());
    @Autowired
    private TestRestTemplate template;
 
    @AfterClass
    public static void close(){
        mockServerContainer.close();
    }
}

最后,您可以在类GatewayCircuitBreakerTest中触发受保护端点的测试,并通过分析控制台中报告的事件来查看它正在通过Resilience4j断路器.

 

              

1

猜你喜欢