分布式消息队列是是大型分布式系统不可缺乏的中间件,主要解决应用耦合、异步消息、流量削锋等问题。实现高性能、高可用、可伸缩和最终一致性架构。前端
对于一个架构师来讲,在大型系统设计中,会常常须要面对同步和异步等架构问题,搞明白这些问题,能更好地实现程序并行执行,减小等待或无效操做,以及充分利用计算机的性能!数据库
本文将详细讲解:1.同步架构和异步架构的区别后端
2.异步架构的主要组成部分:消息生产者、消息消费者、分布式消息队列服务器
3.异步架构的两种主要模型:点对点模型和发布订阅模型。微信
4.消息队列的好处架构
5.消息队列相关产品并发
建议用10min通读,搞懂分布式消息队列的核心内容。异步
1、同步架构和异步架构的区别分布式
1.同步调用 性能
是指从请求的发起一直到最终的处理完成期间,请求的调用方一直在同步阻塞等待调用的处理完成。
如图,在这个例子中客户端代码ClientCode,须要执行发送邮件sendEmail这样一个操做,它会调用EmailService进行发送,而EmailService会调用SmtpEmailAdapter这样一个类来进行处理,而这个类会调用远程的一个服务,经过SMTP和TCP协议把请求发送给它。
而远程服务器收到消息之后会对消息进行一系列的操做,而后将邮件发送出去,再进行返回。Adapter收到返回后,再返回给EmailService,EmailService收到返回后再把返回结果返回给Clientcode。
ClientCode在sendEmail发出请求后,就一直都阻塞在这里,等待最终调用结果的返回,是成功仍是失败。由于这个过程是阻塞等待的,因此这个过程也就是同步调用。
2.异步调用
是指在请求发起的处理过程当中,客户端的代码已经返回了,它能够继续进行本身的后续操做,而不须要等待调用处理完成,这就叫作异步调用。
异步调用过程,一样看刚刚发送邮件的例子,用户Clientcode调用EmailService之后,EmailService会把这个调用请求发送给消息队列,而后就当即返回了。Clientcode收到返回之后继续向下处理,不会继续阻塞等待。实际上消息发送到Queue后,尚未被处理,咱们看到后面的消息消费,其实要比EmailService返回可能还要晚一点,EmailService返回之后消息才会被消费处理。
有一个QueueConsumer消息队列的消费者,从消息队列中取出这个消息,再把这个消息发送给SmtpAdapter,也就是调用SmtpAdapter,处理逻辑跟同步调用同样,SmtpAdapter经过SMTP的通信协议,把消息发送给远程的一个服务器,进行邮件发送,经过RemoteServer进行处理,处理完了收到返回,再把返回结果通知消息队列Queue。
在这个过程当中,客户端的调用,也就是应用程序的调用,和业务逻辑真正发送邮件的操做是不一样步的。
2、异步架构的主要组成部分
使用异步调用架构的主要手段,就是经过消息队列构建,以下是它的架构图。
消息的生产者将消息发送到消息队列之后,由消息的消费者从消息队列中获取消息,而后进行业务逻辑的处理,消息的生产者和消费者是异步处理的,彼此不会等待阻塞,因此叫作异步架构。
使用消息队列构建一个异步调用架构,你须要了解以下3种角色。
1.消息的生产者
是客户端应用程序代码的一部分,用来初始化异步调用处理流程。在基于消息队列的处理中,生产者的职责很是少,它要作的就是建立一个合法的消息,并把这个消息发送到消息队列中,由应用开发者决定生产者的代码在哪里执行,何时发送消息。
2.消息队列
消息队列是消息发送的目的地和发给消费者的一个缓冲。消息队列实现的方法有好多种,能够用共享文件夹,也能够用关系数据库或者NoSQL系统,固然最主要的仍是使用专门的分布式消息队列服务器来实现。
3.消息的消费者
消息的消费者从消息队列中接受并处理消息,消息的消费者也是由应用开发者实现的,可是它是一个异步处理的组件。消息的消费者不须要知道生产者存在,它只依赖消息队列中的消息。消息的消费者一般部署在独立的服务器上,和消息的生产者彻底隔离,而且能够经过添加硬件的方式进行伸缩。
3、异步架构的两种主要模型
使用消息队列构建异步的调用架构,你还须要知道两种模型:点对点模型和发布订阅模型。
1.点对点模型
消费者和生产者只须要知道消息队列的名字,生产者发送消息到消息队列中,而消息队列的另外一端是多个消费者竞争消费消息,每一个到达消息队列的消息只会被路由到一个消费者中去,因此消费者看到的是所有消息的一个子集。咱们看这张图,消息的生产者有多个,消息的消费者也有多个,多个生产者将消息发送到消息队列中,而有多个消费者去消息队列中对消息进行竞争性的消费。每一个消息只会被一个消费者消费,每一个消费者只会消费消息队列中的一部分消息。
2.发布订阅模型
在发布订阅模型中,消息可能被发送到不止一个消费者,生产者发送消息到一个主题,而不是队列中。消息被发布到主题后,就会被克隆给每个订阅它的消费者,每一个消费者接收一份消息复制到本身的私有队列。消费者能够独立于其余消费者使用本身订阅的消息,消费者之间不会竞争消息。经常使用的分布式消息队列都支持发布订阅模型,也就是说消息的发布订阅模型是分布式消息队列的一个功能特性。
3.两个模型的应用
点对点模型:主要用于一些耗时较长的、逻辑相对独立的业务。
好比说我前面的讲到的发送邮件这样一个操做。由于发送邮件比较耗时,并且应用程序其实也并不太关心邮件发送是否成功,发送邮件的逻辑也相对比较独立,因此它只须要把邮件消息丢到消息队列中就能够返回了,而消费者也不须要关心是哪一个生产者去发送的邮件,它只须要把邮件消息内容取出来之后进行消费,经过远程服务器将邮件发送出去就能够了。并且每一个邮件只须要被发送一次。因此消息只被一个消费者消费就能够了。
发布订阅模型:如新用户注册这样一个消息,须要使用按主题发布的方式。
好比新用户注册,一个新用户注册成功之后,须要给用户发送一封激活邮件,发送一条欢迎短信,还须要将用户注册数据写入数据库,甚至须要将新用户信息发送给关联企业的系统,好比淘宝新用户信息发送给支付宝,这样容许用户能够一次注册就能登陆使用多个关联产品。一个新用户注册,会把注册消息发送给一个主题,多种消费者能够订阅这个主题。好比发送邮件的消费者、发送短信的消费者、将注册信息写入数据库的消费者,跨系统同步消息的消费者等。
4、消息队列的好处
1.实现异步处理,提高处理性能
对一些比较耗时的操做,能够把处理过程经过消息队列进行异步处理。这样作能够推迟耗时操做的处理,使耗时操做异步化,而没必要阻塞客户端的程序,客户端的程序在获得处理结果以前就能够继续执行,从而提升客户端程序的处理性能。
2.可让系统得到更好的伸缩性
耗时的任务能够经过分布式消息队列,向多台消费者服务器并行发送消息,而后在不少台消费者服务器上并行处理消息,也就是说能够在多台物理服务器上运行消费者。那么当负载上升的时候,能够很容易地添加更多的机器成为消费者。
如图中的例子,用户上传文件后,经过发布消息的方式,通知后端的消费者获取数据、读取文件,进行异步的文件处理操做。那么当前端发布更多文件的时候,或者处理逻辑比较复杂的时候,就能够经过添加后端的消费者服务器,提供更强大的处理能力。
3.能够平衡流量峰值,削峰填谷
使用消息队列,即使是访问流量持续的增加,系统依然能够持续地接收请求。这种状况下,虽然生产者发布消息的速度比消费者消费消息的速度快,可是能够持续的将消息归入到消息队列中,用消息队列做为消息的缓冲,所以短期内,发布者不会受到消费处理能力的影响。
从这张图能够看到,由于消息的生产者是直接面向用户请求的,而用户的请求访问压力是不均衡的。如淘宝天天的访问高峰是在上午10点左右,而新浪微博则可能在某个明星半夜发一条微博后忽然出现访问高峰。
在访问高峰,用户的并发访问数可能超过了系统的处理能力,因此在高峰期就可能会致使系统负载过大,响应速度变慢,更严重的可能会致使系统崩溃。这种状况下,经过消息队列将用户请求的消息归入到消息队列中,经过消息队列缓冲消费者处理消息的速度。
如图中所示,消息的生产者它有高峰有低谷,可是到了消费者这里,只会按照本身的最佳处理能力去消费消息。高峰期它会把消息缓冲在消息队列中,而在低谷期它也仍是使用本身最大的处理能力去获取消息,将前面缓冲起来、来不及及时处理的消息处理掉。那么,经过这种手段能够实现系统负载消峰填谷,也就是说将访问的高峰消掉,而将访问的低谷填平,使系统处在一个最佳的处理状态之下,不会对系统的负载产生太大的冲击。
4.失败隔离和自我修复
由于发布者不直接依赖消费者,因此分布式消息队列能够将消费者系统产生的错误异常与生产者系统隔离开来,生产者不受消费者失败的影响。 当在消息消费过程当中出现处理逻辑失败的时候,这个错误只会影响到消费者自身,而不会传递给消息的生产者,也就是应用程序能够按照原来的处理逻辑继续执行。
因此,这也就意味着在任什么时候候均可以对后端的服务器执行维护和发布操做。能够重启、添加或删除服务器,而不影响生产者的可用性,这样简化了部署和服务器管理的难度。
5.可使生产者和消费者的代码实现解耦合
也就是说能够多个生产者发布消息,多个消费者处理消息,共同完成完整的业务处理逻辑,可是它们的不须要直接的交互调用,没有代码的依赖耦合。在传统的同步调用中,调用者代码必需要依赖被调用者的代码,也就是生产者代码必需要依赖消费者的处理逻辑代码,代码须要直接的耦合,而使用消息队列,这两部分的代码不须要进行任何的耦合。
耦合程度越低的代码越容易维护,也越容易进行扩展。
好比新用户注册,若是用传统同步调用的方式,那么发邮件、发短信、写数据库、通知关联系统这些代码会和用户注册代码直接耦合起来,整个代码看起来就是完成用户注册逻辑后,后面必然跟着发邮件、发短信这些代码。若是要新增一个功能,好比将监控用户注册状况,将注册信息发送到业务监控系统,就必需要修改前面的代码,至少增长一行代码,发送注册信息到监控系统,咱们知道,任何代码的修改均可能会引发bug。
而使用分布式消息队列实现生产者和消费者解耦合之后,用户注册之后,不须要调用任何后续处理代码,只须要将注册消息发送到分布式消息队列就能够了。若是要增长新功能,只须要写个新功能的消费者程序,在分布式消息队列中,订阅用户注册主题就能够了,不须要修改原来任何一行代码。
这种解耦的特色对于团队的工做分工也颇有帮助!从消息生产者的视角看,它只须要构建消息,将消息放入消息队列中,开发就完成了。而从消费者的开发视角看,它只须要从消息队列中获取消息,而后进行逻辑处理。它们彼此之间不进行任何耦合。消息的生产者不关心放入消息队列中下一步会发生什么,而消费者也不须要知道消息从哪里来。这两部分程序的开发者也能够不关心彼此的工做进展,他们开发的代码也不须要集成在一块儿,只要约定好消息格式,就能够各自开发了。
经常使用的消息队列产品
目前业界经常使用的消息队列产品,有这么几种:RabbitMQ 、ActiveMQ、RocketMQ 、Kafka
RabbitMQ 的主要特色是性能好,社区活跃,可是RabbitMQ用Erlang开发,咱们的应用不多用Erlang,因此不便于二次开发和维护。
ActiveMQ 影响比较普遍,能够跨平台,使用Java开发,对Java比较友好。
RocketMQ 是阿里推出的一个开源产品,也是使用Java开发,性能比较好,可靠性也比较高。
Kafka 是LinkedIn出品的,专门针对分布式场景进行了优化,所以分布式的伸缩性会比较好。
目前看来,Kafka由于最初设计时就是针对互联网的分布式、高可用应用场景而设计,而且在大数据领域获得普遍支持,资料文档更加完善,所以在互联网企业获得更多的应用。
这里跟你们分享一个进行技术产品选型的小技巧,供你在进行技术决策的时候参考。当在几个类似的技术产品中进行选型决策,若是拿不定主意,感受都差很少的时候,一个办法就是利用搜索引擎搜索一下这些产品的名字,搜索结果最多的产品,表明了这个产品是最热门,文档资料最多的、遇到问题有更大几率能够经过搜索引擎找到答案的,最有发展前景、不会半途而废没人维护的。
利用这个技巧,咱们看一下消息队列MQ的产品选型,Kafka在百度中的搜索结果数量是其余三个MQ产品的搜索结果数量之和,那么若是你拿不定主意,选择Kafka至少不会是一个糟糕的选择。
以上内容摘取自拉勾
《阿里前辈的架构经》 第03讲(分布式消息队列) 点击查看更多
主讲人:李智慧,前阿里巴巴技术专家
添加拉勾职场导师微信 lagouandy ,可领取技术相关100+电子书