ActiveMQ高级特性
1.异步投递Async Sends
ActiveMQ支持同步、异步两种发送的模式。
将消息发送到broker,模式的选择对发送延时有巨大的影响
producer能达到怎样的产出率(产出率=发送数据总量/时间)主要受发送延时的影响,使用异步发送可以显著的提高发送的性能
-------------------------------------------------------------------------------------
ActiveMQ默认使用异步发送的模式:除非明确指定使用同步发送的方式或者在未使用事务的前提下发送持久化的消息,这两种情况都是同步发送的
如果你没有使用事务且发送的是持久化消息,每一次发送都是同步发送的且会阻塞producer直接broker返回一个确认,表示消息已经被安全的持久化到磁盘。
-------------------------------------------------------------------------------------
确认机制提供了消息安全的保障,但同时会阻塞客户端带来了很大的延时。
很多高性能的应用,允许在失败的情况下有少量的数据丢失。如果你的应用满足这个特点,可以使用异步发送来提高生产率,即使发送的是持久化的消息
-------------------------------------------------------------------------------------
异步发送
它可以最大化producer端的发送效率。我们通常在发送消息量比较密集的情况下使用异步发送,它可以很大的提升producer性能;不过也带来了额外的问题
就是需要消耗较多的client端内存同时也会导致broker端性能消耗增加
此外它不能有效的确保消息发送成功,在useAsyncSend=true的情况下客户端需要容忍消息丢失的可能
-------------------------------------------------------------------------------------
异步发送如何确认发送成功
异步发送丢失消息的场景是:生产者设置UseAsyncSend=true,使用producer.send(msg)持续发送消息

由于消息不阻塞,生产者会认为所有send的消息均被成功发送到MQ
如果MQ宕机,此时生产者端内存中尚未被发送的MQ的消息都会丢失
所以,正确的异步发送方法是需要接收回调的。
同步发送和异步发送的区别就在此,同步发送等send不阻塞了就表示一定发送成功了,
异步发送需要接收回执并由客户端再判断一次是否发送成功

2.延迟投递和定时投递
在activemq.xml中配置schedulerSupport="true"

AMQ_SCHEDULED_DELAY:long类型,延迟投递的时间
AMQ_SCHEDULED_PERIOD:long类型,重复投递的时间间隔
AMQ_SCHEDULED_REPEAT:int类型,重复投递次数
AMQ_SCHEDULED_CRON:string类型,Cron表达式

3.分发策略
4.ActiveMQ消费重试机制
具体哪些情况会引起消息重发
1)Client用了transactions且在session中调用了rollback()
2)Client用了transactions且在调用commit()之前关闭或者没有commit
3)Client在CLIENT_ACKNOWLEDGE的传递模式下,在session中调用了recover()
消息重发时间间隔和重发次数
间隔:1s
次数:6
有毒消息Poison ACK
一个消息被redelivedred超过默认的最大重发次数(默认6次)时,消费端会给MQ发达一个”poison ack“表示这个消息有毒
告诉broker不要再发了,这个时候broker会把这个消息放到DLQ(死信队列)

collisionAvoidanceFactor:设置防止冲突范围的正负百分比,只有启用了useCollisionAvoidance参数时才生效。也就是在延迟时间上再加一个时间波动范围。默认值为0.15
maximumRedeliveries:最大重传次数,达到最大重连次数后抛出异常。为-1时不限制次数,为0时表示不进行重传。默认值为6
maximumRedeliveryDelay:最大传送延迟,只在useExponentialBackOff为true时有效(V5.5),假设首次重连间隔为10ms,倍数为2,那么第二次重连时间间隔为20ms,第三次
重连间隔为40ms,当重连时间间隔大的最大重连时间间隔时,以后每次重连时间间隔都为最大重连时间间隔。默认为-1
initialRedeliveryDelay:初始重发延迟时间,默认为1000L
redeliveryDelay:重发延迟时间,当redeliveryDelay=0时生效,默认为1000L
useCollisionAvoidance:启用防止冲突功能,默认为false
useExponentialBackOff:启用指数倍数递增的方式增加延迟时间,默认为false
backOffMultiplier:重连时间间隔递增倍数,只有值大于1和启用useExponentialBackOff参数时才生效。默认为5
5.死信队列

ActiveMQ中引入了”死信队列“的概念。即一条消息再被重发了多次后(默认为重发6次redeliveryCounter==6),将会被ActiveMQ移入”死信队列“。
开发人员可以在这个Queue中查看处理出错的消息
ShareDeadLetterStrategy
将所有的DeadLetter保存在一个共享的队列中,这是ActiveMQ broker端默认的策略
共享队列默认为”ActiveMQ.DLQ“,可以通过”deadLetterQueue“属性来设定
<deadLetterStrategy>
<sharedDeadLetterStrategr deadLetterQueuer="DLQ-QUEUE">
</deadLetterStrategy>
IndividualDeadLetterStrategy
把DeadLetter放入各自的死信通道中
对于Queue而言,死信通道的前缀默认为”ActiveMQ.DLQ.Queue.“
对于Topic而言,死信通道的前缀默认为”ActiveMQ.DLQ.Topic.“
比如队列Order,那么它对应的死信通道为”ActiveMQ.DLQ.Queue.Order“
我们使用”queuePrefix“,"topicPrefix"来指定上述前缀
默认情况下,无论是topic还是queue,broker将使用queue来保存deadLeader,即死信通道通过为Queue,不过也可以指定为Topic
<policyEntry queue="order">
<deadLetterStrategy>
<individualDeadLetterStrategy queuePrefix="DLQ." useQueueForQueueMessages="false"/>
</deadLetterStrategy>
</policyEntry>
将队列Order中出现的DeadLetter保存在DLQ.Order中,不过此时DLQ.Order为Topic
属性”useQueueForQueueMessages“,此值表示是否将Topic的DeadLetter保存在Queue中,默认为true
配置案例
自动删除过期消息
有时需要直接删除过期的消息而不需要发送到死队列中,”processExpired“表示是否将过期消息放入死信队列,默认为true
<policyEntry queue=">">
<deadLetterStrategy>
<individualDeadLetterStrategy processExpired="false"/>
</deadLetterStrategy>
</policyEntry>
存放非持久消息到死队列中
默认情况下,Activemq不会把非持久的死消息发送到死信队列中
processNonPersistent表示是否将非持久化消息放入死信队列,默认为false
非持久性如果 你想把非持久的消息发送到死队列中,需要设置属性processNonPersistent=true
">"表示全部起效
<policyEntry queue=">">
<deadLetterStrategy>
<individualDeadLetterStrategy processNonPersistent="true"/>
</deadLetterStrategy>
</policyEntry>
6.如果保证消息不被重复消费
网络延迟传输中,会造成MQ重试,在重试过程中,可能会造成重复消费
如果消息是做数据库的插入操作,给这个消息做一个唯一主键,那么就算出现重复的情况,就会导致主键冲突,避免数据库出现脏数据
如果上面两种情况还不行,准备一个第三服务方来做消费记录。以redis为例,给消息分配一个全局id,只要消费过该消息,将<id,message>
以K-V形式写入redis,那消费者开始消费前,先去redis中查询有没有消费记录即可
浙公网安备 33010602011771号