飙血推荐
  • HTML教程
  • MySQL教程
  • JavaScript基础教程
  • php入门教程
  • JavaScript正则表达式运用
  • Excel函数教程
  • UEditor使用文档
  • AngularJS教程
  • ThinkPHP5.0教程

使用 Spring Cloud Resiliance4j 进行断路器和重试

时间:2021-12-08  作者:匿名  

介绍

随着服务数量的增加,服务可能需要与其他服务器同步通信,从而变得依赖于上游服务。与上游服务通信时的任何问题都会传播到下游服务。 

为了保护服务免受此类问题的影响,我们可以使用一些模式来保护服务。所以,今天我们将研究其中两个,即断路器和重试机制。

我们先来看看Retry机制。 

集成重试 

让我们转到https://域名并使用以下依赖项创建一个简单的 Spring Boot 应用程序。 

<dependency>
  <groupId>域名d</groupId>
  <artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
</dependency>
<dependency>
   <groupId>域名ngframework</groupId>
   <artifactId>spring-aspects</artifactId>
</dependency>

除了断路器启动器依赖项外,我们还需要 spring 方面依赖项,因为重试和断路器机制使用 Spring AOP 概念工作。

接下来,我们将添加一个服务类,该类将使用 RestTemplate 对端点进行 REST 调用。 

@域名域名ice
public class Service {
    @Value("${域名:http://localhost:6060/service2}")
    String serviceUrl;
    @Retry(name = "myRetry", fallbackMethod = "fallback")
    public String fetchData() {
        域名tln(" Making a request to " + serviceUrl + " at :" + 域名());
        RestTemplate restTemplate = new RestTemplate();
        return 域名orObject(serviceUrl, 域名s);
    }
    public String fallback(Exception e) {
        return "fallback value";
    }
}

如您所见,如果重试计数用完,我们在此方法上有重试注释和回退方法的名称。我们将从fetchData只有一个简单的 get 映射的控制器中调用该方法。

@RestController
public class Controller {
    @Autowired
    private Service service;
    @GetMapping("/")
    public String getValues() {
        return 域名hData();
    }
}

现在,让我们看看重试配置。

resilience4j:
  retry:
   instances:
      myRetry:
        max-attempts: 3
        wait-duration: 5s

在此,我们创建了仅重试 3 次且重试间隔为 5 秒的最直接配置。

有了这个,让我们启动应用程序并调用 get 端点。

域名

这是在 5 秒的固定速率后重试。 

指数重试

现在,在固定时间后重试可能会导致上游服务进一步无响应(可能它已经被许多请求淹没了)。在这种情况下,我们可以提供指数退避机制。

让我们添加这个配置。

resilience4j:
  retry:
    instances:
      myRetry:
        max-attempts: 3
        wait-duration: 5s
        enable-exponential-backoff: true
        exponential-backoff-multiplier: 2

指数退避的工作方式如下:

wait-duration * (exponential-backoff-multiplier ^ (retry iteration count))

所以使用上面的配置,reties 将在以下时间发生。 

1st Retry  - 5s * 2^0 = after 5 seconds
2nd Retry  - 5s * 2^1 = after 10 seconds
3rd Retry  - 5s * 2^2 = after 20 seconds
..
..
nTh Retry - 5s * 2^n

有条件的异常重试 

让我们考虑可能存在您想要重试的某些异常和您不想重试的某些异常。 

例如,当我们发送一个错误的请求时,无论重试多少次,我们总会得到相同的错误。在这种情况下,我们不想重试。但是对于 404 错误,我们想重试(可能该服务暂时不可用)。 

在这种情况下,我们可以配置我们应该重试或不重试的异常类型。为此,我们需要添加以下配置属性。

resilience4j:
  retry:    instances:
      myRetry:
        max-attempts: 5
        wait-duration: 5s
        enable-exponential-backoff: true
        exponential-backoff-multiplier: 2
        retry-exceptions:
         - 域名.域名ClientException
        ignore-exceptions:
         - 域名域名reException

举个例子,我已经声明我不想在IgnoreException抛出类型异常时重试。

现在,这些是 Resilience4J 重试机制的一些配置属性。 

让我们看看另一个称为断路器的概念。 

集成断路器

断路器是一种机制,允许应用程序保护自己免受不可靠的下游服务的影响。这可以防止级联故障在整个系统中传播,并有助于构建容错和可靠的服务。

对断路器的支持已经存在于我们添加的依赖项中,所以让我们利用它。 

