RPC 用着好好的?为什么还需要使用 MQ?

简介: 阿粉之前看了一场架构师之路沈剑老师的一场直播,最近又重温了一下,根据自己的认知总结了一下,分享给大家。

阿粉之前看了一场架构师之路沈剑老师的一场直播,最近又重温了一下,根据自己的认知总结了一下,分享给大家。

MQ 想必大家或多或少都用过,接入 MQ 之后的整体架构如下:

47.jpg可以看到使用 MQ 之后,上下游通信就变成图上的这种方式。

这种跨进程的通信方式,我们还有一种常用的解决方案,使用 Dubbo 等这类 RPC 服务。

理论上使用 RPC 的跨进程通信的场景,使用 MQ 也能解决,当然反过来也能说通。

那为什么不都用 RPC,或者 MQ 来解决那

这其实都是业务场景决定的,抛开业务场景来谈架构都是耍流氓!没有全能的架构,只要适合的架构。

下面我们来看看哪些场景适合 RPC,而哪些场景适合 MQ。

RPC 场景

使用 RPC 的场景一般都是上游服务需要实时依赖下游服务的返回。

我们以一个登录服务为例,架构图如下:

48.jpg


用户发起的登录请求首先由对外的 WEB 服务接受,然后 WEB 服务服务调用用户服务查询用户信息,然后比对用户密码。

也就是说我们的 WEB 应用需要实时依赖用户服务返回的用户信息,如果没有返回,这次登录将会失败。

假如这个场景我们用 MQ 代替, WEB 应用发送 MQ 消息之后,然后流程就结束了,此时 WEB 应用无法拿到用户信息。

所以说对于这种需要强依赖下游返回的场景,使用 MQ 将会带来以下不足:

  • 上游无法直接得到下游结果
  • 增加一个 MQ 组件,系统更复杂

MQ 场景

上游不关心下游结果的场景

举个例子,在我们第三方支付系统中,每支付成功一笔,都需要计算手续费。

49.jpg

这个场景我们显然可以使用 RPC 完成调用,但是实际上,支付系统是不关心的计费系统的结果,两个系统不存在直接强依赖的关系。

大家可以想象一下,用户实际上已经收到银行卡扣款短信了,但是支付系统因为计费系统失败,导致对外返回是失败的结果。这对于用户来讲,不能接受啊。我都付钱了,你却告诉我支付异常。

所以对于这种场景,直接使用 RPC 调用由以下几点不足:

  • 系统整体调用延时增加
  • 下游服务异常,影响上游服务。两者物理以及逻辑依赖严重
  • 若后面再增加一个下游系统,需要知道支付成功的结果,上游系统需要改动代码。这种情况对于上游情况来讲,就会很烦。明明与上游系统没有什么关系,却需要修改代码。

那一定要用 MQ 解决吗?

其实不一定,对于我们上面举的场景,我们其实可以使用异步 RPC 或者线程池异步调用 RPC 就可以解决。

毕竟增加一个 MQ, 系统就变得更加复杂,我们还要单独运维 MQ,这对于小团队来讲,工作量还是很大的。

但是这种方式,还是解决不了,增加一个下游系统,上游系统还要改动的代码囧境。

增加 MQ 解耦

这个场景使用 MQ 解耦,带来几点优点:

  • 任务一:上游系统执行时间变短
  • 任务二:上下游逻辑解耦,物理解耦
  • 任务三:最重要一点,增加一个下游服务,其只要订阅即可,上游服务无需要改动代码

数据驱动的定时任务场景

举个例子,支付公司每日都需要对账,主要目的是核实自己系统的应收的钱与支付渠道端是否一致,主要流程分为以下几步:

  • 定时任务下载渠道对账文件,下载方式可能为 Http 接口下载,也有可能 SFTP 下载
  • 定时任务解析对账文件,然后将对账数据入库
  • 定时任务将自己本端支付数据与对账数据核对

上面的定时任务使用 Spring-Schedule 调度,假设各个定时任务下载时间如下所示:

