消费者之间的循环不工作?

时间:2015-03-03 14:47:23

标签: java rabbitmq messaging amqp spring-amqp

我正在尝试修改我的spring-amqp项目,以便在抛出某个异常类型时,始终重新排列该消息。否则,重试x次,然后拒绝。

以下是相关配置xml

<rabbit:connection-factory id="rabbitMqConnectionFactory" host="localhost" port="5672" />

<rabbit:template id="rabbitTemplate" connection-factory="rabbitMqConnectionFactory"
    exchange="my.exchange" routing-key="foo"/>

<bean id="myListenerContainer" class="org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer">
    <property name="connectionFactory" ref="rabbitMqConnectionFactory" />
    <property name="messageListener" ref="myMessageListener" />
    <property name="concurrentConsumers" value="2" />
    <property name="queueNames" value="work.q" />
    <property name="adviceChain" ref="myRetryInterceptor" />
</bean>

这是相关代码

 @Bean(name="myRetryInterceptor")
public MethodInterceptor getInterceptor() {
    return RetryInterceptorBuilder.stateless()
        .retryPolicy(getRetryPolicy())
        .recoverer(new RejectAndDontRequeueRecoverer())
        .build();
}

private RetryPolicy getRetryPolicy() {      
    return new SimpleRetryPolicy(5, Collections.EMPTY_MAP) {
        @Override
        public boolean canRetry(RetryContext context) {
            Throwable t = context.getLastThrowable();
            if ((t!=null) && (t.getCause() instanceof com.test.MessageRetryException)) {
                return true;
            }
            return super.canRetry(context);
        }
    };
}

我注意到当我故意在myMessageListener中抛出一个com.test.MessageRetryException时,同一个线程会一遍又一遍地给出该消息。这与没有修改弹簧类的实现形成对比。在这种情况下,消息交替地给予一个消费者线程然后另一个消费者线程。我做错了吗?

@Bean(name="myRetryInterceptor")
//all consumers are given the message here
public MethodInterceptor getInterceptor() {
    return RetryInterceptorBuilder.stateful()
            .maxAttempts(5)
            .recoverer(new RejectAndDontRequeueRecoverer())
            .build();
}

1 个答案:

答案 0 :(得分:2)

没有;你做错了什么;无状态重试是在原始传递的范围内完成的(在同一个线程上)。在重试耗尽之前不会发生消息拒绝。

另一方面,有状态重试拒绝每次尝试的传递,它将被重新提交并(可能)由另一个线程处理。

由于rabbitmq现在在队列的头部重新排队被拒绝的消息,因此切换到有状态恢复并没有任何好处,它需要消息ID头才能工作(因此可以确定消息的状态)。

编辑:嗯 - 我看到你正在使用有状态重试;所以我希望重新发生在备用线程上。

如果您可以在Gist或某个地方发布DEBUG日志;我可以看看。但是,正如我所说,无国籍重审更简单。