spring amqp rabbit max consumer connection retries

醉酒当歌 提交于 2019-12-20 06:17:54

问题


I am trying to establish the max number of retries from my app to rabbit broker. I have the retry interceptor,

@Bean
public RetryOperationsInterceptor retryOperationsInterceptor() {
    return RetryInterceptorBuilder.stateless()
            .maxAttempts(CommonConstants.MAX_AMQP_RETRIES)
            .backOffOptions(500, 2.0, 3000)
            .build();
}

and this is used inside listener container,

container.setAdviceChain(new Advice[]{retryOperationsInterceptor()});

However, after a couple of retries, the consumer attempts connection all over again in an endless loop,

2017-02-21 15:03:12.229  WARN 9292 --- [nsumerThread_92]  o.s.a.r.l.SimpleMessageListenerContainer : Consumer raised exception, processing  can restart if the connection factory supports it. Exception summary:  org.springframework.amqp.AmqpConnectException: java.net.ConnectException:    Connection refused: connect
2017-02-21 15:03:12.229  INFO 9292 --- [nsumerThread_92] o.s.a.r.l.SimpleMessageListenerContainer : Restarting Consumer: tags=[{}], channel=null, acknowledgeMode=AUTO local queue size=0
2017-02-21 15:03:13.245  WARN 9292 --- [nsumerThread_93] o.s.a.r.l.SimpleMessageListenerContainer : Consumer raised exception, processing can restart if the connection factory supports it. Exception summary: org.springframework.amqp.AmqpConnectException: java.net.ConnectException: Connection refused: connect
2017-02-21 15:03:13.245  INFO 9292 --- [nsumerThread_93] o.s.a.r.l.SimpleMessageListenerContainer : Restarting Consumer: tags=[{}], channel=null, acknowledgeMode=AUTO local queue size=0
2017-02-21 15:03:13.261 ERROR 9292 --- [nsumerThread_83] o.s.a.r.l.SimpleMessageListenerContainer : Failed to check/redeclare auto-delete queue(s).

I want the app to fail and error out because of lack of connectivity to the broker after a MAX_RETRY # limit.

thanks for the help

EDIT

As suggested by @artem-bilan, I ended up using a Component

public class BrokerFailureEventListener implements ApplicationListener<ListenerContainerConsumerFailedEvent>

In this class the onApplicationEvent I counted the number of failures and then take appropriate action.

In case of producer-side, it's a little different scenario. As explained by @artem-bilan, the application would need to take care of any issues. I explored using netflix-hystrix and added a fallback method for the production method and will go with that route. thanks much again.


回答1:


Well, you misunderstood a bit container.setAdviceChain(new Advice[]{retryOperationsInterceptor()});. It is for the business errors during messages processing:

Business exception handling, as opposed to protocol errors and dropped connections, might need more thought and some custom configuration, especially if transactions and/or container acks are in use. Prior to 2.8.x, RabbitMQ had no definition of dead letter behaviour, so by default a message that is rejected or rolled back because of a business exception can be redelivered ad infinitum. To put a limit in the client on the number of re-deliveries, one choice is a StatefulRetryOperationsInterceptor in the advice chain of the listener. The interceptor can have a recovery callback that implements a custom dead letter action: whatever is appropriate for your particular environment.

In contradiction to the:

In fact it loops endlessly trying to restart the consumer, and only if the consumer is very badly behaved indeed will it give up. One side effect is that if the broker is down when the container starts, it will just keep trying until a connection can be established.

What you need is ListenerContainerConsumerFailedEvent, which is emitted as:

private void logConsumerException(Throwable t) {
        if (logger.isDebugEnabled()
                || !(t instanceof AmqpConnectException  || t instanceof ConsumerCancelledException)) {
            logger.warn(
                    "Consumer raised exception, processing can restart if the connection factory supports it",
                    t);
        }
        else {
            logger.warn("Consumer raised exception, processing can restart if the connection factory supports it. "
                    + "Exception summary: " + t);
        }
        publishConsumerFailedEvent("Consumer raised exception, attempting restart", false, t);
    }

So, you can listen for those events and stop your application when some condition is reached.



来源:https://stackoverflow.com/questions/42377113/spring-amqp-rabbit-max-consumer-connection-retries

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!