image.jpeg

上图中三个任务,任务二需要依赖任务一完成,而任务三又需要依赖任务二完成。

我们之前使用这种模式,通常会碰到几个问题:

  • 通常 06:00 就能下载到对账文件,但是有时候渠道端对账文件延迟,就会导致任务一执行失败,这样就会后续两个定时任务也会执行失败
  • 假设任务二数据过多,执行时间过长,任务三执行时还没结束,这就导致任务三无法拿到全量数据,导致对账异常
  • 整体任务执行时间过长
  • 任务一若调整时间,可能导致任务二,任务三都需要调整时间

使用 MQ解耦

使用 MQ 解耦之后架构图如下:

51.jpg

这种方式,只要任务一的定时任务准时启动,任务一完成之后发送 MQ 消息,任务二收到之后就会启动任务,结束之后再发送消息给 MQ。任务三流程同任务二

使用这种方式存在优点为:

  • 下游任务只要收到消息就能立刻执行,不需要额外等待,整体任务执行时间变短
  • 上游任务时间变动,无需修改下游任务时间。我们这个例子,只需要任务一的实际即可

总结

对于上游需要关注下游返回结果的场景,不适合使用 MQ。

适合使用 MQ 的场景有:

  • 上游不关心下游结果的场景
  • 数据驱动的定时任务依赖
相关实践学习
RocketMQ一站式入门使用
从源码编译、部署broker、部署namesrv,使用java客户端首发消息等一站式入门RocketMQ。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
相关文章
|
1月前
|
消息中间件 缓存 API
|
8月前
|
消息中间件 存储 缓存
远程调用RPC和消息MQ区别
远程调用RPC和消息MQ区别
59 0
|
消息中间件 Dubbo 网络协议
rabbitmq高并发RPC调用,你Get到了吗?
rabbitmq高并发RPC调用,你Get到了吗?
741 0
rabbitmq高并发RPC调用,你Get到了吗?
|
消息中间件 Java RocketMQ
RocketMQ源码分析-Rpc通信模块(remoting)二
今天继续RocketMQ-Rpc通信模块(remoting)的源码分析。上一章提到了主要的start()方法执行流程,如果有不清楚的地方可以一起讨论哈,这篇文章会继续解读主要方法,按照惯例先看看NettyRemotingAbstract的类图,看类图知方法。和NettyEventExecutor以及MQ的交互流程。 按照惯例先看看NettyRemotingAbstract的类图,看类图知方法,文中会挑重要方法和主要流程解读。
415 0
RocketMQ源码分析-Rpc通信模块(remoting)二
|
消息中间件 编解码 网络协议
RocketMQ源码分析-Rpc通信模块(remoting)一
上篇文章分析了Rocketmq的nameServer的源码,在继续分析源码之前,先考虑一个问题,设计一个mq并且是高性能的mq最最核心的问题是什么,我个人认为主要是有俩个方面,1:消息的网络传输,2:消息的读写,这两个决定了mq的高性能。
488 0
RocketMQ源码分析-Rpc通信模块(remoting)一
|
消息中间件 存储 RocketMQ
消息中间件—RocketMQ的RPC通信(一)
消息队列的本质在于消息的发送、存储和接收。那么,对于一款消息队列来说,如何做到消息的高效发送与接收是重点和关键
2015 1
|
消息中间件 存储 RocketMQ
消息中间件—RocketMQ的RPC通信(一)
消息队列的本质在于消息的发送、存储和接收。那么,对于一款消息队列来说,如何做到消息的高效发送与接收是重点和关键。
2628 1
|
消息中间件 架构师 中间件
组队学架构之高并发架构系列:详解RPC远程调用和消息队列MQ的区别
RPC RPC(Remote Procedure Call)远程过程调用,主要解决远程通信间的问题,不需要了解底层网络的通信机制。 RPC框架 知名度较高的有Thrift(FB的)、dubbo(阿里的)。
3062 0