Activemq的可靠性机制

ACK概念

一条消息从producer端发出之后,一旦被broker正确保存,那么它将会被consumer消费,然后ACK,broker端才会删除;不过当消息过期或者存储设备溢出时,也会终结它。

  1. prefetchSize(预获取)

预获取prefetch limit
⚠️prefetch limit决定了获取消息的方式,时push还是pull
prefetch limit规定了一次可以向消费者Push(推送)多少条消息。这些消息会暂存在consumer的缓冲对列中
**在destinationUri中指定某个消费者的prefetchSize(预获取)选项
String queueName = “test-queue?customer.prefetchSize=10”;
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Destination queue = session.createQueue(queueName);
consumer = session.createConsumer(queue);
**在ConnectionFactory层面为所有消费者配置预取值:
tcp://localhost:61616?jms.prefetchPolicy.all=50
**在ConnectionFactory层面为队列消费者配置预取值:
tcp://localhost:61616?jms.prefetchPolicy.queuePrefetch=1
⚠️属于Consumer属性,在Consumer端设置。
⚠️若prefetch limit > 0时,broket是push的方式,prefetch limit = 0时,则是consumer是以pull的方式获取消息,若prefetch limit > 0时,则还是push方式
对于MessageListener接口,由于是被动监听consumer的缓冲对列,所以使用MessageListener接口时prefetch limit不可以为0

  1. prefetchACK

开启ack机制
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);


prefetchACK解决的问题:若设置了prefetchSize后,broket为push方式,若消费者处理消息的能力很弱,而消息中间件不断地向消费者push数据,消费者的缓冲区可能会溢出。


⚠️:开启prefetchACK后,当推送消息的数量到达了prefetch limit规定的数值时,消费者若没有ack,消息中间件将不再继续向消费者推送消息。
当prefetchACK为true,则prefetch limit必需大于0,broket是push的方式,当prefetchACK为false时,prefetch limit = 0时,则是consumer pull的方式获取消息,若prefetch limit > 0时,则还是push方式

  1. ACK模式与类型

    ● AUTO_ACKNOWLEDGE = 1 自动确认
    ● CLIENT_ACKNOWLEDGE = 2 客户端手动确认
    ● DUPS_OK_ACKNOWLEDGE = 3 自动批量确认
    ● SESSION_TRANSACTED = 0 事务提交并确认

  2. ACK_TYPE

指需要向broket发送ack消息时,可以发送指定的ack消息类型,如:consumer消费消息出现异常,可以向broket发送一个ack消息,将其ack类型指定为REDELIVERED_ACK_TYPE,broket就会冲新发送此消息。
● DELIVERED_ACK_TYPE = 0 消息”已接收”,但尚未处理结束
● STANDARD_ACK_TYPE = 2 “标准”类型,通常表示为消息”处理成功”,broker端可以删除消息了
● POSION_ACK_TYPE = 1 消息”错误”,通常表示”抛弃”此消息,比如消息重发多次后,都无法正确处理时,消息将会被删除或者DLQ(死信队列)
● REDELIVERED_ACK_TYPE = 3 消息需”重发”,比如consumer处理消息时抛出了异常,broker稍后会重新发送此消息
● INDIVIDUAL_ACK_TYPE = 4 表示只确认”单条消息”,无论在任何ACK_MODE下
● UNMATCHED_ACK_TYPE = 5 BROKER间转发消息时,接收端”拒绝”消息

optimizeACK
“可优化的ACK”,这是ActiveMQ对于consumer在消息消费时,对消息ACK的优化选项,也是consumer端最重要的优化参数之一。
String brokerUrl = “tcp://localhost:61616?” +
“jms.optimizeAcknowledge=true” +
“&jms.optimizeAcknowledgeTimeOut=30000” +
“&jms.redeliveryPolicy.maximumRedeliveries=6”;
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(brokerUrl);


optimizeACK(ACK时机),可以让client在消费消息后暂且不发送ACK,将其缓存(pendingACK),等消息到达一定阀值时,通过一个ACK指令将她们全部确认,提高一条条确认的性能。


⚠️只有当ACK_MODE为AUTO_ACKNOWLEDG时,optimizeACK才会生效。

消息确认方式
ACK_MODE为AUTO_ACKNOWLEDG
===receive(同步)================
在“同步”(receive)方法返回message之前,会检测optimizeACK选项是否开启,如果没有开启,此单条消息将立即确认,所以在这种情况下,message返回之后,如果开发者在处理message过程中出现异常,会导致此消息也不会redelivery,即”潜在的消息丢失”;如果开启了optimizeACK,则会在unAck数量达到prefetch * 0.65时确认,当然我们可以指定prefetchSize = 1来实现逐条消息确认。
===messageListener(异步)================
将会首先调用listener.onMessage(message),此后再ACK,如果onMessage方法异常,将导致client端补充发送一个ACK_TYPE为REDELIVERED_ACK_TYPE确认指令;如果onMessage方法正常,消息将会正常确认(STANDARD_ACK_TYPE)。此外需要注意,消息的重发次数是有限制的,每条消息中都会包含“redeliveryCounter”计数器,用来表示此消息已经被重发的次数,如果重发次数达到阀值,将会导致发送一个ACK_TYPE为POSION_ACK_TYPE确认指令,这就导致broker端认为此消息无法消费,此消息将会被删除或者迁移到”dead letter”通道中。
ACK_MODE为CLIENT_ACKNOWLEDGE
如果接收端不确认消息,那么activemq将会把这条消息一直保留,直到有一个接收端确定了消息

参考:http://blog.csdn.net/czp11210/article/details/47022639
参考:https://www.cnblogs.com/zhuxiaojie/p/5564187.html

你可能感兴趣的:(activemq)