开发中的坑2:MQ 也能做 RPC 调用?

2021-10-01
4分钟阅读时长

hi, 大家好,我是 haohongfan。

最近浏览 帖子 的时候看到一个有意思的吐槽。

大概意思是架构师没有选用 RPC 框架来做服务间调用,而选择用 MQ 来代替。是不是很意外?

当然不出意外的,评论区炸了!

现在提出一些疑问:

  • 这个架构师的做法对吗 ?
  • MQ 是否能做 RPC 调用 ?

RPC 框架的职责

回答上面问题之前,稍微捋一下 RPC 框架。目前市面上比较流行的 RPC 框架其实并不多。

  • Java: SpringCloud,Dubbo 等
  • Go: Dubbogo,go-micro,rpcx,go-zero 等
  • 其他:Thrift,gRPC 等

当然还有其他的一些框架,这里就不再罗列。虽说 RPC 多如牛毛,但是大家干的事情基本都差不多,都是稳定,高效、准确的进行服务间远程调用。

说起 RPC 应该大部分人下意识会联想到 gRPC,不过 gRPC 只提供的了服务间通信的能力,但却没有开源对应的服务治理的能力,需要进行二次开发。Thrift 也是同样的问题。

下面以 Dubbogo 为例,大概介绍下 Dubbogo 实现的功能。

Dubbo-go 还有下面这些特点:

  • 传输支持 http2
  • 双向流模式 rpc
  • 应用级服务发现
  • 跟 Dubbo(Java) 版本对齐,互相之间能稳定通信,同时也打通与其他微服务框架的通信,如:SpringCloud、gRPC

综上,Dubbo-go 为了保证数据准确、高效、稳定传输,做了各种各样的架构设计。随着 dubbo 3.0 的发布,在易用性、超大规模微服务实践、云原生基础设施适配等几大方向上进行了全面升级。

MQ 代替 RPC ?

接着说 MQ 是否能替代 RPC。先看看 MQ 被写进八股文里面的几大特性:

  • 服务间解耦
  • 最终一致性
  • 流量削峰
  • 异步消费

MQ 是微服务框架中必不可少的一环,上面的特性是我们日常开发中最常用的。这些特性确实能让系统的稳定性得到增强,同时也让系统的构建出现更多的可能性。

但是是否能让 MQ 来代替 RPC,做服务间的调用?回答这个问题之前,我们再来看看 RPC 是如何工作的。

大概流程(资料节选 dubbogo website)

  • 类似本地调用,Client 调用远程服务
  • Client stub 收到调用,把调用方法、参数序列化
  • Client 通过 socket 把消息发送到服务端
  • Server stub 收到消息后,将消息对象反序列化
  • Server stub 根据解码结果调用本地的服务,并将结果返回给 Server stub
  • Server stub 将返回结果序列化,通过 sockets 将消息发送到客户端
  • Client stub 接收到结果消息,对返回消息反序列化
  • 客户端得到最终结果

简单概括下 RPC 调用就是 Client 通过 TCP 调用 Server 的一个函数,得到一个返回结果。

再简单点,是不是可以拆分下面两个过程:

  1. Client 发起一个调用到 Server
  2. Server 返回一个结果到 Client

那么是不是可以用 MQ 模拟这个过程。

当然这个流程并不是我瞎写的,这是 RabbitMQ 的官方教程 Remote procedure call (RPC),有兴趣的可以看文末的参考链接。

RabbitMQ tutorial 这篇文章基本就是 MQ 代替 RPC 的理论支持,所以文章开篇帖子提到的 Java 架构师的方案也不算无的放矢,也不算是错的。

MQ 代替 RPC 的真实情况

正常情况有点规模互联网公司内部都是会有一套 RPC 框架的,要么是基于开源版本的二次开发版本,要么完全自研的,使用过或者维护公司框架的都会被各种问题折磨到死,比如:限流、熔断、重试、服务注册发现、网络问题,SDK 升级等。

如果能用 MQ 代替 RPC 做服务间调用,那是不是只用维护一套 MQ 基础组件就可以了,既减少了人力的配置,又能将问题归纳。

理想很丰满,真相往往却很残酷。

如果你下意识去搜一下:用 MQ 代替 RPC 进行服务间通信,你会发现网上只有寥寥几个 Demo 而已,并没有太多真实实践。

没有太多实践 并不代表没有人在项目中实战过,比如那个 Java 架构师。曾经专门向朋友请教过这个设计,话说某大厂曾经在某个项目做了 MQ 代替 RPC 的实践,但是三个月不到这个项目就被毙了。所以你看不到这个设计方案的缺点:因为很多人不能把失败的案例放出来而已。

简单说下这个方案的缺点吧:

  • 本来 一次 TCP 通信就搞定的事情,用 MQ 后会被拆分成至少 二次 TCP,耗时增加不少。
  • 目前 MQ 大部分消费端是 Pull 模型,有一定的耗时成本
  • 服务间调用完全依赖于 MQ 的稳定性。从目前使用 MQ 经验来看,MQ 稳定性的维护成本比 RPC 复杂太多了。如果做异步调用还能容忍出错、延时,做同步调用的话,这些都是不能忽略的问题
  • 如果用 MQ 代替 RPC,那些 RPC 框架做的服务治理的事情,MQ 都需要实现一遍,工作量并没有减少
  • 。。。

现在说一下统一结论:

用 MQ 代替 RPC 只是一种理论,但是高可用无法保障,而且对业务开发来说就更加黑盒了,出现问题就只能干瞪眼了,不建议业务开发实践。

更多的坑,后续更新,欢迎关注公众号。更多学习学习资料分享,关注公众号回复指令:

  • 回复 0,获取 《Go 面经》
  • 回复 1,获取 《Go 源码流程图》

Avatar
HHFCodeRv 欢迎关注我的公众号:HHFCodeRv, 了解我的最新状态。