【问题标题】:Determining when to terminate a Jms Listener in SpringBoot when Queue has zero messages当队列的消息为零时,确定何时终止 SpringBoot 中的 Jms 侦听器
【发布时间】:2017-12-18 15:37:13
【问题描述】:

决定何时杀死听众的正确方法或流行惯例是什么?我似乎在任何地方都找不到可靠的答案。我正在处理的队列是 IBM 的 MQ 队列,我通常知道您会一直阅读,直到收到 2033 错误代码(我的公司在其他应用程序中这样做),此时您可以结束,但对于 SpringBoot Jms 应用程序这里有什么约定?一旦队列为空,侦听器就会挂起,直到有更多消息到来。如果我愿意,我知道如何杀死它,但我怎么知道何时?

作为一个例子,这是我放在一起的示例项目的配置

@Configuration
@EnableTransactionManagement
public class JmsConfig {

@Bean
protected DefaultJmsListenerContainerFactory defaultJmsListenerContainerFactory() throws JMSException {
    DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
    factory.setConnectionFactory(mqQueueConnectionFactory());
    factory.setConcurrency("1");
    factory.setSessionTransacted(true);
    factory.setAutoStartup(true);
    factory.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
        factory.setErrorHandler(new JmsErrorHandler());
    return factory;
}

@Bean
public MQQueueConnectionFactory mqQueueConnectionFactory() {
    MQQueueConnectionFactory mqQueueConnectionFactory = new MQQueueConnectionFactory();
    mqQueueConnectionFactory.setHostName(host);
    try {
        mqQueueConnectionFactory.setTransportType(WMQConstants.WMQ_CM_CLIENT);
        mqQueueConnectionFactory.setCCSID(1208);
        mqQueueConnectionFactory.setChannel(channel);
        mqQueueConnectionFactory.setPort(port);
        mqQueueConnectionFactory.setQueueManager(queueManager);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return mqQueueConnectionFactory;
}

这里是监听器

@Component
public class Consumer {

    @JmsListener(id = "myQueue", destination = "queue")
    public void processMessage(Message message) throws MQException, IOException {
        try {
            String messageString = ((TextMessage) message).getText();
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }
}

除了主类和ErrorHandler之外,它实际上就是整个示例项目,它会处理消息。我在其他应用程序中所做的是在给定队列值的情况下实例化 MQQueue,而 queue.getCurrentDepth() 很简单,如果我得到一个零,然后我调用一个 ListenerContainerController 的实例,然后在给定队列 ID 的情况下从 JmsListenerEndpointRegistry 调用 stop .

Spring 是否有一种简单的沟通方式“嘿,你的队列现在是空的”,或者有没有办法在 x 时间过去后结束它?

【问题讨论】:

  • 为什么要关闭它?如果您让它继续运行,它将处理新消息(如果它们被放入该队列)。
  • @JoshMc 因为在这种情况下,我处理读取消息并根据我处理的内容生成报告,在该报告中应该清除队列并且什么都没有。这是一个日常运行的过程,我不确定我们是否希望它按照您的描述进行设置。您的评论让我想知道我是否在使用这个 JmsListener 有点不合常规。但无论是运行一次还是保持正确收听,该过程都必须在某个时候结束?
  • 不要为此使用监听器。如果这就是您想要的全部内容,请使用JmsTemplate 并阅读直到没有更多内容可阅读。生成报告并完成它。侦听器旨在在消息出现时继续运行和处理消息。您甚至可以使用 Spring Batch 和 JmsItemReader 来阅读消息,直到没有更多内容可阅读。
  • @M.Deinum 哇。我学到了一些新东西,而且显然做错了。很长一段时间以来,我一直有一种代码味道,无法真正弄清楚为什么,我偶然发现的所有文档/资源以及我在这里遇到的问题的答案(也许我问了错误的问题......)让我相信JmsListener 是我在这种过程中所需要的。随意提取您对答案的评论并详细说明您认为合适的内容,我可以接受它,因为这将是我要走的路。已经阅读过文档。感谢您的评论。
  • 使用此方法时,请务必使用CachingConnectionFactory 以便缓存消费者 - 这样可以避免模板必须为每条消息创建一个新消费者。

标签: java spring-boot ibm-mq spring-jms


【解决方案1】:

JmsListener 旨在接收和处理到达目的地的消息。它不打算在目的地为空然后停止之前读取,它旨在继续运行。

而只是使用JmsTemplate 及其receive 方法来读取消息,直到它们完成。然后处理它们并写一份报告。

最终,您甚至可以使用JmsItemReader 创建一个 Spring Batch 作业,该阅读器将一直阅读,直到没有更多内容可阅读,然后一切结束。在它下面还使用JmsTemplate

然后您可以做的是,当您使用 Spring Boot 时,使用 cron 作业每天触发该作业(这基本上完成了启动您创建的 jar)。有关如何使用batch applications,另请参阅 Spring Boot 的参考指南。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-07
    • 2016-02-06
    • 1970-01-01
    • 2011-01-20
    相关资源
    最近更新 更多