什么时候用RPC,什么时候用MQ?
很多人认为,MQ是解耦架构的利器,能用MQ就尽量避免用RPC,这种说法对吗?
什么时候用RPC?
当调用方需要关心执行结果时,通常使用RPC。
例如,登录页面需要调用passport服务,依据passport服务返回的结果,来决定登录是否成功、失败或发生错误:
ret = PassportService::userAuth(name, pass);
switch(ret){
case(YES) : return YesHTML();
case(NO) : return NoHTML();
case(JUMP) : return 304HTML();
default : return 500HTML();
}
在这种场景下,调用方关心结果,所以选择RPC。
如果强行用MQ来解耦?
如果用MQ来通信,调用方无法直接获知登录是否成功,必须等待MQ通知回调。这不仅会让代码复杂化,还可能引入消息丢失的风险。中间增加一个MQ环节,实际上没有太大意义,几乎没人会这样做。
那是不是所有情况都用RPC呢?
并不是。若调用方不关心执行结果,强行使用RPC,会导致严重的耦合和性能瓶颈。
典型场景
假设有一个“帖子发布”服务,它是公司通用的业务功能。在用户发布帖子时,多个下游服务可能会关注这个事件,举例如下:
- 大数据部门需要更新用户画像;
- 信息质量部门要异步检查帖子合规性;
- 招聘业务需要为招聘帖增加积分;
- 其他个性化业务等。
这些下游服务关心事件的发生,但并不关心“帖子发布”服务是否成功。如果“帖子发布”服务通过RPC来通知下游服务,就会遇到一些问题。
为什么会耦合?
“帖子发布”服务本应是一个基础服务,正常情况下,调用者(比如upper)通过RPC通知下游(比如biz1/biz2/biz3):
- 每当有新的需求时,修改代码的依然是基础服务的负责人(upper),这会让人很不爽。
- 如果下游服务出现问题,可能会影响到上游的基础服务,造成更大的麻烦。
- 当下游服务接口升级时,上游基础服务需要配合修改,带来额外负担。
这种架构会导致强耦合,工作中的痛点就显现出来了。
如何解耦?
如果事件发布者不关心下游的执行结果,应该使用MQ,而不是RPC。
MQ可以做到上下游的物理解耦和逻辑解耦:
- 物理解耦:引入MQ后,上游服务和下游服务不再直接连接,而是通过MQ进行通信。
- 逻辑解耦:上游服务无需知道下游服务的存在,也不需要知道谁在订阅消息。新增订阅者只需连接MQ,其他服务不需要关注。
总结
MQ是常用的解耦工具,适用于物理和逻辑层面的解耦:
- 关注执行结果:使用RPC;
- 不关注执行结果:使用MQ。
这个简单的优化对解耦通知系统非常有效,关键是理解其背后的思路,而不仅仅是结论。
- END