早高峰的地铁调度室里,老李死死盯着监控大屏:A站信号故障,B站列车被迫滞留,C站客流瞬间爆满——一条线的延误像多米诺骨牌一样推倒了整张地铁网。老李的墙上挂着四样东西:电箱里的自动跳闸开关、进站口的限流闸机、司机的重新发车规则、以及故障时的地面公交预案。这套“城市地铁容错术”放在微服务世界里,就是 Resilience4j 在做的事。它是一个 Java 轻量级容错库,专门解决服务之间“一个拖垮一片”的雪崩问题,用熔断、限流、重试、降级四个模式,让系统在高并发和故障面前依然站得稳。

岗位关联

掌握 Resilience4j,等于拿到了微服务稳定性保障的行业标配钥匙。它是 Hystrix 停止维护后的主流替代方案,是 Java 后端工程师走向高并发架构的核心技能。

目录
  1. 可视化演示
  2. 容错背景与雪崩
  3. 熔断器三态流转
  4. 限流器令牌桶
  5. 重试与退避策略
  6. 降级与隔离
  7. 轻量设计优势
  8. Hystrix对比实战
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示熔断器三态状态机转换、四大容错组件装饰器链及组合顺序,直观呈现函数式容错的轻量级设计。

本节配有交互动效(进入视口后自动加载,约 3KB)。

熔断器状态机 CLOSED:正常放行,滑动窗口记录失败率 OPEN:拒绝请求,等待超时后进入半开 P(Open)=P(Fail>50%) 三态自动转换

容错背景与雪崩

老李在调度室给新来的值班员上第一课,指着大屏说:“你看,A 站信号故障,列车走不了,后面的车全堵在隧道里,乘客出不去也进不来,C 站客流马上爆表。”这就是一条线的故障像雪球一样滚成雪崩的过程。在微服务世界里,单体应用被拆成成百上千个小服务,它们通过远程调用协同工作,而网络偏偏是世界上最不可靠的东西之一:会延迟、会超时、会断连。

当一个下游接口从 50 毫秒变慢到 2 秒,调用方的线程池会迅速被占满,新请求不断堆积,内存飙升,GC 压力增大,最终进程被压垮。而被压垮的进程又会拖慢调用它的上游服务,灾难就这样顺着调用链一级一级向上传染。在分布式系统里,这种“一个服务故障引发链路整体崩溃”的现象就叫雪崩效应。

为了治理雪崩,业界总结出四大容错模式:熔断(CircuitBreaker)、限流(RateLimiter)、重试(Retry)、降级与隔离(Fallback + Bulkhead)。Resilience4j 正是把这四种模式打包成一套轻量级 Java 工具库的天才之作。它不要求你改架构,不要求继承特定父类,只需要在你现有的方法外面套一层“防护壳”。

老李给值班员定下规矩:看到大屏任何一条线变红,先按熔断键,别等全线飘红才动手。这也是微服务容错的第一原则——在故障还没蔓延之前,先把它关在笼子里。

熔断器三态流转

老李讲起家里老房子的电箱:半夜电流过载,“啪”的一声跳闸,全屋断电,人得摸黑去合闸。后来电工换了个带自动脱扣功能的断路器,电流超过阈值就会自动切断电路,保护整栋楼,故障排除后又自动合闸送电。微服务容错里的熔断器,正是给服务调用安装的这样一枚“自动跳闸开关”。

熔断器不再靠物理电流,而是靠调用结果的失败率来判断下游服务是否健康。它有三种状态:关闭(CLOSED)时一切正常,请求畅通无阻;当失败率超过配置的阈值,熔断器切换到打开(OPEN)状态,后续请求不再真正发给下游,而是直接快速失败,避免线程池被拖垮;过了一段冷却时间,熔断器进入半开(HALF_OPEN)状态,放行少量试探请求,如果这些请求成功了,说明服务已经恢复,熔断器重新闭合,否则继续打开。

Resilience4j 使用滑动窗口来记录最近 N 次调用的成功与失败情况,这个窗口可以是基于调用次数的,也可以是基于时间跨度的。当窗口内失败率超过阈值,比如 50%,熔断器就自动从关闭切换为打开。核心公式如下:

老李看着电箱感叹:以前的跳闸要人半夜爬起来合,现在的熔断器自己看数据、自己做决定、自己试探恢复,把电工从值班室里彻底解放了出来。这就是自动化容错的魅力。

失败率=窗口内失败次数窗口内总请求次数×100%\displaystyle\text{失败率} = \frac{\text{窗口内失败次数}}{\text{窗口内总请求次数}} \times 100\%
  1. 窗口内失败次数滑动窗口覆盖最近 N 次调用,统计其中被标记为失败的数量,它代表服务在这段时间里有多不稳定。
    NfailN_{\text{fail}}
  2. 窗口内总请求次数滑动窗口记录的全部请求数量,无论成功还是失败,都会被计入分母。
    NtotalN_{\text{total}}
  3. 乘以 100%把比值换算成百分比,才能和 50% 这样的熔断阈值做直观比较。
    ×100%\times 100\%

限流器令牌桶

地铁早高峰,站台入口的闸机一排排亮着绿灯,每分钟放行固定数量的人进站。老李说:“限流不是限制站台上同时站多少人,而是限制每秒能涌进去多少人。”如果任由所有乘客一窝蜂冲进站台,别说上车,连转身都难,踩踏事故分分钟发生。微服务里的限流器(RateLimiter)也是同样的逻辑。

Resilience4j 的 RateLimiter 基于令牌桶算法实现。想象一个桶里装着令牌,每个请求必须拿走一个令牌才能被放行;令牌是匀速补充的,比如每秒钟补充 10 个。桶里的令牌用完,新的请求要么被拒绝,要么等待下一个周期拿到令牌再放行。通过这种机制,限流器把进入下游的流量牢牢摁在一个可控速率上。

在配置上,核心参数是 limitRefreshPeriod(令牌刷新周期)和 limitForPeriod(每个周期补充的令牌数量)。比如配置每 100 毫秒补充 5 个令牌,就等价于每秒最多处理 50 个请求。当令牌不足时,默认策略是直接丢弃请求,抛出 RequestNotPermitted 异常;也可以配置 timeoutDuration,让请求最多等多久。

老李在闸机旁贴了张纸条“每秒进站 200 人”,这比“站台最多站 2000 人”聪明得多。限流管住的是速率,就像水管的阀门,不管水池多大,每秒流过多少水才决定系统承不承受得住。

availableTokens=min⁡(C, storedTokens+ΔtTrefill×N)\displaystyle\text{availableTokens} = \min\left( C,\ \text{storedTokens} + \frac{\Delta t}{T_{\text{refill}}} \times N \right)
  1. 桶容量 C令牌桶最多能容纳的令牌数量,对应配置里的容量上限,防止积压过多令牌导致突发流量失控。
    CC
  2. 存量令牌加补充量上一轮剩余的令牌数,加上经过时间间隔 \(\Delta t\) 后按刷新周期 \(T_{\text{refill}}\) 补充进来的新令牌。
    storedTokens+ΔtTrefill×N\text{storedTokens} + \frac{\Delta t}{T_{\text{refill}}} \times N
  3. min 取最小值保证可用令牌数永远不超过桶容量,桶再大也有上限。
    min⁡(⋅)\min(\cdot)

重试与退避策略

地铁司机的驾驶手册上写着一条经验:信号灯跳红灯不是终点,可能是临时故障,等几秒钟信号恢复,列车可以重新启动。但司机绝不会疯狂地反复按启动键——第一次等 2 秒,第二次等 4 秒,第三次等 8 秒,如果三次都失败,就呼叫调度中心请求改线。这套“越等越久”的规则,在容错库里叫指数退避。

在微服务调用中,很多失败其实是暂时的:网络闪断、连接池瞬时耗尽、下游服务正在做垃圾回收。这些情况下,立刻重试很可能就成功了。Resilience4j 的 Retry 模块允许你给任意方法套上重试机制,配置最大尝试次数 maxAttempts(包含首次调用)和重试间隔 waitDuration。

值得注意的是,重试不是万能的。对于下游返回 5xx 错误或请求超时这类临时故障,重试是有效的;但对于 4xx 参数错误,重试多少次都白搭,因为问题出在请求本身。此外,重试必须配合退避策略,否则所有请求同时重试,等于把已经摇摇欲坠的下游再补一刀,引发“重试风暴”。指数退避的等待时间公式如下:

老李给司机的指令很明确:最多重试三次,越等越久,三次不行就上报。这种“克制”是重试策略的灵魂——既给临时故障留了自愈的窗口,又不至于把故障放大成灾难。

