当前位置:   article > 正文

RabbitMQ常见异常处理(踩了一路坑)_listener method 'no match' threw exception

listener method 'no match' threw exception

异常一:方法不匹配异常

Listener method 'no match' threw exception刷屏

2020-03-26 11:00:07.747 [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer#1-1] WARN  org.springframework.amqp.rabbit.listener.ConditionalRejectingErrorHandler.log(117) - Execution of Rabbit message listener failed.
org.springframework.amqp.rabbit.listener.exception.ListenerExecutionFailedException: Listener method 'no match' threw exception
	at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:204)
	at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:129)
	at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:1542)
	at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.actualInvokeListener(AbstractMessageListenerContainer.java:1468)
	at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:1456)
	at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:1451)
	at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:1400)
	at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:870)
	at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:854)
	at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$1600(SimpleMessageListenerContainer.java:78)
	at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.mainLoop(SimpleMessageListenerContainer.java:1137)
	at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1043)
	at java.lang.Thread.run(Thread.java:748)
Caused by: org.springframework.amqp.AmqpException: No method found for class [B
	at org.springframework.amqp.rabbit.listener.adapter.DelegatingInvocableHandler.getHandlerForPayload(DelegatingInvocableHandler.java:149)
	at org.springframework.amqp.rabbit.listener.adapter.DelegatingInvocableHandler.invoke(DelegatingInvocableHandler.java:129)
	at org.springframework.amqp.rabbit.listener.adapter.HandlerAdapter.invoke(HandlerAdapter.java:61)
	at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:196)
	... 12 common frames omitted
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

先上我的代码:

@Slf4j
@Component
@RabbitListener(queues = "mall.order.cancel")
public class CancelOrderReceiver {

    @Autowired
    private OmsPortalOrderService portalOrderService;

    @Resource
    private CancelOrderSender cancelOrderSender;

    @RabbitHandler
    public void handler(Long orderId){
        try {
            log.info("process orderId:{}", orderId);
            portalOrderService.cancelOrder(orderId);
        } catch (Exception e) {
            log.error(ExceptionUtils.getStackTrace(e));
            // 异常处理
            cancelOrderSender.sendFailedMessage(orderId);
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

为什么会出现方法未匹配呢?原因在@RabbitListener身上,当此注解放到类上时,会根据数据类型去匹配@RabbitHandler注解的方法,我的handler方法入参是Long类型,如果传入的是String类型就会报Listener method 'no match' threw exception了,找到了问题(RabbitMQ的requeue机制),下面给出解决方法:

解决方法1:

再增加一个handler(String orderId)方法,无论传入的是Long型还是String型都会得到处理,这种方式比较笨,不推荐使用

解决方法2(推荐):

@RabbitListener注解放到方法上,如下代码:

@Slf4j
@Component
public class CancelOrderReceiver {

    @Autowired
    private OmsPortalOrderService portalOrderService;

    @Resource
    private CancelOrderSender cancelOrderSender;

    @RabbitHandler
    @RabbitListener(queues = "mall.order.cancel")
    public void handler(Long orderId){
        try {
            log.info("process orderId:{}", orderId);
            portalOrderService.cancelOrder(orderId);
        } catch (Exception e) {
            log.error(ExceptionUtils.getStackTrace(e));
            // 异常处理
            cancelOrderSender.sendFailedMessage(orderId);
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

这样无论你传入的数据类型是什么,都会进入此方法,不用担心刷屏了。当然如果传入的类型不匹配,也会报错的。所以要与消息生产者约束好数据类型是非常有必要的。

解决方法3:

rabbitmq的“requeue”配置为false。这种方式简单粗暴,但异常不好捕获,后续的异常处理难进行

异常二:监听方法内异常

Listener method '***' threw exception刷屏

2020-03-26 11:46:22.789 [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer#0-1] WARN  org.springframework.amqp.rabbit.listener.ConditionalRejectingErrorHandler.log(117) - Execution of Rabbit message listener failed.
org.springframework.amqp.rabbit.listener.exception.ListenerExecutionFailedException: Listener method 'public void com.macro.mall.portal.component.CancelOrderReceiver.handler(java.lang.Long)' threw exception
	at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:204)
	at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:129)
	at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:1542)
	at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.actualInvokeListener(AbstractMessageListenerContainer.java:1468)
	at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:1456)
	at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:1451)
	at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:1400)
	at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:870)
	at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:854)
	at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$1600(SimpleMessageListenerContainer.java:78)
	at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.mainLoop(SimpleMessageListenerContainer.java:1137)
	at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1043)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.NumberFormatException: For input string: "嘿嘿嘿"
	at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
	at java.lang.Integer.parseInt(Integer.java:580)
	at java.lang.Integer.parseInt(Integer.java:615)
	at com.macro.mall.portal.component.CancelOrderReceiver.handler(CancelOrderReceiver.java:31)
	at sun.reflect.GeneratedMethodAccessor122.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:171)
	at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:120)
	at org.springframework.amqp.rabbit.listener.adapter.HandlerAdapter.invoke(HandlerAdapter.java:50)
	at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:196)
	... 12 common frames omitted
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

看我的代码:

    @RabbitHandler
    @RabbitListener(queues = "mall.order.cancel")
    public void handler(Long orderId){
        Integer.parseInt("嘿嘿嘿"); // 演示异常使用
        try {
            log.info("process orderId:{}", orderId);
            portalOrderService.cancelOrder(orderId);
        } catch (Exception e) {
            log.error(ExceptionUtils.getStackTrace(e));
            // 异常处理
            cancelOrderSender.sendFailedMessage(orderId);
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

很明显Integer.parseInt("嘿嘿嘿")会报错,导致异常刷屏

解决方法:

将监听方法内的所有代码用try...cache包裹,并在cache中增加异常处理,如下代码:

    @RabbitHandler
    @RabbitListener(queues = "mall.order.cancel")
    public void handler(Long orderId){
        try {
            Integer.parseInt("嘿嘿嘿"); // 演示异常使用
            log.info("process orderId:{}", orderId);
            portalOrderService.cancelOrder(orderId);
        } catch (Exception e) {
            log.error(ExceptionUtils.getStackTrace(e));
            // 异常处理
            cancelOrderSender.sendFailedMessage(orderId);
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

先写这么多吧,后续遇到问题会继续更新,如果有好的方案欢迎给我留言,共同学习共同进步

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/716874
推荐阅读
相关标签
  

闽ICP备14008679号