作者简介:李智慧,前阿里巴巴技术专家。
本文选自:拉勾教育专栏《架构师的 36 项修炼
就程序员而言,日后的职业发展可以走 3 个方向:专攻技术深度、转团队管理、晋升架构师。
成为一名优秀的架构师,是大多数技术人的追求。但资深架构师的出现几率仅约为 0.3%。
如果想在 3-5 年后稳坐金字塔尖,必须有扎实的代码功底和项目积累,也要意识地培养技术广度和架构思维能力。多学习牛人经验也可获益良多。
我是李智慧,我从事构已有 20 多年。屏幕前的你,既然选择了架构,就要踏实学好每一块知识。
今天我们来讲分布式消息队列 MQ。在本篇幅中,我会主要介绍同步架构异步架构的区别。 
01  同步调用
所谓的同步调用,就是说从请求的发起一直到最终的处理完成期间请求的调用方一直在同步阻塞等待调用的处理完成
我们看一下图片中的例子,在这个例子中客户端代码 ClientCode,需要执行发送邮件 sendEmail 这样一个操作,它会调用 EmailService 进行发送。
而 EmailService 会调用 SmtpEmailAdapter 这样一个类来进行处理,而这个类会调用远程的一个服务,通过 SMTP 和 TCP 协议把请求发送给它。
而远程服务器收到消息以后会对消息进行一系列的操作,然后将邮件发送出去,再进行返回。
Adapter 收到返回后,再返回给 EmailService,EmailService 收到返回后再把返回结果返回给 Clientcode。
ClientCode 在 sendEmail 发出请求后,就一直都阻塞在这里,等待最终调用结果的返回,是成功还是失败。因为这个过程是阻塞等待的,所以这个过程也就是同步调用。
02步调用
与同步调用相反的是异步调用。异步调用过程,我们同样看刚刚发送邮件的例子,用户 Clientcode 调用 EmailService 以后,EmailService 会把这个调用请求发送给消息队列,然后就立即返回了。
Clientcode 收到返回以后继续向下处理,不会继续阻塞等待。实际上消息发送到 Queue 后,还没有被处理,我们看到后面的消息消费,其实要比 EmailService 返回可能还要晚一点,EmailService 返回以后消息才会被消费处理。
有一个 QueueConsumer 消息队列的消费者,从消息队列中取出这个消息,再把这个消息发送给 SmtpAdapter,也就是调用 SmtpAdapter。
处理逻辑跟同步调用一样,SmtpAdapter 通过 SMTP 的通讯协议,把消息发送给远程的一个服务器,进行邮件发送,通过 RemoteServer 进行处理,处理完了收到返回,再把返回结果通知消息队列 Queue。
我们看到,在这个过程中,客户端的调用,也就是应用程序的调用,和业务逻辑真正发送邮件的操作是不同步的。
在进行邮件发送操作的处理过程中,客户端的代码已经返回了,它可以继续进行自己的后续操作,而不需要等待邮件的发送,这就叫做异步调用
使用异步调用架构的主要手段,就是通过消息队列构建。这是它的架构图。
消息的生产者将消息发送到消息队列以后,由消息的消费者从消息队列中获取消息,然后进行业务逻辑的处理,消息的生产者和消费者是异步处理的,彼此不会等待阻塞,所以叫做异步架构。
使用消息队列构建一个异步调用架构,你需要了解3种角色,一种是消息的生产者,一种是消息队列,还有一种是消息的消费者。
01
消息的生产者
消息的生产者是客户端应用程序代码的一部分,用来初始化异步调用处理流程。
在基于消息队列的处理中,生产者的职责非常少,它要做的就是创建一个合法的消息,并把这个消息发送到消息队列中,由应用开发者决定生产者的代码在哪里执行,什么时候发送消息。
02
消息队列
消息队列异步架构的另一个主要组成部分就是所谓的消息队列。
消息队列是消息发送的目的地和发给消费者的一个缓冲。消息队列实现的方法有好多种,可以用共享文件夹,也可以用关系数据库或者 NoSQL 系统。
当然最主要的还是使用专门的分布式消息队列服务器来实现。
03
消息的消费者
业务架构的第三个重要角色就是消息的消费者。消息的消费者从消息队列中接受并处理消息,消息的消费者也是由应用开发者实现的,但是它是一个异步处理的组件。
消息的消费者不需要知道生产者存在,它只依赖消息队列中的消息。消息的消费者通常部署在独立的服务器上,和消息的生产者完全隔离,并且可以通过添加硬件的方式进行伸缩。
知道以上 3 种主要角色之后,使用消息队列构建异步的调用架构,你还需要知道两种模型:点对点模型和发布订阅模型。
点对点模型
首先来看点对点模型。消费者和生产者只需要知道消息队列的名字,生产者发送消息到消息队列中,而消息队列的另一端是多个消费者竞争消费消息。
每个到达消息队列的消息只会被路由到一个消费者中去,所以消费者看到的是全部消息的一个子集。
我们看这张图,消息的生产者有多个,消息的消费者也有多个,多个生产者将消息发送到消息队列中,而有多个消费者去消息队列中对消息进行竞争性的消费。
每条消息只会被一个消费者消费,每个消费者只会消费消息队列中的一部分消息。
发布订阅模型
在发布订阅模型中,消息可能被发送到不止一个消费者,生产者发送消息到一个主题,而不是队列中。
消息被发布到主题后,就会被克隆给每一个订阅它的消费者,每个消费者接收一份消息复制到自己的私有队列。
消费者可以独立于其他消费者使用自己订阅的消息,消费者之间不会竞争消息。
常用的分布式消息队列都支持发布订阅模型,也就是说消息的发布订阅模型是分布式消息队列的一个功能特性。
两种模型结合对比来看,通常使用点对点模型的,是一些耗时较长的、逻辑相对独立的业务,比如说我前面的讲到的发送邮件这样一个操作。
因为发送邮件比较耗时,而且应用程序其实也并不太关心邮件发送是否成功,发送邮件的逻辑也相对比较独立,所以它只需要把邮件消息丢到消息队列中就可以返回了。
而消费者也不需要关心是哪个生产者去发送的邮件,它只需要把邮件消息内容取出来以后进行消费,通过远程服务器将邮件发送出去就可以了。而且每个邮件只需要被发送一次。所以消息只被一个消费者消费就可以了
相对应的另一种情况,比如新用户注册,一个新用户注册成功以后,需要给用户发送一封激活邮件,发送一条欢迎短信,还需要将用户注册数据写入数据库,甚至需要将新用户信息发送给关联企业的系统,比如淘宝新用户信息发送给支付宝。
这样允许用户可以一次注册就能登录使用多个关联产品。那么对于新用户注册这样一个消息,就需要使用按主题发布的方式,也就是发布订阅模型这种方式。
一个新用户注册,会把注册消息发送给一个主题,多种消费者可以订阅这个主题。比如发送邮件的消费者、发送短信的消费者、将注册信息写入数据库的消费者,跨系统同步消息的消费者等。 
今天就讲到这里啦~感谢你的坚持,下一课我会详细讲解分布式数据库相关内容,分享我的实践经验。加油,我们不见不散!
版权声明:本文版权归属拉勾教育及该专栏作者,任何媒体、网站或个人未经本网协议授权不得转载、链接、转贴或以其他方式复制发布/发表,违者必究。
“阅读原文”学习《架构师的 36 项修炼》
继续阅读
阅读原文