waitn=W0×2(n−1)\displaystyle\text{wait}_n = W_0 \times 2^{(n-1)}
  1. 初始延迟 W₀第一次重试前等待的基础时长,比如 100 毫秒。
    W0W_0
  2. 指数递增 2^(n-1)第 n 次重试的等待时间等于初始延迟乘以 2 的 n−1 次方,等待时间成倍拉长。
    2(n−1)2^{(n-1)}
  3. wait_n 为第 n 次重试的实际等待随着尝试次数增加,退避时间越来越长,给下游留出恢复喘息的时间。
    waitn\text{wait}_n

降级与隔离

老李的调度预案册里最重要的一页是“地面公交接驳方案”:当某条线路的站点临时封闭,调度中心立刻启动预案,引导乘客出站换乘公交,虽然慢一些,但至少人不会滞留。在容错世界里,这种“走不了地铁就走地面”的备用方案,就是降级(Fallback)。当熔断、限流、超时发生时,系统不再傻等,而是返回一个缓存结果或友好提示,保证用户体验不彻底中断。

另一个重要概念是舱壁隔离(Bulkhead),这个词来自轮船设计:船舱被分隔成多个独立水密隔舱,一个舱进水了,其他舱还能保持浮力。在微服务里,Resilience4j 用 Bulkhead 给不同的下游依赖分配独立的线程池或信号量,支付调用的线程池满了,不会占用商品查询的线程资源,两者互不拖累。

Fallback 的常见实现是提供一个“存根响应”(Stub Response):比如推荐服务挂了,就返回热门商品缓存列表;用户积分服务超时,就返回 0 积分。只要响应格式正确,上游业务可以继续运转。Bulkhead 则支持两种隔离方式:SemaphoreBulkhead(信号量隔离)和 ThreadPoolBulkhead(线程池隔离),前者更轻量,后者适合需要异步调用的场景。

老李把手里的预案册和列车的隔舱门连起来讲:公交预案是 Fallback,隔舱门是 Bulkhead。一个乘客的问题不能拖垮整条线路,一个服务的问题也不能拖垮整个系统。

轻量设计优势

老李刚换装备时,调度室里那套旧工具箱足有半人高,里面堆着各种线缆和笨重仪器,出个差要两个人抬。后来换成一条模块化腰带包,每个工具一个小格子,用哪个抽哪个,轻便得像换了一身装备。Resilience4j 在设计理念上,就是把“工具箱”做成了“模块化腰带包”。

传统容错库如 Hystrix 采用继承式 API,你必须让方法继承 HystrixCommand 才能获得容错能力——这是侵入性极强的设计。而 Resilience4j 基于 Java 8 函数式接口设计,你只需要传进去一个 Supplier 或 Function,它就能用装饰器模式给你的方法层层加防护。不要求改接口、不要求继承任何类,跟现有代码是解耦的。

Resilience4j 的模块化还体现在包结构上:resilience4j-circuitbreaker、resilience4j-ratelimiter、resilience4j-retry、resilience4j-bulkhead 都是独立发布的 jar 包,你只需要引入用得到的模块。它没有第三方运行时依赖,底层就是 JDK 自带的并发工具,开销极小。多个装饰器可以像搭积木一样组合:

老李拍拍腰间的工具包说,以前带工具箱出次现场腰都断了,现在轻装上阵,要哪个功能抽哪个模块。Resilience4j 的轻,轻在依赖少、侵入小、组合灵活,这也是它能取代 Hystrix 成为新宠的根本原因。

guarded=Fallback∘CircuitBreaker∘RateLimiter∘Retry(原始调用)\displaystyle\text{guarded} = \text{Fallback} \circ \text{CircuitBreaker} \circ \text{RateLimiter} \circ \text{Retry}(\text{原始调用})
  1. 原始调用最内层的业务逻辑,也就是你真正要执行的那个方法。
    原始调用\text{原始调用}
  2. Retry 紧贴原始调用失败后的重试发生在最里层,重试的每一次请求都会经过外层装饰器。
    Retry\text{Retry}
  3. RateLimiter 与 CircuitBreaker 叠加从内向外依次叠加限流和熔断,请求先被限流约束,再用熔断统计失败率。
    RateLimiter∘CircuitBreaker\text{RateLimiter} \circ \text{CircuitBreaker}
  4. Fallback 最外层兜底如果整个链最终失败,最外层的降级函数给出备用响应,确保调用方拿到结果。
    Fallback\text{Fallback}

Hystrix对比实战

