Appearance
一、缘起
一切脱离业务的架构设计与新技术引入都是耍流氓。
引入一个技术之前,首先应该解答的问题是,这个技术解决什么问题。
二、MQ是干嘛的
消息总线(Message Queue),后文称MQ,是一种跨进程的通信机制,用于上下游传递消息。
在互联网架构中、MQ是一种非常常见的上下游“逻辑解耦+物理解耦”的消息通信服务。使用了MQ之后,消息发送上游只需要依赖MQ,逻辑上和物理上都不用依赖其他服务。
三、什么时候不适用消息总线
既然MQ是互联网分层架构中的解耦利器,那所有通讯都使用MQ岂不是很好?这是一个严重的误区,调用与被调用的关系,是无法被MQ取代的。
MQ的不足是:
1)系统更复杂,多了一个MQ组件
2)消息传递路径更长,延时会增加
3)消息可靠性和重复性互为矛盾,消息不丢不重难以同时保证
4)上游无法知道下游的执行结果,这一点是很致命的
结论:调用方实时依赖执行结果的业务场景,请使用调用,而不是MQ。
四、什么时候使用MQ?
场景一、数据驱动的任务依赖
什么是任务依赖
举个栗子,互联网公司经常在凌晨进行一些数据统计任务,这些任务之间有一定的依赖关系,比如:
task3需要使用task2的输出作为输入
task2需要使用task1的输出作为输入
这样的话,tast1, task2, task3之间就有任务依赖关系,必须task1先执行,再task2执行,载task3执行。
采用MQ的优点是:
不需要预留buffer,上游任务执行完,下游任务总会在第一时间被执行
依赖多个任务,被多个任务依赖都很好处理,只需要订阅相关消息即可
有任务执行时间变化,下游任务都不需要调整执行时间
需要特别说明的是,MQ只用来传递上游任务执行完成的消息,并不用于传递真正的输入输出数据。
场景二:上游不关心执行结果
上游需要关注执行结果时要用“调用”,上游不关注执行结果时,就可以使用MQ了。
举个栗子,58同城的很多下游需要关注“用户发布帖子”这个事件,比如招聘用户发布帖子后,招聘业务要奖励58豆,房产用户发布帖子后,房产业务要送2个置顶,二手用户发布帖子后,二手业务要修改用户统计数据。
对于这类需求,常见的实现方式是,使用调用关系:
帖子发布服务执行完成之后,调用下游招聘业务、房产业务、二手业务,来完成消息的通知,但事实上,这个通知是否正常正确的执行,帖子发布服务根本不关注。
这种方法的坏处是:
- 帖子发布流程的执行时间增加了
- 下游服务当机,可能导致帖子发布服务受影响,上下游逻辑+物理依赖严重
- 每当增加一个需要知道“帖子发布成功”信息的下游,修改代码的是帖子发布服务,这一点是最恶心的,属于架构设计中典型的依赖倒转,
优化方案是,采用MQ解耦:
帖子发布成功后,向MQ发一个消息
哪个下游关注“帖子发布成功”的消息,主动去MQ订阅
采用MQ的优点是:
上游执行时间短
上下游逻辑+物理解耦,除了与MQ有物理连接,模块之间都不相互依赖
新增一个下游消息关注方,上游不需要修改任何代码
场景三:上游关注执行结果,但执行时间很长
有时候上游需要关注执行结果,但执行结果时间很长(典型的是调用离线处理,或者跨公网调用),也经常使用回调网关+MQ来解耦。
举个栗子,微信支付,跨公网调用微信的接口,执行时间会比较长,但调用方又非常关注执行结果,此时一般怎么玩呢?
一般采用“回调网关+MQ”方案来解耦:
调用方直接跨公网调用微信接口
微信返回调用成功,此时并不代表返回成功
微信执行完成后,回调统一网关
网关将返回结果通知MQ
请求方收到结果通知
这里需要注意的是,不应该由回调网关来调用上游来通知结果,如果是这样的话,每次新增调用方,回调网关都需要修改代码,仍然会反向依赖,使用回调网关+MQ的方案,新增任何对微信支付的调用,都不需要修改代码啦。
转自微信公众号 架构师之路
