消息队列总结

Posted 猿人课堂

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了消息队列总结相关的知识,希望对你有一定的参考价值。

  1. 消息队列中的“消息”即指同一台计算机的进程间,或不同计算机的进程间传送的数据;
    “消息队列”是在消息的传输过程中保存消息的容器。
    消息被发送到队列中,消息队列充当中间人,将消息从它的源中继到它的目标。

2. 传统的进程通信模式如图1左所示:client调用service,等待service的响应。但是这种模式有很多弊端:
-网络情况不好时,client到Service的调用可能会丢失;
-或者service如果处理时间较长,那么client需要一直hold,甚至调用超时而失败;
-或者service的些许改动会带来client的代码修改等等。 

3. 引入消息队列则可以避免这种传统模式的弊端,如图1右所示:

 消息队列总结

图1(左) 典型的Invoke/Respond模型     
图1(右) 典型的消息队列处理流程

 

4. 消息队列可以带来如下好处:
(1)保证消息的传递。
如果发送消息时接收者不可用,消息队列会保留消息,直到成功地传递它;

(2)提供异步的通信协议。
消息的发送者将消息发送到消息队列后可以立即返回,不用等待接收者的响应,消息会被保存在队列中,直到接收者取出它;

(3)解耦,降低两个进程间的耦合度。
只要消息格式不变,即使接收者的接口、位置、或者配置改变,也不会给发送者带来任何改变;
而且,消息发送者无需知道消息接收者是谁,使得系统设计更清晰;
相反的,例如,远程过程调用(RPC)或者服务间通过socket建立连接,如果对方接口改变了或者对方ip、端口改变了,那么另一方需要改写代码或者改写配置;

(4)提供路由。
发送者无需与接收者建立连接,双方通过消息队列保证消息能够从发送者路由到接收者,甚至对于本来相互网络不通的两个服务,也可以提供消息路由。


为什么需要消息队列

 


 

消息队列中的“消息”即指同一台计算机的进程间,或不同计算机的进程间传送的数据;“消息队列”是在消息的传输过程中保存消息的容器。
消息被发送到队列中,消息队列充当中间人,将消息从它的源中继到它的目标。

腾讯云计算平台提供的分布式消息队列CMQ服务实现了消息队列的全部宗旨:
1. 保证消息的传递;
2. 提供异步的通信协议;
3. 解耦;
4. 提供路由。

同时,CMQ具有分布式消息队列的全部优势:安全、可靠、简单易用、透明、实用、可扩展,弥补了消息队列潜在的不足,以自己的方式提供更可靠、更安全、更易用、更实用的周到服务。

引入消息队列则可以避免传统进程通信模式的弊端,如下图所示:

 消息队列总结

图1(左) 典型的Invoke/Respond模型
图1(右) 典型的消息队列处理流程


 

更可靠
(1)接收者接收消息后,CMQ服务并不立刻从队列中删除该消息,只有在接收者确认接到消息,主动发送删除消息请求时,才把消息删除;
(2)保证消息只被接收一次。实现方式是在消息被接收后锁住该条消息,锁有时效,当接收者在时效内没有来删除这条消息,则说明接收者出现异常,锁失效,该条消息可以被再次接收;
(3)应用发送消息,如果直接通过http协议访问消息队列,则消息必须经过base64编码,这样避免了消息的编码格式混乱造成的消息接收错误;CMQ SDK内部进行了base64编码的封装,应用可以传任意内容给SDK接口。

更安全
(1)应用必须登录开放平台,有自己的应用(即具有appid)才可以开通消息队列服务;
(2)开通消息队列时,会告诉用户一个AccessKey作为访问消息队列的密码,之后应用发送和接收消息都要使用该AccessKey;
(3)发送和接收消息时,除了使用AccessKey还要传入应用的appid,而且必须匹配;
(4)应用没有途径可以直接看到其他应用的消息内容。

更易用
(1)只需一键即可开通消息队列服务,只需一键即可创建、删除队列,不用按键即可查看应用已经创建的队列列表及信息。
(2)用户在可视化界面中创建队列后,只需通过http请求访问消息队列。
(3)接口简单,无需对复杂的网络环境进行处理和容错。


消息队列适用场景

 

异步通信
对于BS(Browser-Server 浏览器)架构,很多情景下server的处理时间较长。
如果浏览器发送请求后,保持跟server的连接,等待server响应,那么一方面会对用户的体验有负面影响;
另一方面,很有可能会由于超时,提示用户服务请求失败。

对于这种情景,消息队列提供了一个较好的解决方案,如图2所示:
消息队列总结

 

图2 BS通信模型的优化方案

 

工作流程如下:
(1)浏览器向服务器发送请求后,服务器接到响应后立即返回;
(2)之后,服务器向消息队列发送已经完成的结果信息;
(3)浏览器端用js等技术循环请求该消息队列,检查是否有新的结果信息,如果有则获取消息,并将结果渲染到浏览器界面上。


命令下发/分布式处理模型
在分布式的应用系统中,经常会有master-worker的模型(Map-Reduce就是一个典型的例子)。
有任务到达时,master会将任务直接分配给worker或者切成子任务分配给worker,但是有一个原则就是一个任务或者子任务只希望被一个worker执行。

传统的处理方式是:
(1)master要维护worker的心跳,知道有哪些worker可以接受任务,然后master挑选一个worker,与其建立连接,并发送数据包(即命令);
(2)worker收到数据包(命令)后,如果能够正常解析并执行,则反馈master;
(3)如果worker许久没有反馈,则master会做一系列工作,包括check该worker状态、确保死掉了之后再挑选一个worker分配任务。

这样的处理方式对master压力过大,也过于复杂。使用消息队列则可对master和worker进行有效解耦,如图3所示:

 

图3 master-worker命令下发模型的优化方案

 

CMQ中,master和worker的配置中都事先配置好两个队列名:1任务下发队列名,结果反馈队列名。
master有任务下发时,就向该“任务下发”队列中发送消息;
worker定期检查“任务下发”队列,发现队列有消息则获取(因为CMQ的特性保证了一条消息只会被一个接收者接收,所以一个任务只会被一个worker执行)。
之后worker执行的结果都发送到“结果反馈”队列中,master定期检查“结果反馈”队列,汇总执行结果。
所有这种一对多的通信,并且只希望这个“多”中只有一个真正接收到消息,则都可采用上述的解决方案。


数据上报模型
凡是多对一的通信都可以采用CMQ来解耦合,如下面例子所示:
1. 上文“命令下发/分布式处理模型”中给出的master-worker模型解决方案中,多个worker向同一个队列发送消息,master从该队列接收消息,就是一个典型的数据上报模型,即图3中的结果反馈的过程。

2. 监控服务中各个机器有后台进程定期汇报机器状态,中心服务收集各机器状态,进行计算和统计。也是一个典型的数据上报模型。 
监控服务的后台进程可以将状态汇报到一个消息队列,中心服务从这个队列中接收消息,如图4所示:

 

图4 数据上报模型的优化方案

	


以上是关于消息队列总结的主要内容,如果未能解决你的问题,请参考以下文章

分布式消息队列差异化总结,太全了!

消息队列总结

消息队列的一些知识

案例精选 | 分布式消息队列差异化总结,太全了!

消息队列和 RocketMQ 入门总结

消息队列总结