老李终于下定决心关掉旧信号系统。旧系统的控制台占了大半个房间,操作界面复杂得像飞机驾驶舱,每次升级要停运半天,供应商早就停止维护了。新系统是一台轻薄的控制终端,自动化程度高,维护成本直线下降,机房温度都降了几度。从 Hystrix 迁移到 Resilience4j 的过程,就有点像这次“换系统”。

Hystrix 曾经是微服务容错的标配,但它有两个硬伤:第一,你必须继承 HystrixCommand,把业务逻辑塞进命令模式里,代码侵入性很强;第二,它为每次调用都分配独立的线程池,线程开销大,内存占用高,在上百个服务的场景下简直是一场资源灾难。更关键的是,Hystrix 自 2018 年起进入维护模式,不再更新,社区纷纷转向 Resilience4j。

在 Spring Boot 中集成 Resilience4j 非常简单,引入 resilience4j-spring-boot2 依赖后,配置都写在 application.yml 里,配合 @CircuitBreaker、@RateLimiter 等注解即可使用。最常用的配置调优思路是:先压测拿到接口的 P99 延迟,再乘以一个安全系数作为超时时间,避免超时设得太短误杀正常请求:

老李在总结会上说了一句话:旧系统不是不好,是太重了,重到系统本身成了新的风险点。Hystrix 的教训就在于此,而 Resilience4j 用函数式和模块化给出了新一代答案。

---

超时时间=P99 延迟×2\displaystyle\text{超时时间} = \text{P99 延迟} \times 2
  1. P99 延迟99% 的请求都能在这个时间内完成,代表着接口的典型最坏延迟。
    P99 延迟\text{P99 延迟}
  2. 乘以安全系数 2为尾部抖动和极端网络状况留出一倍缓冲,减少因为超时误判导致的熔断。
    ×2\times 2
  3. 结果作为超时阈值比绝大多数请求慢,又不至于拖垮调用方,是超时配置的黄金平衡点。
    超时时间\text{超时时间}

AI 应用场景

支付渠道调用防护

阶段:模型推理或服务调用的稳定性保障

解决的问题:在 AI 客服机器人调用支付网关时,第三方渠道偶尔出现高延迟和超时。传统做法是无脑等待,导致调用方线程池被占满,机器人整体卡死。引入 Resilience4j 的 CircuitBreaker + Retry 后,失败率一旦飙升立即熔断,快速返回“支付暂不可用”的降级文案,同时用指数退避重试避免重试风暴。

具体案例:某电商平台的智能客服需要实时查询订单支付状态,依赖第三方支付网关。网关在大促期间性能抖动,熔断器在失败率超过 40% 时跳闸,客服机器人改走缓存应答,大促结束后自动恢复。

秒杀场景的流量闸门

阶段:高并发入口的流量整形

解决的问题:秒杀活动中,AI 推荐的爆款商品瞬间涌入百万请求,如果全部打到下单服务,数据库必然被打爆。RateLimiter 负责把每秒下单量限制在系统可承受范围内,Bulkhead 把秒杀流量和普通订单流量隔离在线程池的两个舱室,秒杀再激烈也不影响日常订单。

具体案例:某电商平台通过 Resilience4j 的 RateLimiter 将下单接口限流为每秒 5000 个请求,超出的请求直接提示“稍后再试”,同时用 Bulkhead 隔离了秒杀链路和普通购物车链路,大促期间系统全程零故障。

商品详情页的降级兜底

阶段:依赖服务故障时的优雅降级

解决的问题:AI 个性化推荐服务偶尔发生故障,如果商品详情页被推荐服务拖垮,整页白屏,用户直接流失。通过 Fallback 在推荐服务超时或熔断时返回热门商品缓存列表,页面始终有内容可看,推荐失败对用户几乎无感。

具体案例:某内容社区 App 的首页信息流依赖推荐服务,推荐服务发布新模型时偶发抖动。配置 Fallback 返回昨日热榜后,首页首屏成功率从 96.5% 提升到 99.9%,用户几乎感知不到推荐服务的升级过程。

Python 演示

