专栏首页TECH flower图解resilience4j容错机制

图解resilience4j容错机制

Resilience4j是一个轻量级、易于使用的容错库,其灵感来自Netflix Hystrix,但专为Java 8和函数式编程设计。轻量级,因为库只使用Vavr,它没有任何其他外部库依赖项。相比之下,Netflix Hystrix对Archaius有一个编译依赖关系,Archaius有更多的外部库依赖关系,如Guava和Apache Commons。 Resilience4j提供高阶函数(decorators)来增强任何功能接口、lambda表达式或方法引用,包括断路器、速率限制器、重试或舱壁。可以在任何函数接口、lambda表达式或方法引用上使用多个装饰器。优点是您可以选择所需的装饰器,而无需其他任何东西。 有了Resilience4j,你不必全力以赴,你可以选择你需要的。 https://resilience4j.readme.io/docs/getting-started

概览

本文将介绍resilience4j中的四种容错机制,不过鉴于容错机制原理的通用性,后文所介绍的这几种容错机制也可以脱离resilience4j而独立存在(你完全可以自己编码实现它们或者采用其他类似的第三方库,如Netflix Hystrix)。下面将会用图例来解释舱壁(Bulkhead)、断路器(CircuitBreaker)、限速器(RateLimiter)、重试(Retry)机制的概念和原理。

舱壁(Bulkhead)

Resilience4j提供了两种舱壁模式的实现,可用于限制并发执行的次数:

  • SemaphoreBulkhead(信号量舱壁,默认),基于Java并发库中的Semaphore实现。
  • FixedThreadPoolBulkhead(固定线程池舱壁),它使用一个有界队列和一个固定线程池。

SemaphoreBulkhead应该在各种线程和I / O模型上都能很好地工作。它基于信号量,与Hystrix不同,它不提供“影子”线程池选项。取决于客户端,以确保正确的线程池大小将与舱壁配置保持一致。

信号量舱壁(SemaphoreBulkhead)

?原图地址:http://images.dongxishaonian.tech/%E5%9B%BE%E8%A7%A3%E5%AE%B9%E9%94%99%E6%9C%BA%E5%88%B61.jpg

如上图,当信号量存在剩余时进入系统的请求会直接获取信号量并开始业务处理。当信号量全被占用时,接下来的请求将会进入阻塞状态,SemaphoreBulkhead提供了一个阻塞计时器,如果阻塞状态的请求在阻塞计时内无法获取到信号量则系统会拒绝这些请求。若请求在阻塞计时内获取到了信号量,那将直接获取信号量并执行相应的业务处理。

固定线程池舱壁(FixedThreadPoolBulkhead)

?原图地址:http://images.dongxishaonian.tech/%E5%9B%BE%E8%A7%A3%E5%AE%B9%E9%94%99%E6%9C%BA%E5%88%B60.jpg

FixedThreadPoolBulkhead的功能与SemaphoreBulkhead一样也是用于限制并发执行的次数的,但是二者的实现原理存在差别而且表现效果也存在细微的差别。FixedThreadPoolBulkhead使用一个固定线程池和一个等待队列来实现舱壁。当线程池中存在空闲时,则此时进入系统的请求将直接进入线程池开启新线程或使用空闲线程来处理请求。当线程池无空闲时接下来的请求将进入等待队列,若等待队列仍然无剩余空间时接下来的请求将直接被拒绝。在队列中的请求等待线程池出现空闲时,将进入线程池进行业务处理。

可以看到FixedThreadPoolBulkhead和SemaphoreBulkhead一个明显的差别是FixedThreadPoolBulkhead没有阻塞的概念,而SemaphoreBulkhead没有一个队列容量的限制。

限速器(RateLimiter)

?原图地址:http://images.dongxishaonian.tech/%E5%9B%BE%E8%A7%A3%E5%AE%B9%E9%94%99%E6%9C%BA%E5%88%B62.jpg

限速器(RateLimiter)的功能是防止突然的过量请求导致系统不堪重负,RateLimiter使用一个刷新周期的概念,限定在一个固定刷新周期内可处理的最大请求数量。若在某一个刷新周期内的请求数量已经达到最大,则本周期内接下来的请求将进入阻塞状态,如果在最大阻塞计时内新的刷新周期开启,则阻塞状态的请求将进入新的周期内进行处理。如最大的阻塞计时内新的刷新周期并未开启,则此时超出阻塞计时的那些请求将被直接拒绝。

断路器(CircuitBreaker)

?原图地址:http://images.dongxishaonian.tech/%E5%9B%BE%E8%A7%A3%E5%AE%B9%E9%94%99%E6%9C%BA%E5%88%B63.jpg

