繁体   English   中英

如何避免出现意外错误时关闭SimpleMessageListenerContainer?

[英]How to avoid shutdown of SimpleMessageListenerContainer in case of unexpected errors?

我正在使用Java boot 1.4.0和'spring-boot-starter-amqp'连接到RabbitMq。 消息生产者,消费者和rabbitMq服务器都在我的控制之下。在生产中,几个月后一切正常。 但是突然我的消费者停止了以下例外情况。 因为我只生成始终有效的消息,所以我不知道出了什么问题。

但这导致我的监听器容器关闭。 因此,我的消息处理停止了。我不得不手动重新启动我的消息消费程序。

所以我的问题是:

  1. 在任何意外情况下,我们都可以避免完全关闭监听容器吗?
  2. 是否可以优雅地丢弃此类消息并使监听器容器保持活动状态?
  3. 如果不是,那么有什么方法可以检查我所有的监听容器是否正在运行,如果发现它们已死,则可以启动它们? (注:我查看了RabbitListenerEndpointRegistry.getListenerContainers()。但看起来它并不涵盖SimpleMessageListenerContainer容器。)

异常日志:

 2017-02-20 12:42:18.441 ERROR 18014 --- [writeToDBQQueueListenerContainer-17] osarlSimpleMessageListenerContainer : Consumer thread error, thread abort. java.lang.NoClassDefFoundError: org/springframework/messaging/handler/annotation/support/MethodArgumentNotValidException at org.springframework.amqp.rabbit.listener.ConditionalRejectingErrorHandler$DefaultExceptionStrategy.causeIsFatal(ConditionalRejectingErrorHandler.java:110) ~[spring-rabbit-1.6.1.RELEASE.jar!/:na] at org.springframework.amqp.rabbit.listener.ConditionalRejectingErrorHandler$DefaultExceptionStrategy.isFatal(ConditionalRejectingErrorHandler.java:97) ~[spring-rabbit-1.6.1.RELEASE.jar!/:na] at org.springframework.amqp.rabbit.listener.ConditionalRejectingErrorHandler.handleError(ConditionalRejectingErrorHandler.java:72) ~[spring-rabbit-1.6.1.RELEASE.jar!/:na] at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeErrorHandler(AbstractMessageListenerContainer.java:625) ~[spring-rabbit-1.6.1.RELEASE.jar!/:na] at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.handleListenerException(AbstractMessageListenerContainer.java:852) ~[spring-rabbit-1.6.1.RELEASE.jar!/:na] at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:685) ~[spring-rabbit-1.6.1.RELEASE.jar!/:na] at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:1165) ~[spring-rabbit-1.6.1.RELEASE.jar!/:na] at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:1149) ~[spring-rabbit-1.6.1.RELEASE.jar!/:na] at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$1100(SimpleMessageListenerContainer.java:95) ~[spring-rabbit-1.6.1.RELEASE.jar!/:na] at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1312) ~[spring-rabbit-1.6.1.RELEASE.jar!/:na] at java.lang.Thread.run(Thread.java:745) [na:1.8.0_91] Caused by: java.lang.ClassNotFoundException: org.springframework.messaging.handler.annotation.support.MethodArgumentNotValidException at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[na:1.8.0_91] at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_91] at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:89) ~[KattaQueueManager-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT] at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_91] ... 11 common frames omitted 

