【问题标题】:SpringAMQP errorHandler and returnExceptions problemSpringAMQP errorHandler 和 returnExceptions 问题
【发布时间】:2019-05-19 15:42:33
【问题描述】:

我不确定我对errorHandler和returnExceptions的理解是否正确。

但这是我的目标:我从 App_A 发送了一条消息,使用 @RabbitListener 在 App_B 中接收消息。

根据文档 https://docs.spring.io/spring-amqp/docs/2.1.3.BUILD-SNAPSHOT/reference/html/_reference.html#annotation-error-handling

假设APP_B在消息处理过程中出现业务异常,通过@RabbitListener正确设置errorHandler和returnExceptions可以让异常返回给App_A。

我理解正确吗?

如果我是正确的,如何以正确的方式使用它?

使用我的代码,我在 APP_A 中一无所获。

这是我在 APP_B 中的代码

错误处理程序:

@Component(value = "errorHandler")
public class ErrorHandler implements RabbitListenerErrorHandler {

    @Override
    public Object handleError(Message arg0, org.springframework.messaging.Message<?> arg1,
            ListenerExecutionFailedException arg2) throws ListenerExecutionFailedException {
        throw new ListenerExecutionFailedException("msg", arg2, null);
    }

}

兔子监听器:

@RabbitListener(
        bindings = @QueueBinding(
            value = @Queue(value = "MRO.updateBaseInfo.queue", durable = "true"),
            exchange = @Exchange(name = "MRO_Exchange", type = ExchangeTypes.DIRECT, durable = "true"),
            key = "baseInfoUpdate"
        ),
//      errorHandler = "errorHandler",
        returnExceptions = "true"
    )
    public void receiveLocationChangeMessage(String message){
        BaseUpdateMessage newBaseInfo = JSON.parseObject(message, BaseUpdateMessage.class);
        dao.upDateBaseInfo(newBaseInfo);
    }

和APP_A中的代码

@Component
public class MessageSender {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void editBaseInfo(BaseUpdateMessage message)throws Exception {
        //and i am not sure set RemoteInvocationAwareMessageConverterAdapter in this way is right 
        rabbitTemplate.setMessageConverter(new RemoteInvocationAwareMessageConverterAdapter());

        rabbitTemplate.convertAndSend("MRO_Exchange", "baseInfoUpdate", JSON.toJSONString(message));
    }

}

我对三点很困惑:

1) 我必须同时使用errorHandler 和returnExceptions 吗?我认为errorHandler就像一个后处理器,可以让我自定义异常。如果我不需要自定义异常,我可以设置returnExceptions而不使用errorHandler吗?

2)@RabbitListener 注解的方法应该返回一些东西还是 void 就好了?

3)在发送方(我的情况是APP_A),是否有任何特定的配置来捕获异常?

我的工作环境:

春季启动 2.1.0

docker上的rabbitMQ服务器3.7.8

【问题讨论】:

    标签: spring-amqp


    【解决方案1】:

    1) 不,你不需要 en 错误处理程序,除非你想增强异常。

    2) 如果方法返回 void;发送者最终将等待超时以等待永远不会到达的回复,以防可能引发异常;这可能不是对资源的良好利用。最好总是发送回复,以释放发布方。

    3) 只需RemoteInvocationAwareMessageConverterAdapter。

    这是一个例子:

    @SpringBootApplication
    public class So53846303Application {
    
        public static void main(String[] args) {
            SpringApplication.run(So53846303Application.class, args);
        }
    
        @RabbitListener(queues = "foo", returnExceptions = "true")
        public String listen(String in) {
            throw new RuntimeException("foo");
        }
    
        @Bean
        public ApplicationRunner runner(RabbitTemplate template) {
            template.setMessageConverter(new RemoteInvocationAwareMessageConverterAdapter());
            return args -> {
                try {
                    template.convertSendAndReceive("foo", "bar");
                }
                catch (Exception e) {
                    e.printStackTrace();
                }
            };
        }
    
    }
    

    和

    org.springframework.amqp.AmqpRemoteException: java.lang.RuntimeException: foo
        at org.springframework.amqp.support.converter.RemoteInvocationAwareMessageConverterAdapter.fromMessage(RemoteInvocationAwareMessageConverterAdapter.java:74)
        at org.springframework.amqp.rabbit.core.RabbitTemplate.convertSendAndReceive(RabbitTemplate.java:1500)
        at org.springframework.amqp.rabbit.core.RabbitTemplate.convertSendAndReceive(RabbitTemplate.java:1433)
        at org.springframework.amqp.rabbit.core.RabbitTemplate.convertSendAndReceive(RabbitTemplate.java:1425)
        at com.example.So53846303Application.lambda$0(So53846303Application.java:28)
        at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:804)
        at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:794)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:324)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248)
        at com.example.So53846303Application.main(So53846303Application.java:15)
    Caused by: java.lang.RuntimeException: foo
        at com.example.So53846303Application.listen(So53846303Application.java:20)
    

    如您所见,有一个本地的org.springframework.amqp.AmqpRemoteException,其原因是远程服务器上抛出的实际异常。

    【讨论】:

    • 还有一个问题:当消费者在例外情况下不处理消息时,使用此功能补偿发布者是否是个好主意?
    • 我不明白你的意思;不要在 cmets 中对答案提出新问题;提出一个新问题,提供更明确的信息。
    猜你喜欢
    • 1970-01-01
    • 2010-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-07
    相关资源
    最近更新 更多