-
消息消费过程,当spring-amqp消费者监听到有消息进入时,会启动一个异步消费者(AsyncMessageProcessingConsumer)线程去处理消息,该类是静态内部类所以是线程安全的,该类在执行run方法时主要做一些绑定队列、事物支持等的校验;然后while循环监听消费消息。如下是消息的流转过程
-
SimpleMessageListenerContainer.receiveAndExecute
-
该方法判断是否有事物管理器,有的话就注册,没有继续执行步骤2
-
-
SimpleMessageListenerContainer.doReceiveAndExecute
-
根据txSize(要处理的消息数量)调用步骤三的方法executeListener循环一条条处理;
-
消息确认异常捕获
-
Throwable异常捕获,当有事物管理器时做回滚操作rollbackOnExceptionIfNecessary;无事物时调用rollbackOnExceptionIfNecessary方法处理异常
-
-
AbstractMessageListenerContainer.executeListener
-
对消息做一些前置处理postProcessMessage
-
执行invokeListener方法
-
处理异常handleListenerException
-
-
代理执行actualInvokeListener方法
-
执行doInvokeListener方法
-
-
AbstractMessageListenerContainer.doInvokeListener
-
执行listener的onMessage方法
-
-
.MessageListenerAdapter.onMessage
-
判断是否是自定义的listener,如果不是采用委托机制执行onMessage
-
自定义listener执行invokeListenerMethod方法(代理模式)
-
-
MessageListenerAdapter.invokeListenerMethod
-
该方法抛出ListenerExecutionFailedException异常,也就是当我们的处理方法异常时抛出的
-
-
-
通过上面几步我们可以看到有两处处理了抛出的异常
-
executeListener中的handleListenerException方法 : 该方法会继续出发invokeErrorHandler方法,这个方法就是调用ListenerContainer中注册的errorHandler实体来处理异常的,当然默认的事项是ConditionalRejectingErrorHandler,里面对未到达消费者方法的消息由于解析错误产生的异常做了处理,而对于一般的业务异常并未做处理,所以我们可以定义ErrorHandler来处理自己的业务异常
-
另一个是最开始的doReceiveAndExecute方法中调用的BlockingQueueConsumer消费者类的rollbackOnExceptionIfNecessary方法做出的处理,该方法中会判断当该消息即没有自动确认也没有手动确认的时候会触发this.channel.basicNack(deliveryTag.getAsLong(), true,RabbitUtils.shouldRequeue(this.defaultRequeueRejected, ex, logger));这段代码,我们知道basicNak方法是将消息返回队列的其中左后一个requeue参数就是判定是返回队列还是直接丢弃。而其中最关键的参数defaultRequeueRejected就是在SimpleMessageListenerContainer中通过createBlockingQueueConsumer方法设置的,这个参数也是在配置文件中指定的,默认是true private volatile boolean defaultRequeueRejected = true;
-
-
通过上面的源码分析,我们可以看出若想业务异常不重复返回队列,可以自定义errorHandler处理异常消息,然后设置
<rabbit:listener-container connection-factory="connectionFactory" prefetch="4" concurrency="8" requeue-rejected="false">