本文转载自微信公众号《Java极客技术》,作者鸭血范。转载本文请联系Java极客技术公众号。阿芬看了建筑师之路沈建老师的一场直播,最近重温了一遍,结合自己的认知总结出来,分享给大家。MQ想必大家或多或少都用过。接入MQ后的整体架构如下:可以看到使用MQ后,上下游的通信就变成了图中所示的方式。对于这种跨进程通信方式,我们也有通用的解决方案,使用RPC服务,比如Dubbo。理论上,使用RPC进行跨进程通信的场景,使用MQ也可以解决,当然反过来也是有道理的。那为什么不用RPC或者MQ来解决呢?这其实是由业务场景决定的。抛开业务场景谈架构,简直是耍流氓!没有万能的架构,只有适合的架构。下面我们来看看哪些场景适合RPC,哪些场景适合MQ。RPC场景RPC场景一般在上游服务需要实时依赖下游服务返回时使用。我们以登录服务为例。架构图如下:用户发起的登录请求首先被外部WEB服务接受,然后WEB服务调用用户服务查询用户信息,然后比对用户密码。也就是说,我们的WEB应用需要依赖用户服务实时返回的用户信息。如果没有返回,则本次登录失败。如果我们在这个场景中改用MQ,WEB应用发送MQ消息后,流程结束,此时WEB应用无法获取到用户信息。所以对于这种需要高度依赖下游返回的场景,使用MQ会带来以下缺点:上游无法直接获取下游结果。添加一个MQ组件,系统就更复杂了。MQ场景上游不关心下游结果。比如在我们的第三方支付系统中,每笔成功的支付都需要计算手续费。在这种场景下,我们明明可以使用RPC来完成调用,但实际上,支付系统是计费系统不关心的结果,两个系统之间没有直接的强依赖关系。可以想象,用户其实收到了一条银行卡扣款短信,但是由于计费系统的故障导致支付系统出现故障,导致对外退货失败。这是用户无法接受的。我付了所有的钱,你却告诉我付款不正常。因此,对于这种场景,直接使用RPC调用有以下缺点:系统整体调用延迟增加。下游服务异常,影响上游服务。两者的物理和逻辑依赖性严重。如果后面增加下游系统,需要知道支付成功的结果,需要修改上游系统的代码。这种情况对于上游情况来说会很恼火。显然和上游系统没有关系,只是需要修改代码。一定要用MQ来解决吗?不必要。对于我们上面提到的场景,其实我们可以使用异步RPC或者线程池来异步调用RPC。毕竟加入一个MQ会让系统变得更加复杂,而且我们还要单独运维MQ,对于一个小团队来说工作量还是很大的。但是,这种方法仍然不能解决增加下游系统和更改上游系统代码的问题。添加MQ解耦本场景使用MQ解耦,带来几个好处:任务一:缩短上游系统的执行时间任务二:上下游逻辑解耦,物理解耦任务三:最重要的一点是增加一个下游服务,只需要订阅,上游服务不需要改代码数据驱动的定时任务场景。比如支付公司需要每天对账。流程分为以下几个步骤:定时任务下载渠道对账文件,下载方式可以是Http接口下载,也可以是SFTP下载定时任务解析对账文件,然后将对账数据放入数据库。对账数据检查上面的定时任务是使用Spring-Schedule进行调度的,假设每个定时任务的下载时间如下:上图中有3个任务,任务2需要任务1完成,任务3需要由任务2来完成。我们之前使用的是这种模式,通常会遇到几个问题:通常06:00可以下载到对账文件,但有时通道端对账文件会延迟,会导致任务失败一旦执行。计划任务也将无法执行。假设任务2数据量太大,执行时间太长,任务3执行时还没有完成。这样会导致task3无法获取到全量数据,导致对账异常。整体任务执行时间过长。Task1如果调整了时间,可能会导致Task2和Task3需要调整时间。使用MQ解耦。使用MQ解耦后,架构图如下:这样只要按时启动任务1的定时任务,任务1完成后发送MQ消息。2.收到后会启动任务,结束后会发送消息给MQ。在任务3和任务2的过程中使用这种方式的好处是:下游任务一收到消息就可以立即执行,无需额外等待,整体任务执行时间缩短。当上游任务时间发生变化时,无需修改下游任务时间。在我们的示例中,我们只需要对实际任务一进行总结。对于上游需要关注下游返回结果的场景,不适合使用MQ。适合使用MQ的场景有:上游不关心下游结果,数据驱动的定时任务依赖
