安全终止 Spring JMS 应用程序 [英] Safely Terminating a Spring JMS application

查看:36
本文介绍了安全终止 Spring JMS 应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个严格使用 bean 注释设置的 Spring boot JMS 应用程序,并且正在从 WebshpereMQ 读取消息.一切正常,除了我不知道如何安全地关闭这个应用程序.一旦我的 JMSListener 方法读取了所有消息,它就会保持空闲状态.我与队列建立初始连接并访问队列深度,因此理想情况下,当队列深度为零时,它需要将其打包并关闭.我目前的解决方法(我根本不喜欢它)是当深度为零时我调用的这个小方法(从侦听器内部,yikes):

I'm working on a Spring boot JMS application that is setup strictly with bean annotations and is reading messages from WebshpereMQ. Everything works except I can't figure out how to safely shutdown this application. Once my JMSListener Method reads all the messages it just stays idle. I make an initial connection to the queue and access the queue depth, so ideally when queue depth is zero, it needs to wrap it up and shut down. My current workaround (and I do not like it at all) is this little method I call (from inside the listener, yikes) when depth is zero:

public void shutDownApplication() {
        logger.info("Initiating shutdown of application...");
        System.out.println("Terminating application...");
        Thread.currentThread().interrupt();
        System.exit(0);
    }

我不喜欢这个解决方案.Spring 也没有,因为这显然在过程中作为错误中断,在应用程序死亡之前,我的 JMSListener 启动回滚并将最后一条剩余的消息放回队列中.

I do not like this solution. And neither does Spring, because this is obviously interrupted as an error mid-process and before the application dies my JMSListener initiates a rollback and puts the single last remaining message back on the queue.

在查看以下来源后,我尝试了其他一些解决方案:

I tried a few other solutions after looking at the following sources:

我如何停止/启动/暂停@JmsListener(干净的方式)

如何优雅地关闭 Spring JMS MessageListenerAdapter

http://forum.spring.io/forum/spring-projects/integration/jms/124980-graceful-shutdown-of-jms-message-listener

这是我最近的解决方案:

This was my most recent solution:

public class JMSShutdownService {

    public void initiateShutdown() {
        JmsListenerEndpointRegistry jmsListenerEndpointRegistry = new JmsListenerEndpointRegistry();
        Collection<MessageListenerContainer> col = jmsListenerEndpointRegistry
                .getListenerContainers();
        for (MessageListenerContainer cont : col) {
            cont.stop(Thread.currentThread());
        }
        System.exit(0);
    }

}

这会杀死应用程序,但仍将最后一条消息放回队列中.我仍在努力理解 Spring 的许多错综复杂之处,所以这一切都归结为这一点.我觉得主要问题是它在我发出关闭信号的侦听器内.据我所知,听众不应该为此负责.但是我不确定如何定义在侦听器启动之前关闭应用程序的方法,或者如何在队列深度为零时弹出侦听器.

This kills the application but still puts the last message back on the queue. There are alot of intricacies of Spring I'm still trying to understand, so it all really comes down to that. I feel like the main issue is that it is inside the listener I signal for shutdown. From what I gather the listener shouldn't be responsible for that. But I'm not sure how to define a way to shutdown the application before the listener starts, or how to pop out of the listener when queue depth is zero.

有什么想法吗?

推荐答案

JmsListenerEndpointRegistry jmsListenerEndpointRegistry = new JmsListenerEndpointRegistry();

那没用;新的注册表将没有任何容器,如果您使用 @JmsListener,则需要从应用程序上下文中获取注册表.

That's no use; a new registry won't have any containers, if you are using @JmsListener you need to get the registry from the application context.

System.exit(0);

那只会杀死 JVM.

最重要的是你应该在不同线程上停止容器 - 使用任务执行器启动一个新线程来停止容器;容器将在停止之前等待线程退出侦听器.

The bottom line is you should stop on the container on a different thread - use a task executor to start a new thread to stop the container; the container will wait for the thread to exit the listener before stopping.

停止容器后,您需要等待一个宽限期才能杀死 JVM.

After stopping the container, you will need to wait for a grace period before killing the JVM.

你怎么知道你已经完成了?停止容器后可能会显示另一条消息,在这种情况下,您可能会在日志中看到一些关于消息因容器停止而被拒绝的噪音.

How do you really know you are done? Another message could show up after you stop the container, in which case you'll likely see some noise in the log about a message being rejected because the container is stopping.

编辑

在我的听众中...

...
if (timeToShutDown()) {
    Executors.newSingleThreadExecutor.execute(new Runnable() {

        public void run() {
            stopTheContainer();
        }
    }
 }
 // exit the listener so the container can actually stop.

这篇关于安全终止 Spring JMS 应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