大家知道,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. pytesser模块WindowsError错误解决方法

    在使用pytesser做图片文字识别时遇到 WindowsError: [Error 2] 错误,报错内容如下: Traceback (most recent call last): File &qu ...

  2. 《secret》读书笔记

    这是在从大连到深圳飞机上看完的一本书,也是大学毕业时室友整理书籍给我的.正好回来的途中,一气呵成读完了. 全书讲了几个事情,其中费了很大篇幅就围绕一个主题,当然书题了——秘密,这个秘密就是“吸引力法则 ...

  3. Codeforces Round #441 (Div. 2)

    Codeforces Round #441 (Div. 2) A. Trip For Meal 题目描述:给出\(3\)个点,以及任意两个点之间的距离,求从\(1\)个点出发,再走\(n-1\)个点的 ...

  4. PHP发送邮件:如何自定义reply-to头部以及附件

    虽然有现成的类库(如PEAR)可以很方便地实现附件添加和发送,但是对于一些小站点(服务器硬件.网站规模都不理想),安装PEAR可能会带来不必要的负担,降低WEB程序运行效率. 通过对邮件格式的认识,我 ...

  5. Codefroces 919D Substring(拓扑排序+DP)

    题目链接:http://codeforces.com/problemset/problem/919/D 题目大意:给你一张有向图,给你每个顶点上的字母和一些边,让你找出一条路径,路径上的相同字母数最多 ...

  6. Codeforces Round #423 Div. 2 C-String Reconstruction(思维)

    题目大意:告诉你n个字符串以及这些字符串在字符串s中出现的位置(x1,x2.....xn),要求在满足上述条件的情况下,求出字典序最小的字符串s. 解题思路:主要问题是,如果直接模拟是会超时的,比如v ...

  7. spring自定义注解的使用

    前几天写了一个消息中间件(kafka)的封装,业务方发现消费者需要配置的东西太多(每增加一个topic和实现类都需要在配置文件中加,会显得很繁琐).于是我为了尽量减少这个XML配置,采用注解的方式来获 ...

  8. Python+Selenium 自动化实现实例-模块化调用

    public 目录存一些公共模块,供用例调用.login.py 内容如下: # coding=utf-8 import time # login def login(driver): driver.f ...

  9. Error: could not open `C:\Java\jre7\lib\i386\jvm.cfg

    打开eclipse时出现Error: could not open `C:\Program Files\Java\jre7\lib\i586\jvm.cfg’) 删除 c:\windows\syste ...

  10. linux中的vim 编辑一行内容,如何使光标快速移动到行首和行尾以及行中间某处啊?

    光标定位G 移至行行首nG 移至第n行行首n+ 移n行行首n- 移n行行首n$ 移n行(1表示本行)行尾0 所行行首$ 所行行尾^ 所行首字母h,j,k,l 左移移移右移H 前屏幕首行行首M 屏幕显示 ...