前言

Github:https://github.com/HealerJean

博客:http://blog.healerjean.com

2、消息队列功能特点以及解决的问题

1566902171300

Producer 消息生产者,负责产生和发送消息到消息处理中心

Broker 消息处理中心,负责消息接收、存储、转发

Consumer 消息消费者,负责从消息处理中心获取消息,并进行处理

生产环境中,对于消息队列的要求可不止基本的消息发送、暂存、接收,在不同的业务中,需要消息队列产品能解决 消息堆积、消息持久化、消息重复、严格有序等各种问题

2.1、消息堆积

最开始介绍过,消息队列的生产者和消费者是分开处理消息的系统,所以我们无法预知两者处理消息速度的快慢,如果一段时间内消息消费者处理消息的速度太慢,必然会导致消息堆积,

因此有时候需要给消息队列设一个阈值,超过的不再放入消息处理中心,以防止系统资源耗尽,导致机器挂掉,整个消息队列不可用

2.1.1、消息过期

默认情况下,activemq永远不会过期,如果业务场景需要,可以指定过期时间,如果下面这个设置为0

MessageProducer producer = session.createProducer(destination);
producer.setTimeToLive(1000L); //每一条都设置过期时间


//单独设置过期时间
public void send(Destination destination, Message message, int deliveryMode, int priority, long timeToLive);

2.1.2、死信队列 (阅读删除积压已久的缓冲区)

2.1.3、慢消费者策略设置

如果慢速消费者最后一个ACK距离现在的时间间隔超过阀maxTimeSinceLastAck,则中断慢速消费者。

Broker将会启动一个后台线程用来检测所有的慢速消费者, Broker端一旦发现slow consumer,就将它注册到慢速消费者列表中,此后将有额外的线程扫描并关闭它们(定期关闭它们)

其中abortConnection表示,是否关闭底层的transport

默认为false,此时将会通过transport向client端发送一个指令(其中包括consumerId),当client端(Session)接收之后,将会调用consumer.close()方法;

如果此值为true,将会导致底层的transport链接被关闭,这是很粗暴的办法,不过如果client端多个consumer共享一个connection的话,会导致所有的consumer被关闭,那就等老板开你把

  • AbortSlowConsumerStrategy, 如果慢速消费者最后一个ACK距离现在的时间间隔超过阀值,则中断慢速消费者
<slowConsumerStrategy>    
    <abortSlowConsumerStrategy abortConnection="false"  maxTimeSinceLastAck="30000"/><!-- 30秒滞后 -->    
</slowConsumerStrategy>  

2.2、消息持久化

有时候我们 需要在合适的时机传递给消费者,内存肯定是不可以的,因为一旦机器挂掉消息就会丢失,所以我们可以放到本地文件,分布式文件系统,数据库系统中。这样就可以持久化了

2.3、可靠投递( 消息丢失,分布式那一篇文章解决这个问题)

这个去年面试官问过我,当时回答的不是很好,可靠投递是不允许存在消息丢失的情况,从消息的整个生命周期来看,消息丢失我们可以分析下存在于那个阶段

1、从生产者到消息处理中心

2、消息处理中心持久化消息

3、从消息处理中心到消费者

2.4、消息重复

在接收到消息后先持久化到数据库,然后放到消息队列,再发送给消费者,当消息发送失败或者不知道是否发送成功时,消息的状态是待发送,定时任务不停读取待发送的消息,然后发送消息,最终保证消息不会丢失,

但是这样有一个问题,虽然超时了,但是消费者毕竟接收到了。而我这里因为超时却记录到了。这就是消息重复,怎么处理呢,一个编号搞定

2.5、严格有序

比如,淘宝购物,每一笔订单必须经过创建订单,支付完成,已发货,已收货,订单完成等环节,如果说每个环节都是消息的话,我们必须按照顺序消费消息,否则在业务上是不合理的,我们不允许顺序有误

2.6、集群

大型系统中,系统一般是集群的,集群可以让消费者和生产者在某个节点崩溃的情况下继续运行

2.7、消息中间件

上面介绍了很多,那什么是消息中间件 ?

消息中间件关注数据的发送和接收,利用高效,可高的异步消息传递机制集成分布式系统。不是直接给最终用户使用的,不能直接给用户带来价值的软件称为中间件,

3、Queue 和 Topic

JMS中定义了两种消息模型

点对点(point to point, queue):不可重复消费,默认是持久化的

发布/订阅(publish/subscribe,topic) : 重复消费,默认是非持久的(要求消费者必须在线)

这里重复消费的意思是,可以多次读取,也就是同一个消息被多个消费者读取。而不是消息签收

3.1、Queue

消息生产者生产消息发送到queue中,然后消息消费者从queue中取出并且消费消息,消息被消费以后,queue中不再有存储,所以消息消费者不可能消费到已经被消费的消息。

Queue支持存在多个消费者,但是对一个消息而言,只会有一个消费者可以消费、其它的则不能消费此消息了。当消费者不存在时,消息会一直保存,直到有消费消费

3.2、Topic

消息生产者发布将消息发布到topic中同时有多个消息消费者订阅消费该消息和点对点方式不同发布到topic的消息会被所有订阅者消费

非持久化当生产者发布消息不管是否有消费者都不会保存消息
持久化会保存消息等待消息超时删除

ContactAuthor