还有一个例外:

 2017-02-20 12:42:18.674 ERROR 18014 --- [imageQueueListenerContainer-53] osarlSimpleMessageListenerContainer : Consumer thread error, thread abort. java.lang.NoClassDefFoundError: com/rabbitmq/utility/Utility at org.springframework.amqp.rabbit.listener.BlockingQueueConsumer.checkShutdown(BlockingQueueConsumer.java:348) ~[spring-rabbit-1.6.1.RELEASE.jar!/:na] at org.springframework.amqp.rabbit.listener.BlockingQueueConsumer.nextMessage(BlockingQueueConsumer.java:402) ~[spring-rabbit-1.6.1.RELEASE.jar!/:na] at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:1160) ~[spring-rabbit-1.6.1.RELEASE.jar!/:na] at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:1149) ~[spring-rabbit-1.6.1.RELEASE.jar!/:na] at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$1100(SimpleMessageListenerContainer.java:95) ~[spring-rabbit-1.6.1.RELEASE.jar!/:na] at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1312) ~[spring-rabbit-1.6.1.RELEASE.jar!/:na] at java.lang.Thread.run(Thread.java:745) [na:1.8.0_91] Caused by: java.lang.ClassNotFoundException: com.rabbitmq.utility.Utility at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[na:1.8.0_91] at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_91] at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:89) ~[KattaQueueManager-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT] at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_91] ... 7 common frames omitted 2017-02-20 12:42:18.675 ERROR 18014 --- [imageQueueListenerContainer-53] osarlSimpleMessageListenerContainer : Stopping container from aborted consumer 

我的消费者示例代码:

@Bean
public MessageConverter jsonMessageConverter(){
    //return new JsonMessageConverter();
    Jackson2JsonMessageConverter converter =  new   Jackson2JsonMessageConverter();

    converter.setClassMapper(new ClassMapper() {
        @Override
        public Class<?> toClass(MessageProperties properties) {
            return String.class;
        }

        @Override
        public void fromClass(Class<?> clazz, MessageProperties properties) {
        }
    });

    return converter;
}

@Bean
public ConnectionFactory connectionFactory() 
{
    CachingConnectionFactory connectionFactory =
            new CachingConnectionFactory(_rabbitmqHost, _rabbitmqPort);
    return connectionFactory;
}

@Bean
public RabbitTemplate rabbitTemplate() 
{
    RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory());
    rabbitTemplate.setMessageConverter(jsonMessageConverter());
    return rabbitTemplate;
}

@Bean
TopicExchange exchange() 
{
    return new TopicExchange("MyExchange");
}

@Bean
public Queue mainQueue() 
{
    return new Queue("MyMainQ");
}

@Bean
public Binding mainRouteBinding() 
{
    return BindingBuilder.bind(mainQueue()).to(exchange()).with("MyMainQ");
}

@Bean
SimpleMessageListenerContainer mainQueueListenerContainer(
        ConnectionFactory connectionFactory, 
        @Qualifier("mainQueueListenerAdapter") MessageListenerAdapter listenerAdapter) 
{
    SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
    container.setConnectionFactory(connectionFactory);
    container.setQueues(mainQueue());

    container.setMessageConverter(jsonMessageConverter());

    container.setMessageListener(listenerAdapter);
    container.setConcurrentConsumers(1);
    return container;
}

@Bean
MessageListenerAdapter mainQueueListenerAdapter(MainConsumer receiver) 
{
    MessageListenerAdapter msgAdapter = new MessageListenerAdapter(receiver, "receiveMessage");

    msgAdapter.setMessageConverter(jsonMessageConverter());

    return msgAdapter;
}

@Bean
MainConsumer getMainConsumer()
{
    return new MainConsumer();
}

//
//The receiving method in MainConsumer class looks as given below
public void receiveMessage(String message) 
{
     // My business logic goes here ...
}

几个月前,我遇到了同样的问题,这对我有所帮助。 如果Rabbit Java Client的版本低于4.0.0,则您没有自动的恢复连接,需要进行如下设置:

ConnectionFactory factory = new ConnectionFactory();
factory.setUsername(userName);
factory.setPassword(password);
factory.setVirtualHost(virtualHost);
factory.setHost(hostName);
factory.setPort(portNumber);

// connection that will recover automatically
factory.setAutomaticRecoveryEnabled(true);

// attempt recovery every 10 seconds
factory.setNetworkRecoveryInterval(10000);

Connection conn = factory.newConnection();

尝试查看RabbitMQ的文档: Rabbit Client API

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM