RPC(Remote Procedure Call)是分布式系统机制的重要部分,被广泛使用
RPC消息传输:
RPC的软件结构:
RPC中 Client 可能会出现的 failure:
- Client 没有收到 Server 的回应
- Client 不知道 Server 是否收到了 Request(或许 Server/Net 在发送回复的时候失败了)
最简单的解决 failure 的方案:at-least-once
- RPC等待回应一段时间
- 如果没有收到回应,再发送请求
- 重复1、2数次
- 仍然没有收到回应,返回 APP 一个 error
Q:at-least-once对于 app 来说便于执行吗?
- 例:简单的问题:Client 发送“往我的银行账户上加10块钱”
Q:Client 程序将会发生什么?
- Put(“k”, 10) - - - 一个RPC操作,在数据库 Server 处设置 k 的值
- Put(“k”, 20) - - - 客户端发出了第二次请求来设置同一个 k
Q:at-least-once 可以正常运行吗?
- 可以:如果操作是可重复的,e.g. read-only 操作
- 可以:如果 app 有自己的重复写操作
更好的解决 failure 的方案:at-most-once
- Server RPC 会检测重复的请求,返回之前的回应而不是重新运行handler
Q:如何检测重复请求?
- Client 在发出请求时会附带一个唯一的 ID
- Server:
if seen[xid]:
r = old[xid]
else:
r = handler()
old[xid] = r
seen[xid] = True
Q:如何保证 XID 是唯一的?
- 很大的随机数
- 将 Client ID 与队列号结合起来,Server 最终一定会丢掉就的 RPC 的信息
Q:什么时候丢掉 RPC 的信息是安全的?
- Client 对每个 RPC 规定“必须看见之前 X 个回复”,与计算机网络中的 TCP 序列号与 ACK 帧的确认机制相似
- 或者 Client 一次只允许一个未解决的 RPC 存在,Server 收到 seq + 1 个消息会丢掉 <= seq 的消息
- 或者 Client 同意不断重试发送请求的时间不超过5分钟,Server 会丢掉超过5分钟的 RPC
Q:如果 at-most-once 服务器崩溃重启会怎么样?
- 如果 at-most-once 的重复信息是保存在内存,则重启服务器将导致忘记以前的信息,重启后继续接受重复的 Request
- 或许可以将重复信息写到硬盘中保存
- 或者复制服务器的时候也要复制重复信息