activemq为保证消息的可靠性,引入重发机制。
触发重发的情况:
1.在使用事务的Session中,调用rollback()方法;
2.在使用事务的Session中,调用commit()方法之前就关闭了Session;
3.在Session中使用CLIENT_ACKNOWLEDGE签收模式或者INDIVIDUAL_ACKNOWLEDGE模式,并且调用了recover()方法。
参数配置:
@Bean //此处是结合springboot设置的redeliveryPolicy
public RedeliveryPolicy redeliveryPolicy(){
RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
//设置初始化重发延迟时间,默认1000毫秒
redeliveryPolicy.setInitialRedeliveryDelay(1000);
//设置最大重发次数,默认为6
redeliveryPolicy.setMaximumRedeliveries(6);
//是否开启重发延迟大小倍数递增,默认false
redeliveryPolicy.setUseExponentialBackOff(true);
//重发延迟递增倍数,默认为5
redeliveryPolicy.setBackOffMultiplier(2);
//这个参数主要是为了防止高并发下,消息重发会在同一时刻发生,让消息在时间上消费的更加均衡,默认为false
redeliveryPolicy.setUseCollisionAvoidance(true);
//设置下次重发延迟波动百分比,默认0.15,此处写成15是因为源码中对参数*0.01
redeliveryPolicy.setCollisionAvoidancePercent((short)15);
//设置最大重发延迟,默认为-1,表示无限增大
redeliveryPolicy.setMaximumRedeliveryDelay(10000);
return redeliveryPolicy;
}
下面通过源码进行分析,该方法位于 RedeliveryPolicy 类中:
public RedeliveryPolicy() {
//redeliveryDelay属性在对象被初始化时由initialRedeliveryDelay属性赋值,此时redeliveryDelay为1000
this.redeliveryDelay = this.initialRedeliveryDelay;
this.preDispatchCheck = true;
}
//previousDelay初始值为0,由ActivemqMessageConsumer类调用getNextRedeliveryDelay
if (currentRedeliveryCount > 0) {
this.redeliveryDelay = this.redeliveryPolicy.getNextRedeliveryDelay(this.redeliveryDelay);
} else {
this.redeliveryDelay = this.redeliveryPolicy.getInitialRedeliveryDelay();
}
public long getNextRedeliveryDelay(long previousDelay) {
long nextDelay = this.redeliveryDelay;
//当倍增属性useExponentialBackOff为true并且倍数大于1
if (previousDelay > 0L && this.useExponentialBackOff && this.backOffMultiplier > 1.0D) {
//原来的延迟*倍数
nextDelay = (long)((double)previousDelay * this.backOffMultiplier);
//如果最大延迟不等于-1(说明有延迟上限),并且下一次的延迟时间大于最大延迟
if (this.maximumRedeliveryDelay != -1L && nextDelay > this.maximumRedeliveryDelay) {
//比较最大延迟和redeliveryDelay的值,取出最大值作为下一次延迟时长,此时如果redeliveryDelay设置的
//比最大值大,那么最大值似乎就不起作用了,后面就会一直采用redeliveryDelay的值
nextDelay = Math.max(this.maximumRedeliveryDelay, this.redeliveryDelay);
}
}
//当useCollisionAvoidance为true时,让nextDelay加上collisionAvoidanceFactor上下波动的值,nextDelay+nextDelay*0.15
//或者nextDelay-nextDelay*0.15
if (this.useCollisionAvoidance) {
Random random = getRandomNumberGenerator();
//随机取正负值
double variance = (random.nextBoolean() ? this.collisionAvoidanceFactor : -this.collisionAvoidanceFactor) * random.nextDouble();
nextDelay = (long)((double)nextDelay + (double)nextDelay * variance);
}
return nextDelay;
}
欢迎访问个人博客码农地带,共同学习,共同进步!