@CircuitBreaker(name = "myCircuitBreaker", fallbackMethod = "fallback")
@Retry(name = "myRetry")
public String fetchData() {
    域名tln(" Making a request to " + serviceUrl + " at :" + 域名());
    RestTemplate restTemplate = new RestTemplate();
    return 域名orObject(serviceUrl, 域名s);
}

注意: 请注意,我已从重试注释中删除了回退方法。因为我希望断路器在重试用尽时接管。 

让我们配置断路器。

resilience4j:
  retry:    instances:
      myRetry:
        max-attempts: 3
        wait-duration: 5s
        enable-exponential-backoff: true
        exponential-backoff-multiplier: 2
        retry-exceptions:
         - 域名.域名ClientException
        ignore-exceptions:
         - 域名域名reException
  circuitbreaker:
    instances:
      myCircuitBreaker:
       wait-duration-in-open-state: 1m
       permitted-number-of-calls-in-half-open-state: 3
       sliding-window-type: count-based
       sliding-window-size: 5
       minimum-number-of-calls: 5
       slow-call-duration-threshold: 10s
       slow-call-rate-threshold: 60 
       failure-rate-threshold: 60

了解断路器配置

在这里,我使用了基于计数的滑动窗口,其中窗口大小为 5 个事件,失败和缓慢阈值率为 60%。

现在,这个滑动窗口是什么意思?

这意味着我们将考虑一组 5 个连续事件(成功或失败),以确定断路器是否应转换为 OPEN 或 CLOSED 状态。 

术语 OPEN 状态意味着断路器被激活,从而不允许对上游服务进行调用。

现在,在上面的配置中,如果在 5 个调用中,60% 的调用失败或很慢(即至少 3 个调用),则断路器将移动到 OPEN 状态。一旦断路器移动到 OPEN 状态,它将在此状态下等待 1 分钟,然后再移动到 HALF-OPEN 状态。 

现在,这个半开状态是什么?

这种状态就像一个评估状态,我们根据有限数量的允许调用检查断路器是否移动到 OPEN 或 CLOSED 状态。根据允许的调用次数,如果慢速或故障次数超过慢速或故障阈值,则断路器将移回 OPEN 状态,否则将其移至 CLOSED 状态。 

例如,在上面的配置中,由于我们将 HALF_OPEN 状态下允许的调用次数设置为 3,因此至少需要 2 个调用成功才能使断路器移回 CLOSED 状态并允许调用到上游服务器。

断路器和重试配置一起

现在有了上面的配置,让我们启动应用程序并向端点发出请求。

在发出请求时,我们看到它只尝试了一次并直接返回给我们回退值。这是因为直接调用了断路器回退方法,没有触发重试。这样做的原因是处理这两个机构的弹簧方面的排列顺序。

断路器和重试方面顺序

由于断路器和重试机制的实现是利用spring的基于方法的AOP机制来工作的,因此处理这两种不同机制的方面有一定的顺序。 

默认情况下,重试机制具有较低的优先级,因此它会围绕断路器方面进行扭曲。 

 Retry  ( Circuit Breaker ( function ) )

现在要改变这一点,我们可以添加一个“方面顺序”属性来定义顺序,如下所示:

resilience4j:
  retry:
    retry-aspect-order: 2
    instances:
      myRetry:
        max-attempts: 3
        wait-duration: 5s
        enable-exponential-backoff: true
        exponential-backoff-multiplier: 2
        retry-exceptions:
         - 域名.域名ClientException
        ignore-exceptions:
         - 域名域名reException
  circuitbreaker:
    circuit-breaker-aspect-order: 1
    instances:
      myCircuitBreaker:
        wait-duration-in-open-state: 1m
        permitted-number-of-calls-in-half-open-state: 3
        sliding-window-type: count-based
        sliding-window-size: 5
        minimum-number-of-calls: 5
        slow-call-duration-threshold: 10s
        slow-call-rate-threshold: 60 
        failure-rate-threshold: 60

订单值越高,优先级越高。

有了这个,当我们运行应用程序时,我们会得到以下输出。

有了这个,3 次重试发生,然后断路器方面将接管。

结论

有了这个,我们刚刚看到了如何在 Spring Boot 应用程序中集成断路器和重试机制。同样,我们可以集成速率限制器、隔板等。

标签:JAVASpring
湘ICP备14001474号-3  投诉建议:234161800@qq.com   部分内容来源于网络,如有侵权,请联系删除。