大家知道,JMS规范中,Message消息头接口中有setJMSRedelivered(boolean redelivered)和getJMSRedelivered()方法,用于设置和获取消息的重发标志,当然set方法主要是MOM来调用的,我们客户端使用的是get方法。
还记得当时阿里的电话面试曾问过我,你知道ActiveMQ中的消息重发时间间隔和重发次数吗?我当时尴尬了,只知道会重发,还真没去了解过其中的细节,所以最后被完美的“淘汰了”。
后来有时间了就去网上看了下官方的文档,所以现在把ActiveMQ中的重发机制和大家一起分享一下。
首先,我们得大概了解下,在哪些情况下,ActiveMQ服务器会将消息重发给消费者,这里为简单起见,假定采用的消息发送模式为队列(即消息发送者和消息接收者)。
1.如果消息接收者在处理完一条消息的处理过程后没有对MOM进行应答,则该消息将由MOM重发。
2.如果我们队某个队列设置了预读参数(consumer.prefetchSize),如果消息接收者在处理第一条消息时(没向MOM发送消息接收确认)就宕机了,则预读数量的所有消息都将被重发。
3.如果Session是事务的,则只要消息接收者有一条消息没有确认,或发送消息期间MOM或客户端某一方突然宕机了,则该事务范围中的所有消息MOM都将重发。
说到这里,大家可能会有疑问,ActiveMQ消息服务器怎么知道消费者客户端到底是消息正在处理中还没来得急对消息进行应答还是已经处理完成了没有应答或是宕机了根本没机会应答呢?其实在所有的客户端机器上,内存中都运行着一套客户端的ActiveMQ环境,该环境负责缓存发来的消息,负责维持着和ActiveMQ服务器的消息通讯,负责失效转移(fail-over)等,所有的判断和处理都是由这套客户端环境来完成的。
我们可以来对ActiveMQ的重发策略(Redelivery Policy)来进行自定义配置,其中的配置参数主要有以下几个:
a) collisionAvoidanceFactor :碰撞躲避因数,默认值是0.15,这个参数是为了躲避高并发的重发带来的问题,我们查看org.apache.activemq.RedeliveryPolicy类的源代码,
// +/-15% for a 30% spread -cgs
protected double collisionAvoidanceFactor = 0.15d;
protected long initialRedeliveryDelay = 1000L;
可以发现,该默认值带来的变动范围是正负百分之15,也就是有30%的范围,也就是说,如果延迟发送时间(也就是initialRedeliveryDelay 默认值)是1000毫秒,则该条消息第一次有可能被拖延850毫秒到1150毫秒之间后被发送,如果有第二次重发,基数就不是1000毫秒了,而是以上一次重发拖延时间为基础来算。源代码如下:
public long getNextRedeliveryDelay(long previousDelay) {
long nextDelay = redeliveryDelay;
if (previousDelay > 0 && useExponentialBackOff && backOffMultiplier > 1) {
nextDelay = (long) (previousDelay * backOffMultiplier);
if(maximumRedeliveryDelay != -1 && nextDelay > maximumRedeliveryDelay) {
// in case the user made max redelivery delay less than redelivery delay for some reason.
nextDelay = Math.max(maximumRedeliveryDelay, redeliveryDelay);
}
}
if (useCollisionAvoidance) {
/*
* First random determines +/-, second random determines how far to
* go in that direction. -cgs
*/
Random random = getRandomNumberGenerator();
double variance = (random.nextBoolean() ? collisionAvoidanceFactor : -collisionAvoidanceFactor) * random.nextDouble();
nextDelay += nextDelay * variance;
}
return nextDelay;
}
b)maximumRedeliveries :最大重发次数,默认值是6,如果你想不限次数重发,可以设置成-1。同样是org.apache.activemq.RedeliveryPolicy类中的代码:
public static final int NO_MAXIMUM_REDELIVERIES = -1;
public static final int DEFAULT_MAXIMUM_REDELIVERIES = 6;
protected int maximumRedeliveries = DEFAULT_MAXIMUM_REDELIVERIES;
我们探究一下maximumRedeliveries 的get方法,可以发现有org.apache.activemq.ActiveMQSession和org.apache.activemq.ActiveMQMessageConsumer两个类中有用到:
其中ActiveMQSession中的代码如下:
// Figure out how long we should wait to resend this message.
long redeliveryDelay = redeliveryPolicy.getInitialRedeliveryDelay();
for (int i = 0; i < redeliveryCounter; i++) {
// 每次重发拖延时间都是以上一次重发拖延时间来算,所以这里for循环来取得最新的拖延时间
redeliveryDelay = redeliveryPolicy.getNextRedeliveryDelay(redeliveryDelay);
}
// 交给定时任务重发
connection.getScheduler().executeAfterDelay(new Runnable() {
public void run() {
((ActiveMQDispatcher)md.getConsumer()).dispatch(md);
}
}, redeliveryDelay);
ActiveMQMessageConsumer中的代码类似。