python61 行
class CircuitBreaker:    def __init__(self, failure_threshold, window_size):        self.failure_threshold = failure_threshold        self.window_size = window_size        self.records = []        self.state = '关闭'        self.trial_used = False     def allow_request(self):        if self.state == '打开':            return False        if self.state == '半开':            return not self.trial_used        return True     def record(self, ok):        if self.state == '关闭':            self.records.append(1 if ok else 0)            if len(self.records) > self.window_size:                self.records.pop(0)            if self.failure_rate() >= self.failure_threshold:                self.state = '打开'        elif self.state == '半开':            if ok:                self.records.clear()                self.state = '关闭'            else:                self.state = '打开'            self.trial_used = False     def try_half_open(self):        if self.state == '打开':            self.state = '半开'            self.trial_used = False     def failure_rate(self):        if not self.records:            return 0.0        return self.records.count(0) / len(self.records)  def fake_call():    import random    return random.random() >= 0.4  def main():    cb = CircuitBreaker(failure_threshold=0.5, window_size=10)    for i in range(30):        if not cb.allow_request():            print("第 {0:2d} 次: 被熔断拒绝 -> 走降级兜底".format(i))            cb.try_half_open()            continue        ok = fake_call()        cb.record(ok)        print("第 {0:2d} 次: {1:2s}, 当前状态={2}".format(            i, "成功" if ok else "失败", cb.state))  if __name__ == '__main__':    main()
目的:用 30 行 Python 模拟 Resilience4j 熔断器的三态状态机,帮助你直观理解滑动窗口、失败率阈值和半开试探机制。
  1. class CircuitBreaker:定义一个三态熔断器类,状态分别为“关闭”“打开”“半开”。
  2. self.records.append(1 if ok else 0)把每次调用的结果写入滑动窗口,1 代表成功,0 代表失败。
  3. if self.failure_rate() >= self.failure_threshold:当窗口失败率达到 50% 阈值时,熔断器从“关闭”切到“打开”。
  4. if not self.allow_request():熔断器打开期间,新请求直接被拒绝,不再发起真实调用。
  5. cb.try_half_open()模拟冷却时间结束后,熔断器自动转半开,准备放行试探请求。

常见误区

误区很多初学者以为熔断器打开后,请求还是会被发送到下游,只是多了一个告警而已,下游慢就慢慢等呗。

正解大错特错。熔断器一旦从关闭切换到打开,后续请求会在本层直接被拦截,根本不发往下游,直接抛出异常或走降级逻辑。就像地铁跳闸后电流被完全切断,而不是继续流过去再亮个警告灯。

为何常见:因为“熔断”这个词容易让人联想到保险丝烧断后电路仍然连着,实际上熔断器的本质是彻底隔离故障源。

误区下游偶尔超时,我多配几次重试,最多重试 10 次,总能成功吧?反正调用方等得起。

正解重试是把双刃剑。10 个调用方同时重试 10 次,等于把原本 10 个请求放大成 100 个请求,下游瞬间被流量风暴打垮,雪崩反而更严重。正确做法是控制重试次数(2-3 次)并配合指数退避。

为何常见:人天生倾向于“再试一次会更好”,却忽略了系统中的重试是并发叠加的,不是单线程的。

误区有人把 RateLimiter 理解成“同时最多处理 100 个请求”,以为它和线程池限制是一样的。

正解RateLimiter 限制的是“每秒处理请求的速率”,本质是令牌桶,管的是流量速度;而线程池或信号量限制的是“同时存在的活跃请求数”,管的是并发规模。一个是水龙头流速,一个是水池容量,完全是两个维度。

为何常见:在很多中间件里“限流”和“并发控制”的措辞混用,导致概念被混淆。

误区有的开发图省事,降级方法直接 `return null`,觉得只要不抛异常就算兜底了。

正解返回 null 会让调用方在拿到结果解引用时抛出空指针异常,等于把故障从下游转移到了上游。降级响应应该是有业务含义的,比如返回空列表、缓存数据或默认文案。

为何常见:因为写一个“啥也不干”的降级最快,但恰恰是这种偷懒让故障在链路里继续传播。

误区听到“隔离”两个字,有人以为 Bulkhead 是类似数据库事务隔离级别的东西,用来保证数据一致性。

正解Bulkhead 的隔离发生在资源层面,本质是给不同的下游调用分配独立的线程池或信号量,防止一个依赖耗尽所有资源连累其他依赖。它和数据库隔离级别完全是两回事。

为何常见:同一个词在分布式系统和数据库领域含义差异巨大,初学者容易张冠李戴。

面试题

Q1. 熔断器处于打开状态时,新的请求会怎样处理?

单选题 · easy

  • A.照常发送给下游服务
  • B.直接快速失败不发送← 正确答案
  • C.排队等下游服务恢复
  • D.转发给另一个机房处理

