任何引进倒闭的元器件都是耍流氓。在引入一个组件时,首先要回答的问题是这个组件解决什么问题。MQ,互联网技术体系中的一个常用组件,什么时候不用MQ,什么时候用MQ,MQ适用于哪些场景,就是今天要分享的内容。什么是微商?消息总线(MessageQueue),简称MQ,是一种跨进程的通信机制,用于上下游传递消息。画外音:这两个进程一般不在同一台服务器上。在互联网架构中,MQ常被用作“上下游解耦”:消息的发送方只依赖MQ,并不关心消费者是谁;消息的消费者也只依赖MQ,并不关心发送者是谁;消费者在逻辑上和身体上都相互依赖。什么时候不使用MQ?当调用方需要关心消息执行结果时,通常不使用MQ,而是使用RPC调用。ret=PassportService::userAuth(name,pass);switch(ret){case(YES):returnYesHTML();case(NO):returnNoHTML();case(JUMP):return304HTML():default:return500HTML();}如上例所示,上游调用Passport服务时,处理结果不同,业务会经过不同的逻辑处理分支(登录成功、登录失败、执行错误等),即“processingresultsarestronglydependent”,此时应该使用RPC调用。画外音:大多数情况下,应该使用RPC。如果这个时候强行使用MQ呢?如果强行使用MQ通信,调用方无法直接告诉用户登录成功或失败,必须等待另一个MQ通知回调。以这种方式播放不仅使编码复杂化,而且还引入了消息丢失的风险。不需要在中间添加额外的层。什么时候使用MQ?以下四种典型场景应该使用MQ。典型场景一:数据驱动的任务依赖(1)什么是任务依赖?例如,互联网公司经常在凌晨进行一些数据统计任务,这些任务之间存在一定的依赖关系,例如:task3需要使用task2的输出作为输入;task2需要使用task1的输出作为输入;在这种情况下,tast1、task2、task3之间存在任务依赖关系,必须先执行task1,然后执行task2,再执行task3。(2)你通常是如何实现这类要求的?一种常见的方法是使用crontab手动安排执行计划。如上图,手动设置如下:task1,0:00执行,体验执行时间为50分钟;task2,1:00执行(为task1预留10分钟缓冲),体验执行时间也是50分钟;task3,2:00执行(为task2预留10分钟的缓冲);手动调度crontab的缺点是什么?如果有一个任务的执行时间超过了预留的缓冲时间,就会得到错误的结果,因为后续任务不知道前驱任务是否执行成功,此时需要手动重新运行该任务,可能会需要调整时间表;总的任务执行时间很长,总是需要预留很多缓冲区。如果前置任务提前完成,则后继任务不会提前开始;如果一个任务依赖多个任务,这个任务就会被称为关键路径,进度表很难体现依赖关系,很容易出错;如果有一个任务执行时间需要调整,会有多个任务执行时间需要调整;无论如何,使用“crontabschedule”方式,任务耦合严重,用过的人都知道其中的痛点。画外音:如果你用过或伤害过它,请留言。(3)应该如何优化?使用MQ解耦。如上图所示,“开始”和“结束”的通知是通过MQ在任务之间传递的:task1准时开始,结束后发送“task1done”的消息;task2订阅“task1done”的消息,收到消息后第一个时间开始执行,结束后发送“task2done”消息;task3也是如此;(4)使用MQ有什么好处?无需保留缓冲区。上游任务执行完后,下游任务总会尽快执行。;依赖多任务,被多任务依赖好办,只需要订阅相关消息即可;任务执行时间有变化,下游任务不需要调整执行时间;需要特别注意的是,MQ只是用来传输上游任务的完成消息,并不用于传输真正的输入输出数据。典型场景二:上游不关心执行结果。当上游需要关注执行结果时,使用“RPC调用”。当上游不关心执行结果时,使用MQ。比如58同城很多下游会员需要关注“用户发帖”事件。例如:招聘用户发帖后,招聘商家奖励58豆;发布帖子后,二手商家需要修改用户统计;(1)可以用什么方法来实现这种需求?比较无脑,使用RPC调用即可实现:帖子发布服务执行后,调用下游招聘业务、房产业务、二手业务完成消息的通知。但实际上,发布服务并不关注通知是否正常执行。(2)使用RPC传输不需要知道处理结果的通知有什么缺点?帖子发布过程的执行时间增加;下游服务宕机,可能影响发布后服务,上下游逻辑+物理依赖严重;每当下游增加一个需要知道“发布成功”信息的下游时,就是发布服务修改代码;画外音:这是最恶心的一点,是架构设计中典型的反向依赖。(3)如何优化?使用MQ解耦代替RPC。如上图所示:帖子发布成功后,向MQ发送消息;无论哪个下游关注“帖子发布成功”的消息,并主动订阅MQ;(4)这样,有什么好处?上游执行时间短;下游逻辑+物理解耦,除与MQ物理连接外,各模块互不依赖;新增下游消息跟随器,上游无需修改任何代码。典型场景3:上游关注执行结果,但执行时间很长。有时上游需要关注执行结果,但是执行结果耗时较长(一般是调用离线处理,或者跨公网调用),往往使用回调网关+MQ解耦。比如微信支付,跨公网调用微信接口,执行时间会比较长,但是调用方很关心执行结果。这时候怎么玩?一般采用“回调网关+MQ”方案解耦:调用方跨公网直接调用微信接口;微信返回调用成功,不代表返回成功;微信执行完成后回调统一网关;网关将返回结果通知给MQ;请求者收到结果通知;这里有一些需要注意的地方,回调网关不应该使用RPC来通知上游通知结果。如果是这样的话,每增加一个新的调用者,回调网关都需要修改代码,它仍然会反向依赖。使用回调网关+MQ方案,添加对微信支付的任意调用不需要修改代码。结束语MQ是互联网架构中常用的解耦工具。什么时候不使用MQ?上游实时关注执行结果,通常使用RPC。什么时候使用MQ?数据驱动的任务依赖;上游不关心多个下游执行结果;异步返回需要很长时间才能执行;知其所以然,希望大家有所收获。【本文为专栏作者《58神剑》原创稿件,转载请联系原作者】点此阅读更多该作者好文