c)maximumRedeliveryDelay :重发最大拖延时间,默认为-1,表示没有最大拖延时间,此参数只有当useExponentialBackOff 为true时起效。同样是RedeliveryPolicy中的代码:
protected long maximumRedeliveryDelay = -1;
public long getNextRedeliveryDelay(long previousDelay) {
long nextDelay = redeliveryDelay;
if (previousDelay > 0 && useExponentialBackOff && backOffMultiplier > 1) {
nextDelay = (long) (previousDelay * backOffMultiplier);
if(maximumRedeliveryDelay != -1 && nextDelay > maximumRedeliveryDelay) {
// in case the user made max redelivery delay less than redelivery delay for some reason.
nextDelay = Math.max(maximumRedeliveryDelay, redeliveryDelay);
}
}
。。。。。
}
看源代码就显而易见了。

d)initialRedeliveryDelay :第一次重发的拖延时间基础,默认是1000,单位为毫秒,前面讲collisionAvoidanceFactor 属性时已经提到过,这里不再多说。

e)redeliveryDelay :如果initialRedeliveryDelay 为0,则使用redeliveryDelay ,默认也是1000。RedeliveryPolicy中源代码如下:
protected long initialRedeliveryDelay = 1000L;
protected long redeliveryDelay = initialRedeliveryDelay;

f)useCollisionAvoidance :消息重发时是否采用前面提到的碰撞避免collisionAvoidanceFactor 参数,默认是false,不采用。源代码上面也给出了,这里不再多说。

g)useCollisionAvoidance :是否使用成倍增加拖延,默认为false,如果我们希望重发的拖延时间一次比一次大很多,则可以设置它为true。上面已经给出过源代码,这里再次给出:
protected boolean useExponentialBackOff;
protected double backOffMultiplier = 5.0;
public long getNextRedeliveryDelay(long previousDelay) {
long nextDelay = redeliveryDelay;
if (previousDelay > 0 && useExponentialBackOff && backOffMultiplier > 1) {
nextDelay = (long) (previousDelay * backOffMultiplier);
if(maximumRedeliveryDelay != -1 && nextDelay > maximumRedeliveryDelay) {
// in case the user made max redelivery delay less than redelivery delay for some reason.
nextDelay = Math.max(maximumRedeliveryDelay, redeliveryDelay);
}
}
if (useCollisionAvoidance) {
/*
* First random determines +/-, second random determines how far to
* go in that direction. -cgs
*/
Random random = getRandomNumberGenerator();
double variance = (random.nextBoolean() ? collisionAvoidanceFactor : -collisionAvoidanceFactor) * random.nextDouble();
nextDelay += nextDelay * variance;
}
return nextDelay;
}
可以看出,成倍拖延是将上一次拖延时间乘以backOffMultiplier来实现的,而 backOffMultiplier默认为5.
h)backOffMultiplier :成倍拖延时间的倍率,默认为5,上面已经提到了,这里不再多说。

转自:http://www.tuicool.com/articles/iMb2Y3

activemq消息重发机制[转]的更多相关文章

  1. Activemq消息确认机制 --转载

      转自:http://blog.csdn.net/czp11210/article/details/47022639 ActiveMQ消息传送机制以及ACK机制详解 AcitveMQ是作为一种消息存 ...

  2. 学习ActiveMQ(六):JMS消息的确认与重发机制

    当我们发送消息的时候,会出现发送失败的情况,此时我们需要用到activemq为我们提供了消息重发机制,进行消息的重新发送.那么我们怎么知道消息有没有发送失败呢?activemq还有消息确认机制,消费者 ...

  3. springboot+activemq中引入重发机制

    一.简介 在使用activemq消息中间件进行消息队列传输时,总会由于各种原因导致消息失败. 一个经典的场景是一个生成者向Queue中发消息,里面包含了一组邮件地址和邮件内容.而消费者从Queue中将 ...

  4. springboot整合activemq加入会签,自动重发机制,持久化

    消费者客户端成功接收一条消息的标志是:这条消息被签收. 消费者客户端成功接收一条消息一般包括三个阶段:          1.消费者接收消息,也即从MessageConsumer的receive方法返 ...

  5. ActiveMQ消息的可靠性机制(转)

    文章转自:http://www.linuxidc.com/Linux/2013-02/79664.htm 1.JMS消息确认机制 JMS消息只有在被确认之后,才认为已经被成功地消费了.消息的成功消费通 ...

  6. ActiveMQ的JMS消息可靠机制

    JMS消息可靠机制 ActiveMQ消息签收机制: 客戶端成功接收一条消息的标志是一条消息被签收,成功应答. 消息的签收情形分两种: 1.带事务的session 如果session带有事务,并且事务成 ...

  7. ActiveMQ讯息传送机制以及ACK机制详解

    [http://www.ylzx8.cn/ruanjiangongcheng/software-architecture-design/11922.html] AcitveMQ:消息存储和分发组件,涉 ...

  8. ActiveMQ讯息传送机制以及ACK机制

    http://blog.csdn.net/lulongzhou_llz/article/details/42270113 ActiveMQ消息传送机制以及ACK机制详解 AcitveMQ是作为一种消息 ...

  9. RocketMQ(消息重发、重复消费、事务、消息模式)

    分布式开放消息系统(RocketMQ)的原理与实践 RocketMQ基础:https://github.com/apache/rocketmq/tree/rocketmq-all-4.5.1/docs ...

随机推荐

  1. IE6-IE9不支持table.innerHTML的解决方法--终极解决办法

    一.把要转译的内容放到其他属性中,例如“tt” <p class="feedback_answer_content" tt='${feedInfo.feedback_answ ...

  2. 11.Container With Most Water---两指针

    题目链接:https://leetcode.com/problems/container-with-most-water/description/ 题目大意:给出一串数组(a1, a2, a3, .. ...

  3. Django 1.10文档中文版Part1

    目录 第一章.Django1.10文档组成结构1.1 获取帮助1.2 文档的组织形式1.3 第一步1.4 模型层1.5 视图层1.6 模板层1.7 表单1.8 开发流程1.9 admin站点1.10 ...

  4. SilverLight 浏览器出现滚动条

    照网上说的很多解决方案要不得,最后想了下,直接在body上面加 style="overflow:hidden"解决问题,真觉得微软管理混乱,很多它自己的东西都不支持了.

  5. Codeforces 821C Okabe and Boxes(模拟)

    题目大意:给你编号为1-n的箱子,放的顺序不定,有n条add指令将箱子放入栈中,有n条remove指令将箱子移除栈,移出去的顺序是从1-n的,至少需要对箱子重新排序几次. 解题思路:可以通过把栈清空表 ...

  6. BFC(块级格式化上下文)

    渲染规则 1.内部的box会在垂直方向,一个接一个的放置 2.box垂直方向的距离由margin决定,属于同一个bfc的两个相邻box的margin会发生重叠 3.每个元素的margin box的左边 ...

  7. awk书上练习

    文件car: plym fury chevy malibu ford mustang volvo s80 ford thundbd chevy malibu bmw 325i honda accord ...

  8. bzoj 1123 tarjan求割点

    #include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk mak ...

  9. Java 如何调用 oracle 的存储过程

    通过命令行创建存储过程 create or replace procedure emp_sal(eno emp.empno%type,esal out emp.sal%type) as begin s ...

  10. 洛谷P3538 [POI2012]OKR-A Horrible Poem [字符串hash]

    题目传送门 A Horrible Poem 题目描述 Bytie boy has to learn a fragment of a certain poem by heart. The poem, f ...