金庆的专栏

  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  423 随笔 :: 0 文章 :: 454 评论 :: 0 Trackbacks

避免RPC回调死锁


(金庆的专栏 2020.9)

今天发现一例 RPC 回调死锁,现象为一串相关的 RPC 调用全部超时失败。

A 调用 B 的 RPC, B 再回调 A, 形成一个 RPC 调用环后,
如果 A 调用 B 时先加了一个锁,然后 B 回调 A 时又需要这个锁,
而此时 A 正在等待 B 的 RPC 返回,之后才会释放锁,
这样就形成了死锁。这个 RPC 调用环最终会全部超时失败。

这个调用环可能会涉及多个服务,如 A->B->C->...->A。

避免回调死锁有以下方法。

## 避免回调,不要有 RPC 调用环

一般的服务依赖应该都是无环的。
可以画一个服务依赖图,如果没有形成调用环,就可以放心不会有死锁。

## RPC 调用时不要加锁

一般进入某个 RPC 处理时,会锁住相关的资源,直到处理完成。
如果处理过程中需要向外发出 RPC 请求,应该先释放锁,待请求完成后再次获取锁。
如果请求过程中需要禁止其他协程操作相关资源,也可以不释放锁,
但锁的使用上应该允许加锁失败,不要等待锁。

锁应该是能够快速释放的。如果需要加锁去执行一个长时间的操作,
这个锁的设计可能需要重新考虑。

## 打断调用链

有时候 RPC 调用链不必是阻塞等待的。
如通知性的,无返回值的RPC, 不需要等待他返回,可以开一个新的协程去执行 RPC.
父RPC等待子RPC返回,改为父RPC直接返回,子RPC后台执行,即断开 RPC 的调用依赖。
RPC 调用链断开成多段后,调用循环的可能性就大大下降了。
posted on 2020-09-19 13:56 金庆 阅读(506) 评论(0)  编辑 收藏 引用 所属分类: 9. 其它

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理