消息队列(入门篇)

来源:互联网 发布:靡靡之音知乎 编辑:程序博客网 时间:2024/06/05 15:16

什么是消息队列?

小时候,我的爸爸希望我多读书,并常常寻找好书给我看,最开始他每次看见我写完作业之后就给我拿来书,并亲自监督我读完之后他才忙自己的事情。久而久之,我养成了读书的习惯。所以方式就改成了,爸爸想要我读的书,都放在书架上,由于我已经养成了好习惯,一有空就从书架上拿书下来读。再后来我的小伙伴们听说我家很多书,也常常来我家玩,然后它们也可以直接从书架上拿书下来看。
看完这个故事之后再看看官方一点的消息队列定义。

消息队列(英语:Message queue)是一种进程间通信或同一进程的不同线程间的通信方式,软件的贮列用来处理一系列的输入,通常是来自用户。消息队列提供了异步的通信协议,每一个贮列中的纪录包含详细说明的数据,包含发生的时间,输入设备的种类,以及特定的输入参数,也就是说:消息的发送者和接收者不需要同时与消息队列互交。消息会保存在队列中,直到接收者取回它。 ——维基百科

为了帮助理解
消息队列,顾名思义,首先是个队列。队列的操作有入队和出队,也就是你有一个程序在产生内容然后入队(生产者),另一个程序读取内容,内容出队(消费者)。
Producer:消息生产者,负责产生和发送消息到 Broker;
Broker:消息处理中心。负责消息存储、确认、重试等,一般其中会包含多个 queue;
Consumer:消息消费者,负责从 Broker 中获取消息,并进行相应处理;

生产者消费者设计模式?

使用场景?

比如你写日志,因为可能一个客户端有多个操作去写,又有很多个客户端,显然并发不能无穷大,于是你就需要把写日志的请求放入到消息队列里,在消费者那边依次把队列中产生的日志写到数据库里。

再比如假设用户在你的软件中注册,服务端收到用户的注册请求后,它会做这些操作:校验用户名等信息,如果没问题会在数据库中添加一个用户记录如果是用邮箱注册会给你发送一封注册成功的邮件,手机注册则会发送一条短信分析用户的个人信息,以便将来向他推荐一些志同道合的人,或向那些人推荐他发送给用户一个包含操作指南的系统通知等等……但是对于用户来说,注册功能实际只需要第一步,只要服务端将他的账户信息存到数据库中他便可以登录上去做他想做的事情了。至于其他的事情,非要在这一次请求中全部完成么?值得用户浪费时间等你处理这些对他来说无关紧要的事情么?所以实际当第一步做完后,服务端就可以把其他的操作放入对应的消息队列中然后马上返回用户结果,由消息队列异步的进行这些操作。

消息队列的特性

异步性
将耗时的同步操作,通过以发送消息的方式,进行了异步化处理。减少了同步等待的时间。
松耦合
消息队列减少了服务之间的耦合性,不同的服务可以通过消息队列进行通信,而不用关心彼此的实现细节,只要定义好消息的格式就行。
分布式
通过对消费者的横向扩展,降低了消息队列阻塞的风险,以及单个消费者产生单点故障的可能性(当然消息队列本身也可以做成分布式集群)。
可靠性
消息队列一般会把接收到的消息存储到本地硬盘上(当消息被处理完之后,存储信息根据不同的消息队列实现,有可能将其删除),这样即使应用挂掉或者消息队列本身挂掉,消息也能够重新加载。

使用消息队列带来的好处?

1.解耦
每个成员不必受其他成员影响,可以更独立自主,只通过一个简单的容器来联系。再往后我长大了,不仅可以从家里的书架取书来看,还可以从图书馆的书架等等。只要有书架这个“容器”我就可以取书下来看。而不必关心到底是谁把书放上了书架。
2.提速
爸爸不再监督我看书,而为自己节省了大量时间。
3.广播
将书摆上书架,可以让不同的人读,这样读书人的“成本”就很低,只需要找到书架就OK了。
4.削峰
读书的频率可以控制在自己手中,我学习忙的时候可以少读一些,等空下来了,我可以加紧读书。在我读完这部分书之前,并不影响爸爸将更多好书放上书架。

使用消息队列带来的坏处?

1.引入复杂度:在最开始的例子中,“书架”无疑是多出来的一个东西,在我们的系统中自然就需要地方来存放它,以及对它作相应的处理。

2.暂时的不一致性:依然拿最开始的例子来说,由于爸爸在对我进行阅读习惯的培养之后,我会自觉的去看完爸爸放上来的书,并且他也是信任我的。但是他并不知道我具体是什么时候看完的,他只知道我一定会看完,他甚至会疏忽我学业的繁忙而错误的认为我已经看完了那些书,然而实际上我稍后才一段时间才看完。可以肯定的是,这本书我一定会看完的,但在期间一段时间内,我跟爸爸对于我读书进程状态的认知是不一致的。

在作消息队列的时候需要考虑的事项包括?

1.持久性,消息可能被保存在内存中,写入到磁盘,或甚至提交到DBMS,如果可靠性要求表明了更加资源密集型的解决方案。
2.安全策略,哪些应用程序可以访问这些消息?
3.消息清理策略,队列或消息应当有存活时间
4.消息过滤,一些系统支持过滤数据,因此,订阅者只能看到匹配预定义兴趣标准的消息
5.交付策略,我们是不是应该保证消息传递至少一次,或不超过一次?
6.路由策略,在一个有许多队列服务器的系统中,哪些服务器应该收到一条消息或一队列的消息?
7.批量策略,是否立即将消息传送?还是说系统应该稍等,并尝试一次传递多条消息?
8.排队标准,什么时候应当考虑消息“入队”?什么时候队列有了?或者,何时它被转发到至少一个远程队列?或所有队列?
9.已收通知,发布者可能需要知道,何时部分或全部订阅者收到了消息。
这些因素都是要考虑的,会显著影响到传输语义,系统的可靠性,系统效率。

标准和协议?

从历史来看,消息队列使用了专有的,封闭的协议,以约束不同的操作系统或编程语言在异构环境中交互的能力。
最近,已经出现了三个标准,使得消息队列开放而广泛:高级消息队列协议、MQTT、面向流文本的消息传递协议

last but not least

所以在软件的正常功能开发中,并不需要去刻意的寻找消息队列的使用场景,而是当出现性能瓶颈时,去查看业务逻辑是否存在可以异步处理的耗时操作,如果存在的话便可以引入消息队列来解决。否则盲目的使用消息队列可能会增加维护和开发的成本却无法得到可观的性能提升,那就得不偿失了。