1043 字
5 分钟
RPC-rpc的失败模型和容错机制
2026-05-17
无标签

RPC通信模块(或传输)主要基于一组通信原语(IPC): makerpc(.), getRequest(.),和sendResponse(.) 其失败模型和容错机制也围绕着这些原语展开。

常见故障类型

alt text

总结下来就是“执行了没、执行了几次、结果在哪”。

RPC 容错的三大核心机制#

三个可以独立或组合使用的容错措施:

1. 重传请求(客户端侧)#

思想:控制是否重新传输请求服务,直到收到应答或假定服务器失败为止

问题:请求或回复消息可能丢失(网络丢包、服务器过载)。

方法:makerpc(.) 使用超时+重传机制。

  • 发送请求后启动定时器

  • 超时未收到回复,则重传请求

  • 可以重复多次,直到收到回复或认定服务器失败

挑战:如何选择超时值?

  • 太短:误判(服务器慢但未崩溃)

  • 太长:响应慢

  • 通常基于经验或统计(如 RTT 均值 + 偏差)

2. 重复过滤(服务器侧)#

思想:控制何时使用重传,以及是否在服务器上过滤掉重复的请求

问题:重传可能导致同一请求被执行多次(服务器处理完但回复丢失,客户端重传,服务器再次执行)。

危险:并非所有操作都是幂等的。多次执行结果相同的操作叫做幂等操作(如读取数据、设置键值)。多次执行结果不同的操作叫做非幂等操作(如扣款、转账)。

方法:服务器应识别来自同一客户端的重复请求。

  • 对请求使用单调递增序号(每个客户端的请求有自己的序号)

  • 收到已处理过的序号,则:

    • 选项 A:若操作幂等,直接重新执行并回复(简单但有风险)

    • 选项 B:保留之前的结果历史(在非易失存储中),直接重传上次的回复,不重新执行

3. 保留结果(服务器侧)#

思想:控制是否保留结果消息的历史记录,以便使丢失的回复能够重新传输,而无需在服务器上重新执行操作

问题:即使过滤掉重复执行,如果回复消息丢失,客户端重传,服务器还是得重新生成回复(要么重执行,要么从历史取)。

方法:服务器将已处理请求的回复消息保留在历史日志中(非易失存储)。

  • 收到重复请求时,直接重传历史回复,无需重新执行

适用于非幂等操作,也是实现最多一次语义的基础

代价:需要存储空间和持久化写入开销。

RPC的调用语义#

重传请求重复过滤保留结果/重传回复调用语义
N/AN/AMaybe(可能执行 0 或 1 次?实际可能因丢包而不执行)
重新执行程序至少一次(At Least Once)
最多一次(At Most Once)

Maybe 语义

  • 不做任何容错,客户端发一次请求,不重传

  • 结果:可能执行 0 次(丢包)或 1 次(成功)

  • 适用:容忍丢包的场景,如实时传感器数据

At Least Once 语义

  • 客户端重传,服务器不过滤重复

  • 结果:请求至少被执行一次,可能多次

  • 适用:幂等操作(如读、更新计数器但允许重复加)

  • 风险:非幂等操作会导致数据错误

At Most Once 语义

  • 客户端重传 + 服务器重复过滤 + 服务器保留历史回复

  • 结果:请求最多被执行一次,可能 0 次(如果服务器崩溃或消息永远丢失)

  • 适用:大多数业务操作(如转账、扣款)

  • 实现复杂:需要持久化存储请求序号和回复

受底层传输协议影响的调用语义#

UDP 需要 RPC 自己做重传;TCP 提供了可靠传输但仍需应用层端到端检查。

端到端论证:不能完全依赖底层可靠性,应用层需要自己的容错逻辑。

RPC-rpc的失败模型和容错机制
https://biscuit0613.github.io/posts/net_dist_sys/rpc-robustness/
作者
Biscuit
发布于
2026-05-17
许可协议
CC BY-NC-SA 4.0