第 9 章:交互冗余:重试和其他控制循环

本章深入探讨云原生系统中的交互冗余与重试机制,分析重试风暴的风险及预防措施,并介绍控制循环在分布式弹性架构中的关键作用。通过实际案例和实验,帮助读者理解如何平衡系统稳定性与故障恢复能力。

交互冗余与重试机制概述

在云原生架构中,服务间的请求不可避免地会遇到失败。与冗余服务实例类似,请求层面的冗余(如重试)也是提升系统弹性的关键手段。用户在网页加载失败时会选择刷新,软件同样应具备自动重试能力,但需合理控制重试行为,避免引发更严重的问题。

例如,访问 Hacker News 时,若页面加载失败,用户会刷新页面;但在电商网站下单失败时,重复请求可能导致重复订单。此时应先确认订单状态,再决定是否重试。对于机器客户端,重试频率和数量远高于人工操作,因此更需谨慎设计。

云原生交互模型与客户端重试

云原生系统中的交互双方通常是程序而非人类。客户端需模拟人类决策,如等待时长、重试次数及条件。合理的重试机制能提升系统容错性,但也可能带来负面影响。

下文将通过示例应用,逐步展示重试机制的实现、风险及优化方法。

请求重试的基本模式

请求重试模式:客户端向远程服务发起请求,若超时未响应则自动重试。以博客聚合程序为例,相关帖子服务作为客户端,向帖子服务发起 HTTP 请求并实现重试逻辑。

图 9.2 重试可以将分布式系统的某些部分与其他部分的错误隔离。
图 9.2 重试可以将分布式系统的某些部分与其他部分的错误隔离。

实际案例:简单重试实现

在实际部署中,可通过环境变量控制是否启用重试。相关帖子服务在请求失败时会进入循环重试,直到成功或达到最大重试次数。日志中可观察到每次重试的详细信息。

示例代码可简化为: “客户端在请求失败时,进入循环重试,直至成功或达到最大次数。每次重试均记录日志,最终返回结果或错误。”

合理设置连接超时和读取超时非常重要,过长会导致上游超时,过短则可能影响结果有效性。

重试机制的风险与重试风暴

重试机制虽能提升系统稳定性,但在高负载或大规模故障时,可能导致“重试风暴”。此时,大量排队重试请求会使系统雪上加霜,恢复时间大幅延长。

图 9.3 受限网络的行为就像受限的高速公路一样,请求的数量与以前相同。即使取消了限制,所有排队的流量也可能要花费一些时间才能再次移动。
图 9.3 受限网络的行为就像受限的高速公路一样,请求的数量与以前相同。即使取消了限制,所有排队的流量也可能要花费一些时间才能再次移动。

实验:重试风暴的影响

通过压力测试工具(如 JMeter)模拟高并发场景,观察在网络中断和恢复后的系统表现。实验结果显示,重试机制在故障期间会导致错误率飙升,恢复后系统需较长时间才能回归稳定。

说明:
“在高负载下,重试风暴会导致错误率持续高企,系统恢复时间显著延长。关闭重试机制则可实现快速恢复,但故障期间无法获得结果。”

优化重试:友好客户端设计

为平衡重试带来的正负影响,可通过以下方式优化客户端行为:

  • 限制最大重试次数
  • 在重试间引入延迟
  • 仅对特定异常类型进行重试

Spring Retry 框架可通过注解实现上述控制。例如,设置最大重试次数为 3,每次重试间隔 500 毫秒,仅对连接超时异常重试。

示例描述:
“使用 Spring Retry 注解,限定重试次数和间隔,自动处理特定异常,无需手动循环。”

实验:优化后的重试机制

在优化后的重试机制下,系统在故障恢复后能更快回归稳定状态,且在间歇性故障场景下显著降低整体错误率。

何时不应重试

重试机制仅适用于“安全”或“幂等”操作。对于非安全操作(如下单、扣款),重复请求可能导致副作用,应避免重试或采用补偿机制(如 Sagas)。

说明:
“开发者需确保仅对安全或幂等方法启用重试,避免因重复请求导致数据异常。”

回退逻辑与缓存机制

面向失败设计是云原生弹性架构的核心。重试失败后,可通过回退逻辑提升用户体验。例如,相关帖子服务在无法获取实时数据时,返回 Redis 缓存中的历史结果。

图 9.6 提前考虑,在结果可用时将结果缓存起来,以便以后出现问题时,可以将这些缓存结果作为回退逻辑的一部分。
图 9.6 提前考虑,在结果可用时将结果缓存起来,以便以后出现问题时,可以将这些缓存结果作为回退逻辑的一部分。

Spring Retry 支持 @Recover 注解,自动在重试失败后调用回退方法,返回缓存结果。

示例描述: “主逻辑失败后,自动调用回退方法,从缓存中读取并返回历史数据。”

实验:回退机制的效果

在负载测试下,启用回退机制后,相关帖子服务即使下游服务故障,仍能返回缓存结果,客户端无感知错误,系统稳定性显著提升。

控制循环模式

重试只是控制循环的一种具体实现。Kubernetes 等平台广泛采用控制循环(如副本控制器、守护程序集控制器等),持续监控并调整系统状态,实现最终一致性。

说明:
“控制循环通过不断比较实际与期望状态,自动修正系统偏差,是分布式系统弹性设计的基础。”

控制循环的参数与回退策略

控制循环可通过参数(如最大次数、间隔、异常类型)灵活调整行为。非线性回退策略(如 CrashLoopBackOff)能有效防止系统反复重启,提升整体稳定性。

总结

  • 合理设计重试机制可提升系统弹性,但需防范重试风暴风险。
  • 优化重试参数(次数、间隔、异常类型)可平衡稳定性与恢复速度。
  • 回退逻辑与缓存机制能显著提升故障期间的用户体验。
  • 控制循环是分布式系统弹性架构的核心模式,广泛应用于云原生平台。
  • 开发者需确保仅对安全或幂等操作启用重试,避免副作用。

参考文献

文章导航

独立页面

这是书籍中的独立页面。

书籍首页

评论区