开发者学习笔记【阿里云云原生助理工程师认证(ACA)课程:消息队列和应用工具产品体系-消息队列的基本概念】
课程地址:https://edu.aliyun.com/course/3112075/lesson/19036
消息队列和应用工具产品体系-消息队列的基本概念
内容介绍:
一.高可用架构的演变
二.消息队列的由来
三.高并发场景的应对
四.异步调用和业务解耦模式
五.消息队列和ESB企业服务总线的区别
一.高可用架构的演变
软件架构的演变大概分成三个阶段
第一阶段是单体应用架构,在这个阶段,软件中的模块和模块集中在一个应用,此种架构只能通过提高硬件的性能来应对高并发场景,基本上没有办法从软件层面进行高并发设计。
第二是初步分布式架构,经过分布式架构调整后,模块一般采用多实例的方式进行设计,模块A有两个实例,A1和A2,而模块B有三个相同的实例,B1,B2,B3,当实例A1需要调用B模块时,需要从B中手动选择一个实例进行调用,因此此种模式下A模块中的实例都需要管理B模块中所有实例的位置,并在发起请求的时候选择一个模块进行调用,无形中增加了分布式调用的复杂度。
第三阶段是微服务架构时期,这个时期的高可用还是采用单模块多实例的方式,不同的是模块的位置和调用关系是通过服务注册和组件负载均衡进行管理。
如图,
A1需要调用B模块时,并不需要自己管理B1,B2,B3的真实位置,只需要通过负载均衡组件 LB发送请求,再由LB转发请求到具体组件中,实现A模块和B模块的解耦。但这种架构在应对高并发时候还有不足,例如当B模块处理较慢,无法达到A模块的请求速度时,此种模式无法进行有效的处理。在这种情况下,我们就需要新的模式来进行应对,而这个新的模式就是消息对列。
二.消息队列的由来
消息对列是指在模块和模块之间加入中间层,所有模块的调用都先转换成消息,由消息队列先将消息持久化,即存盘,存盘后再传递给下一的服务提供者,实现分布式调用。
如图,A1和A2对B的调用,并不是直接传递给B模块,而是先将调用的请求和参数实际化成消息交流、消息队列存盘,如果多个消息同时到来,会按照先进先出的数据将消息排队,再将队列的消息逐一传递给B模块中的实例进行处理。这种先转换成消息再排队的模式就是消息队列的名称来源。通过上面的说明可以知道,这种模式中消息队列不但提供了消息分布式调用的能力以及负载均衡组件的能力,同时也降低了服务之间的耦合关系,服务A和服务B不再需要统一接口。只要能和消息队列的统一接口进行交互即可,同时,调用的安全性也有了进一步的提高,而一旦调用出现错误,因为消息都会存盘,所以错误重试就会变得非常简单,消息队列在高并发场景和异步调用以及业务结果模式上也有了很好的应对措施
三.高并发场景的应对
当突发流量巅锋到来时,后端服务往往受限于数据存储层的性能瓶颈,无法通过弹性扩容进行快速扩容以此来提高并发数。这种情况下,除了提高数据存储的性能之外,最重要的手段是通过消息队列将消息持久化和消息排队的机制来实现流量的削峰填谷。
以图为例,当前端调用出现流量洪峰时,前端调动的洪峰并不会直接传导到下游,而是先以消息的形式保存在消息队列中。消息队列的消息存储只是简单的写文件,因此消息持久化的速度非常快,这样前方可以快速完成消息的写入,而不会陷入长时间的等待。同时由于消息队列的排队特性,虽然后端应用的处理速度达不到前端应用的流量峰值,但来不及处理的消息可以先保存在消息队列中,后端应用可以用合适的处理速度,匀速的从消息队列中取出消息,逐步对堆积的消息进行处理,这样就避免了前端请求大量失败或者后端服务在大量请求之下因资源耗尽而崩溃,从而实现高并发场景下,尤其是尖峰请求时候的削峰填谷。
四.异步调用和业务解耦模式
消息队列能够将前端的求以消息文件的形式保存,在适当的时候再交给后端进行处理。但这种模式引发了一个问题,也就是前端的请求在返回之时,此请求并不见得由后端真正进行处理,很有可能只是在排队的过程中。这种情况与传统的微服务调用的过程相比,前端发出的请求在返回时要么经过后端的处理,要么直接失败的方式有了很大的不同。前端在发出请求后一直等待后端处理的方式,称为同步调用。而消息队列这种前端发出请求就立刻返回,后端在合适的时机进行处理的模式,称为异步调用。
微服务采用的是同步调用,而消息队列采用的是异步调用,同步调用的技术特点,就是消息处理的流程设计简单,前后耦合和也比较紧密,调用返回即可获得处理结果,可以进行下一步的操作,一般来讲适合于大功能的内部模块之间的互相调用。而异步调用程序的处理则相对复杂,调用发送之后并不会收到处理结果,如果需要处理结果才能进行下一步操作,则需要将业务的流程割裂在不同的代码里面。但异步调用的前后端耦合度比较低,后端的异常不会对前端的功能产生影响,同时流量洪峰也可以被隔离,所以一般来讲异步调用适合于不同大功能之间的跨功能调用。
在消息队列中,异步调用采用发布订阅者模式,应用调用者作为消息发动者,应用提供者作为消息订阅者,发布者和订阅者通过topic进行关联,发布者向指定的topic发送消息后,并不关注消息如何处理,可以有一个或多个而消息订阅,消息的订阅者可以在适当的时机从消息订阅中取出消息进行消费,并不关心消息发布者的来源。这种模式就是通过异步调用模式实现业务的松耦合。
五.消息队列和 ESB 企业服务总线的区别
消息队列的处理流程和SOA流程中的企业服务总线十分相似,同样是通过集中式的单点设备来管理模块和模块之间的调度,那么两者间的区别是什么?或者说,为什么要放弃企业服务总线而转向使用消息队列?企业服务总线和消息队列之间的有三个最主要的差异
首先,企业服务总线主要用于模块内部的分布式调用,即所有的分布式请求都要通过企业服务总线进行转发,因此企业服务总线的吞吐量要远远高过消息队列。同时,在企业服务总线上的调用采用同步调用方法,与消息队列采用的异步调用方法有很大的差别。同步调用模式对错误的容忍程度远远小于异步模式下对错误的容忍程度。这就意味着企业服务总线对于整个系统的安全风险是远远高过于消息队列。
第二,企业服务总线不但包括分布式调用,还包括如协议转换、服务发现、负载均衡、应用健全等功能,而消息队列的功能较为单一,只负责消息的转发、保存和订阅发布,即消息队列并不需要考虑太多的分布式之间的协作,因此对消息队列开发分布式集群的复杂度也远远低于对企业服务总线开发集群的复杂度。
第三点:消息队列的功能较为单一,使得消息队列本身和应用模块之间的耦合度也非常低。消息队列并不会规定分布式调用模块之间的协议、参数规格、接口描述等业务逻辑,因此也不会成为应用解耦中的障碍。
而企业服务总线定义了过多业务相关逻辑,一旦需要更换,则有大量业务代码需要进行修改。从易扩展性的角度来看,企业服务总线远不如消息队列良好。
以上三个特点就决定了消息队列符合分布式架构下的松耦合设计、多可用区设计两个重要的概念,因此替代了企业服务总线成为了新一代的消息中间件。