本文转载自微信公众号「HHFCodeRv」,作者haohongfan。转载本文请联系HHFCodeRv公众号。
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 的一个函数,得到一个返回结果。
再简单点,是不是可以拆分下面两个过程:
- Client 发起一个调用到 Server
- 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 只是一种理论,但是高可用无法保障,而且对业务开发来说就更加黑盒了,出现问题就只能干瞪眼了,不建议业务开发实践。