答案:B。熔断器打开时,请求会在本层被直接拦截并快速失败,不会发往下游。就像电箱跳闸后电流被彻底切断,而不是继续流向电器。

Q2. 下列哪个是 Resilience4j 相比 Hystrix 的核心设计优势?

单选题 · easy

  • A.强制继承特定父类
  • B.函数式 API 和模块化← 正确答案
  • C.依赖重量级网络框架
  • D.必须搭配 Spring Cloud

答案:B。Resilience4j 基于函数式接口设计,用装饰器模式给方法加防护,且各模块独立发布、按需引入,比 Hystrix 的继承式命令模式更轻量灵活。

Q3. RateLimiter 的令牌桶机制中,令牌是如何产生的?

单选题 · mid

  • A.启动时一次性生成
  • B.每隔周期匀速补充← 正确答案
  • C.每次请求后自动回收
  • D.由下游服务动态返回

答案:B。令牌桶按固定刷新周期匀速补充令牌,每个周期补充固定数量。请求必须消耗令牌才能被放行,没有令牌则等待或拒绝。

Q4. 熔断器从打开状态转为半开状态的主要目的是什么?

单选题 · mid

  • A.彻底关闭所有调用
  • B.试探服务是否恢复← 正确答案
  • C.增加并发等待队列
  • D.把实例从注册中心下线

答案:B。半开状态放行少量试探请求,根据试探结果决定是恢复关闭还是继续打开,避免服务恢复后无法自动合闸。

Q5. 关于指数退避策略,下列说法哪项是正确的?

单选题 · mid

  • A.每次重试间隔逐步拉大← 正确答案
  • B.重试间隔逐步缩小加快
  • C.所有重试间隔都完全相等
  • D.重试间隔由请求方任意决定

答案:A。指数退避让等待时间按 \(2^{n-1}\) 倍递增,逐步拉大间隔,给下游留出恢复时间,同时避免重试风暴。

Q6. 以下哪种响应方式适合作为 Fallback 降级兜底?

单选题 · mid

  • A.把异常重新抛给上层
  • B.返回缓存或友好提示← 正确答案
  • C.无限循环重试直到成功
  • D.创建新的线程池继续等待

答案:B。降级应该返回有业务含义的兜底数据,如缓存结果、空列表或默认文案,既保证接口有响应,又不会让调用方产生空指针等次生故障。

Q7. Bulkhead 舱壁隔离在 Resilience4j 中主要用于隔离什么?

单选题 · hard

  • A.隔离下层数据库表
  • B.隔离不同依赖的调用资源← 正确答案
  • C.隔离微服务的网络分区
  • D.隔离本地磁盘读写空间

答案:B。Bulkhead 给不同下游依赖分配独立的线程池或信号量,让一个依赖的资源耗尽不影响其他依赖,类似轮船的水密隔舱设计。

Q8. 以下哪些失败场景适合配置 Retry 重试机制?

多选题 · mid

  • A.下游返回 5xx 服务器错误← 正确答案
  • B.下游请求超时或网络闪断← 正确答案
  • C.请求参数校验失败返回 400
  • D.连接池瞬时耗尽导致异常← 正确答案

答案:ABD。临时性故障如 5xx、超时、网络闪断、连接池瞬时耗尽都适合重试;参数校验错误是请求本身的问题,重试多少次都不会成功。

Q9. 下列哪些属于 Resilience4j 的独立功能模块?

多选题 · hard

  • A.resilience4j-circuitbreaker← 正确答案
  • B.resilience4j-retry← 正确答案
  • C.spring-cloud-gateway
  • D.resilience4j-ratelimiter← 正确答案

答案:ABD。Resilience4j 按功能拆分为熔断、重试、限流、舱壁等独立 jar 包,按需引入;spring-cloud-gateway 是网关框架,不属于 Resilience4j 模块。

Q10. 关于熔断器的滑动窗口统计,下列说法正确的有哪些?

多选题 · extreme

  • A.滑动窗口只统计最近 N 次调用← 正确答案
  • B.成功请求和失败请求都计入窗口← 正确答案
  • C.窗口记录数量会无限增长
  • D.失败率等于失败数除以总调用数← 正确答案

答案:ABD。滑动窗口有固定大小,记录最近 N 次调用,超过上限会淘汰最旧记录,因此不会无限增长。失败率就是窗口内失败数除以总调用数,这是触发熔断的判断依据。