断路器(CircuitBreaker)相对于前面几个熔断机制更复杂,CircuitBreaker通常存在三种状态(CLOSE、OPEN、HALF_OPEN),并通过一个时间或数量窗口来记录当前的请求成功率或慢速率,从而根据这些指标来作出正确的容错响应。

当CircuitBreaker为CLOSE状态时客户端发起的请求将正常进入服务端系统,CircuitBreaker会计算出当前请求前的一个窗口里所有请求的异常率(失败率或慢速率),若异常率低于预期配置值,则系统将继续正常处理接下来的请求。当异常率不低于预期配置值时,此时服务端会进入OPEN状态,此时服务端将会暂时性的拒绝所有请求。在一段冷却时间(自定义配置)之后,服务端将自动进入HALF_OPEN状态,在半开状态服务端将尝试接受一定数量的请求(自定义配置),若这一定数量的请求的异常率低于预期,则此时服务端将再次恢复CLOSE状态,正常处理请求。而如果异常率还是高于预期则会继续退回到OPEN状态。

重试(Retry)

?原图地址:http://images.dongxishaonian.tech/%E5%9B%BE%E8%A7%A3%E5%AE%B9%E9%94%99%E6%9C%BA%E5%88%B64.jpg

重试机制比较简单,当服务端处理客户端请求异常时,服务端将会开启重试机制,重试期间内,服务端将每隔一段时间重试业务逻辑处理。如果最大重试次数内成功处理业务,则停止重试,视为处理成功。如果在最大重试次数内处理业务逻辑依然异常,则此时系统将拒绝该请求。

总结

本文介绍了常用的几种容错机制,与其说是resilience4j中的容错机制不如直接把resilience4j去掉,因为可以看到这些机制原理并不只来源于某个库或只与某个特定库有关,它更是一种设计理念,他的通用性应该是跨语言的。此外虽然本文只介绍了这几种容错机制,但是如何使用他们完全取决于你的业务场景和架构设计。你甚至可以随意组合使用它们,并且完全看不出这些组合最后所展示的效果像哪一种机制,那也没有关系,怎么使用、怎么组合完全取决于你所处的技术/业务环境。

本文分享自微信公众号 - TECH flower(tech-flower),作者:东溪陈姓少年

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-06-30

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • [译] 微服务的设计模式

    微服务架构已经成为现代应用程序开发中公认的技术选择。尽管它解决了某些问题,但不是灵丹妙药。它有几个缺点,使用这种体系架构时,还需要解决许多问题。这就需要学习这些...

    东溪陈姓少年
  • 除了FastJson,你也应该了解一下Jackson(二)

    上一篇文章介绍了Jackson中的映射器ObjectMapper,以及如何使用它来实现Json与Java对象之间的序列化和反序列化,最后介绍了Jackson中一...

    东溪陈姓少年
  • Spring Boot Admin实现服务健康预警

    上一篇文章主要介绍了Spring Boot Admin的概况以及我们如何在系统中引入和使用Spring Boot Admin,以此来帮助我们更加了解自己的系统,...

    东溪陈姓少年
  • BIO,NIO,AIO的理解

    BIO:同步阻塞式IO,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销...

    ydymz
  • 性能测试-Jmeter性能测试实战

    接口地址:http://www.baidu.com/s?ie=utf-8&wd=jmeter性能测试

    用户6367961
  • Tomcat性能优化,学会薪水翻倍

    tomcat是我们在web开发过程中会用到的servlet容器,同时也是springBoot内置集成默认的容器

    公众号 IT老哥
  • 线程并行学习笔记

    同步和异步的本质区别是是否需要等待,比如一个方法在执行,必须等前面一个方法程执行完成,才可以执行,这就是同步。如果不需要等上一个方法执行完成,并行或者并发执行,...

    SmileNicky
  • 面试之你该为老板选什么样的人

    本来的话,是觉得自己不够资历写这样的文章,不过总有一个过程嘛,自己也曾经作为技术面试官面试过一部分人,有一些自己的观点,可能会给还在面试或者面试官一些有益的启示...

    RobinsonZhang
  • 腾讯T4高级Java工程师十年技术之路的思考与感悟(技术与管理)

    美的让人心动
  • 一个10年工作经验程序员的成长故事

    很多新手程序员在面对自己的岗位和职业发展的时候,都会希望能得到过来人的指引,帮助自己少走弯路,更快的成长,老九君为小伙伴们整理了一位在互联网公司工作十年的技术专...

    老九君

扫码关注云+社区

领取腾讯云代金券