Exactly when to use MQ

Disclaimer: The following article comes from the way the architect, the author Shen Jian 58 

Components from the business of introducing any bullying. The introduction of a component, the first question to answer is, this component to solve the problem.

What is MQ

Message bus (Message Queue), hereinafter called the MQ, a communication mechanism across the process for the delivery message downstream. Voice-over: usually not on the same server both processes.

In the Internet architecture, MQ is often used as a "downstream decoupling":

  1. The message sender only rely MQ, a consumer who is not concerned;
  2. Message consumer only rely MQ, does not care who the sender is;

Vo: the sender and the consumer, not dependent on each other logically and physically.

When not in use MQ?

When a caller needs to be concerned about the results of the message is not normally used MQ, using RPC calls.

ret = PassportService::userAuth(name, pass);

switch(ret){

    case(YES) : return YesHTML();

    case(NO) : return NoHTML();

    case(JUMP) : return 304HTML():

    default : return 500HTML();

}

As illustrated, the upstream Passport service calls, the results of different treatments, different logic operations may go processing branches (successful login, the login fails, execution errors, etc.), i.e., "the processing result of the strong dependence", RPC calls should be used at this time. Voice-over: the vast majority of cases, you should use the RPC.

At this point if forced to use MQ it?

If forced to use MQ communication, the caller can not directly tell the user login success and or failure, will have to wait for another MQ notification callback. So to play, not only makes coding complexity, also introduce the risk of message loss, adding a layer of a multi-center, superfluous.

What MQ when using it?

The following four typical scenario, you should use MQ.

A typical scenario: data-driven task dependencies

What is task-dependent : For chestnuts, Internet companies often make some statistics task in the morning, there is a certain dependencies between these tasks, such as:

  1. task3 task2 output required as input;
  2. task2 task1 output required as input;

这样的话,tast1, task2, task3之间就有任务依赖关系,必须task1先执行,再task2执行,载task3执行。

对于这类需求,通常怎么实现呢?常见的玩法是,crontab人工排执行时间表

如上图,手动设定如下:

  1. task1,0:00执行,经验执行时间为50分钟;
  2. task2,1:00执行(为task1预留10分钟buffer),经验执行时间也是50分钟;
  3. task3,2:00执行(为task2预留10分钟buffer);

crontab手动排表有什么坏处呢?

  1. 如果有一个任务执行时间超过了预留buffer的时间,将会得到错误的结果,因为后置任务不清楚前置任务是否执行成功,此时要手动重跑任务,还有可能要调整排班表;
  2. 总任务的执行时间很长,总是要预留很多buffer,如果前置任务提前完成,后置任务不会提前开始;
  3. 如果一个任务被多个任务依赖,这个任务将会称为关键路径,排班表很难体现依赖关系,容易出错
  4. 如果有一个任务的执行时间要调整,将会有多个任务的执行时间要调整

无论如何,采用“crontab排班表”的方法,各任务严重耦合,谁用过谁痛谁知道。画外音:用过的,痛过的,请留言。

应该如何优化呢?采用MQ解耦。

如上图,任务之间通过MQ来传递“开始”与“结束”的通知:

  1. task1准时开始,结束后发一个“task1 done”的消息;
  2. task2订阅“task1 done”的消息,收到消息后第一时间启动执行,结束后发一个“task2 done”的消息;
  3. task3同理;

采用MQ有什么好处呢?

  1. 不需要预留buffer,上游任务执行完,下游任务总会在第一时间被执行;
  2. 依赖多个任务,被多个任务依赖都很好处理,只需要订阅相关消息即可
  3. 有任务执行时间变化,下游任务都不需要调整执行时间

需要特别说明的是,MQ只用来传递上游任务执行完成的消息,并不用于传递真正的输入输出数据

典型场景二:上游不关心执行结果

上游需要关注执行结果时要用“RPC调用”,上游不关注执行结果时,使用MQ。举个栗子,58同城的很多下游需要关注“用户发布帖子”这个事件,比如:

  1. 招聘用户发布帖子后,招聘业务要奖励58豆;
  2. 房产用户发布帖子后,房产业务要送2个置顶;
  3. 二手用户发布帖子后,二手业务要修改用户统计数据;

对于这类需求,可以采用什么方式实现呢?

比较无脑的,可以使用RPC调用来实现:帖子发布服务执行完成之后,调用下游招聘业务、房产业务、二手业务,来完成消息的通知。但事实上,这个通知是否正常正确的执行,帖子发布服务根本不关注。

通过RPC来传递不需要知道处理结果的通知,有什么坏处呢?

  1. 帖子发布流程的执行时间增加了;
  2. 下游服务当机,可能导致帖子发布服务受影响,上下游逻辑+物理依赖严重;
  3. 每当增加一个需要知道“帖子发布成功”信息的下游,修改代码的是帖子发布服务;

画外音:这一点是最恶心的,属于架构设计中典型的反向依赖。

如何来进行优化呢?   采用MQ解耦,代替RPC。

如上图所示:

  1. 帖子发布成功后,向MQ发一个消息;
  2. 哪个下游关注“帖子发布成功”的消息,主动去MQ订阅;

如此一来,有什么好处呢?

  1. 上游执行时间短;
  2. 上下游逻辑+物理解耦,除了与MQ有物理连接,模块之间都不相互依赖;
  3. 新增一个下游消息关注方,上游不需要修改任何代码;

典型场景三:上游关注执行结果,但执行时间很长

有时候上游需要关注执行结果,但执行结果时间很长(典型的是调用离线处理,或者跨公网调用),也经常使用回调网关+MQ来解耦。举个栗子,微信支付,跨公网调用微信的接口,执行时间会比较长,但调用方又非常关注执行结果,此时一般怎么玩呢?

一般采用“回调网关+MQ”方案来解耦:

  1. 调用方直接跨公网调用微信接口;
  2. 微信返回调用成功,此时并不代表返回成功;
  3. 微信执行完成后,回调统一网关;
  4. 网关将返回结果通知MQ;
  5. 请求方收到结果通知;

这里需要注意的是,不应该由回调网关来RPC通知上游来通知结果,如果是这样的话,每次新增调用方,回调网关都需要修改代码,仍然会反向依赖,使用回调网关+MQ的方案,新增任何对微信支付的调用,都不需要修改代码。

总结

MQ是一个互联网架构中常见的解耦利器。

  1. 什么时候不使用MQ?上游实时关注执行结果,通常采用RPC。
  2. 什么时候使用MQ?
    (1)数据驱动的任务依赖;
    (2)上游不关心多下游执行结果;
    (3)异步返回执行时间长;
发布了694 篇原创文章 · 获赞 560 · 访问量 134万+

Guess you like

Origin blog.csdn.net/qq_36761831/article/details/104504079
Recommended