图解resilience4j容错机制
Resilience4j是一个轻量级、易于使用的容错库,其灵感来自Netflix Hystrix,但专为Java 8和函数式编程设计。轻量级,因为库只使用Vavr,它没有任何其他外部库依赖项。相比之下,Netflix Hystrix对Archaius有一个编译依赖关系,Archaius有更多的外部库依赖关系,如Guava和Apache Commons。
Resilience4j提供高阶函数(decorators)来增强任何功能接口、lambda表达式或方法引用,包括断路器、速率限制器、重试或舱壁。可以在任何函数接口、lambda表达式或方法引用上使用多个装饰器。优点是您可以选择所需的装饰器,而无需其他任何东西。
有了Resilience4j,你不必全力以赴,你可以选择你需要的。
概览
本文将介绍resilience4j中的四种容错机制,不过鉴于容错机制原理的通用性,后文所介绍的这几种容错机制也可以脱离resilience4j而独立存在(你完全可以自己编码实现它们或者采用其他类似的第三方库,如Netflix Hystrix)。下面将会用图例来解释舱壁(Bulkhead)、断路器(CircuitBreaker)、限速器(RateLimiter)、重试(Retry)机制的概念和原理。
舱壁(Bulkhead)
Resilience4j提供了两种舱壁模式的实现,可用于限制并发执行的次数:
- SemaphoreBulkhead(信号量舱壁,默认),基于Java并发库中的Semaphore实现。
- FixedThreadPoolBulkhead(固定线程池舱壁),它使用一个有界队列和一个固定线程池。
SemaphoreBulkhead应该在各种线程和I / O模型上都能很好地工作。它基于信号量,与Hystrix不同,它不提供“影子”线程池选项。取决于客户端,以确保正确的线程池大小将与舱壁配置保持一致。
信号量舱壁(SemaphoreBulkhead)
如上图,当信号量存在剩余时进入系统的请求会直接获取信号量并开始业务处理。当信号量全被占用时,接下来的请求将会进入阻塞状态,SemaphoreBulkhead提供了一个阻塞计时器,如果阻塞状态的请求在阻塞计时内无法获取到信号量则系统会拒绝这些请求。若请求在阻塞计时内获取到了信号量,那将直接获取信号量并执行相应的业务处理。
固定线程池舱壁(FixedThreadPoolBulkhead)
原图地址:固定线程池舱壁(FixedThreadPoolBulkhead)
FixedThreadPoolBulkhead的功能与SemaphoreBulkhead一样也是用于限制并发执行的次数的,但是二者的实现原理存在差别而且表现效果也存在细微的差别。FixedThreadPoolBulkhead使用一个固定线程池和一个等待队列来实现舱壁。当线程池中存在空闲时,则此时进入系统的请求将直接进入线程池开启新线程或使用空闲线程来处理请求。当线程池无空闲时接下来的请求将进入等待队列,若等待队列仍然无剩余空间时接下来的请求将直接被拒绝。在队列中的请求等待线程池出现空闲时,将进入线程池进行业务处理。
可以看到FixedThreadPoolBulkhead和SemaphoreBulkhead一个明显的差别是FixedThreadPoolBulkhead没有阻塞的概念,而SemaphoreBulkhead没有一个队列容量的限制。
限速器(RateLimiter)
原图地址:限速器(RateLimiter)
限速器(RateLimiter)的功能是防止突然的过量请求导致系统不堪重负,RateLimiter使用一个刷新周期的概念,限定在一个固定刷新周期内可处理的最大请求数量。若在某一个刷新周期内的请求数量已经达到最大,则本周期内接下来的请求将进入阻塞状态,如果在最大阻塞计时内新的刷新周期开启,则阻塞状态的请求将进入新的周期内进行处理。如最大的阻塞计时内新的刷新周期并未开启,则此时超出阻塞计时的那些请求将被直接拒绝。
断路器(CircuitBreaker)
原图地址:断路器(CircuitBreaker)
断路器(CircuitBreaker)相对于前面几个熔断机制更复杂,CircuitBreaker通常存在三种状态(CLOSE、OPEN、HALF_OPEN),并通过一个时间或数量窗口来记录当前的请求成功率或慢速率,从而根据这些指标来作出正确的容错响应。
当CircuitBreaker为CLOSE状态时客户端发起的请求将正常进入服务端系统,CircuitBreaker会计算出当前请求前的一个窗口里所有请求的异常率(失败率或慢速率),若异常率低于预期配置值,则系统将继续正常处理接下来的请求。当异常率不低于预期配置值时,此时服务端会进入OPEN状态,此时服务端将会暂时性的拒绝所有请求。在一段冷却时间(自定义配置)之后,服务端将自动进入HALF_OPEN状态,在半开状态服务端将尝试接受一定数量的请求(自定义配置),若这一定数量的请求的异常率低于预期,则此时服务端将再次恢复CLOSE状态,正常处理请求。而如果异常率还是高于预期则会继续退回到OPEN状态。
重试(Retry)
原图地址:重试(Retry)
重试机制比较简单,当服务端处理客户端请求异常时,服务端将会开启重试机制,重试期间内,服务端将每隔一段时间重试业务逻辑处理。 如果最大重试次数内成功处理业务,则停止重试,视为处理成功。如果在最大重试次数内处理业务逻辑依然异常,则此时系统将拒绝该请求。
总结
本文介绍了常用的几种容错机制,与其说是resilience4j中的容错机制不如直接把resilience4j去掉,因为可以看到这些机制原理并不只来源于某个库或只与某个特定库有关,它更是一种设计理念,他的通用性应该是跨语言的。此外虽然本文只介绍了这几种容错机制,但是如何使用他们完全取决于你的业务场景和架构设计。你甚至可以随意组合使用它们,并且完全看不出这些组合最后所展示的效果像哪一种机制,那也没有关系,怎么使用、怎么组合完全取决于你所处的技术/业务环境。
欢迎访问笔者博客:blog.dongxishaonian.tech
关注笔者公众号,推送各类原创/优质技术文章 ️
图解resilience4j容错机制的更多相关文章
- 【原】Storm 守护线程容错机制
Storm入门教程 1. Storm基础 Storm Storm主要特点 Storm基本概念 Storm调度器 Storm配置 Guaranteeing Message Processing(消息处理 ...
- Spark RDD概念学习系列之RDD的容错机制(十七)
RDD的容错机制 RDD实现了基于Lineage的容错机制.RDD的转换关系,构成了compute chain,可以把这个compute chain认为是RDD之间演化的Lineage.在部分计算结果 ...
- Flink资料(2)-- 数据流容错机制
数据流容错机制 该文档翻译自Data Streaming Fault Tolerance,文档描述flink在流式数据流图上的容错机制. ------------------------------- ...
- Hadoop(七)HDFS容错机制详解
前言 HDFS(Hadoop Distributed File System)是一个分布式文件系统.它具有高容错性并提供了高吞吐量的数据访问,非常适合大规模数据集上的应用,它提供了一个高度容错性和高吞 ...
- Storm学习笔记 - 消息容错机制
Storm学习笔记 - 消息容错机制 文章来自「随笔」 http://jsynk.cn/blog/articles/153.html 1. Storm消息容错机制概念 一个提供了可靠的处理机制的spo ...
- 【Storm篇】--Storm 容错机制
一.前述 Storm容错机制相比其他的大数据组件做的非常不错. 二.具体原因 结合Storm集群架构图: 我们的程序提交流程如下: 其中各个组件的作用如下: Nimbus资源调度任务分配接收jar ...
- 图解Tomcat类加载机制(阿里面试题)
Tomcat的类加载机制是违反了双亲委托原则的,对于一些未加载的非基础类(Object,String等),各个web应用自己的类加载器(WebAppClassLoader)会优先加载,加载不到时再交给 ...
- Flink学习(三)状态机制于容错机制,State与CheckPoint
摘自Apache官网 一.State的基本概念 什么叫State?搜了一把叫做状态机制.可以用作以下用途.为了保证 at least once, exactly once,Flink引入了State和 ...
- Elasticsearch和HDFS 容错机制 备忘
1.Elasticsearch 横向扩容以及容错机制http://www.bubuko.com/infodetail-2499254.html 2.HDFS容错机制详解https://www.cnbl ...
随机推荐
- Java实现 LeetCode 799 香槟塔 (暴力模拟)
799. 香槟塔 我们把玻璃杯摆成金字塔的形状,其中第一层有1个玻璃杯,第二层有2个,依次类推到第100层,每个玻璃杯(250ml)将盛有香槟. 从顶层的第一个玻璃杯开始倾倒一些香槟,当顶层的杯子满了 ...
- Java实现 LeetCode 430 扁平化多级双向链表
430. 扁平化多级双向链表 您将获得一个双向链表,除了下一个和前一个指针之外,它还有一个子指针,可能指向单独的双向链表.这些子列表可能有一个或多个自己的子项,依此类推,生成多级数据结构,如下面的示例 ...
- Java实现 LeetCode 394 字符串解码
394. 字符串解码 给定一个经过编码的字符串,返回它解码后的字符串. 编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次.注意 k ...
- Java实现找零问题
1 问题描述 现需找零金额为n,则最少需要用多少面值为d1 < d2 < d3 < - < dm的硬币?(PS:假设这m种面值d1 < d2 < d3 < - ...
- java实现第四届蓝桥杯黄金连分数
黄金连分数 题目描述 黄金分割数0.61803- 是个无理数,这个常数十分重要,在许多工程问题中会出现.有时需要把这个数字求得很精确. 对于某些精密工程,常数的精度很重要.也许你听说过哈勃太空望远镜, ...
- Linux fdisk手动分区
查询系统中可以被识别的硬盘:fdisk -l 可以看到,我的服务器只有一块硬盘,容量是53.7GB,有1个分区,文件系统类型是Linux,Id 是83(82是Linux swap分区,相当于Windo ...
- 什么!你想要封装好的ajax
ajax作为前端开发领域一个必不可少的内容,也是灵魂所在,今天就ajax的封装给大家做一个分析, 如果没有猜错的话现在基本上用原生去写ajax的意见不多了,这是肯定的 ,为什么这么说,jq的ajax大 ...
- 游戏开发之UI管理器(跨引擎)
使用UI管理器的目的 使用单场景与zindex结合的方式管理UI. 能够隐藏底层UI达到优化效果. 很好的组织和管理UI. 跨引擎使用. 管理器分类 根据以往经验我开发了三种类型的管理器,队列管理器, ...
- CentOS8.1中搭建Gitlab服务器
依旧是写在前面的话♠:很多IT人从业N年也许都还没有亲自搭过一次Gitlab服务器,是不是?有木有?!通常都是背着自己的笔记电脑到一家公司入职,或入职后领到公司分配的电脑,然后分配了Git账号,拿了将 ...
- STM32学习笔记——printf
printf复习 当我们写printf("%d\n", 1);的时候,printf函数并不能通过C语言语法得知第二个参数是int类型.printf是一个变参函数(variadic ...