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

CoderPark

共 2509字,需浏览 6分钟

 · 2021-11-29

hi, 大家好,我是 haohongfan。

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

大概意思是架构师没有选用 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[2])

  • 类似本地调用,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)[3],有兴趣的可以看文末的参考链接。

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 只是一种理论,但是高可用无法保障,而且对业务开发来说就更加黑盒了,出现问题就只能干瞪眼了,不建议业务开发实践。

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


参考资料

[1]

帖子: https://www.toutiao.com/w/a1702697615869956/

[2]

dubbogo website: https://dubbo.apache.org/zh/blog/2019/01/07/%E6%B5%85%E8%B0%88-rpc/

[3]

Remote procedure call (RPC): https://www.rabbitmq.com/tutorials/tutorial-six-python.html

浏览 16
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报