ActiveMQ消费者平滑关闭
平滑關(guān)閉的思路就是讓正在執(zhí)行的任務(wù)線程正常執(zhí)行完畢,然后再關(guān)閉JVM。在JVM關(guān)閉之前觸發(fā)一個(gè)shutdown hook,jvm自帶這個(gè)hook,在java啟動(dòng)時(shí)候就可以注冊這樣的hook。
##1、簡述JVM關(guān)閉鉤子(shutdown hook) 首先JVM的關(guān)閉方式可以分為三種:
-
正常關(guān)閉:當(dāng)最后一個(gè)非守護(hù)線程結(jié)束或者調(diào)用了System.exit或者通過其他特定平臺(tái)的方法關(guān)閉(發(fā)送SIGINT,SIGTERM信號(hào)等)
-
強(qiáng)制關(guān)閉:通過調(diào)用Runtime.halt方法或者是在操作系統(tǒng)中直接kill(發(fā)送SIGKILL信號(hào))掉JVM進(jìn)程
-
異常關(guān)閉:運(yùn)行中遇到RuntimeException異常等。
在某些情況下,我們需要在JVM關(guān)閉時(shí)做些掃尾的工作,比如刪除臨時(shí)文件、停止日志服務(wù)以及內(nèi)存數(shù)據(jù)寫到磁盤等,為此JVM提供了關(guān)閉鉤子(shutdown hooks)來做這些事情。另外特別注意的是:如果JVM因異常關(guān)閉,那么子線程(Hook本質(zhì)上也是子線程)將不會(huì)停止。但在JVM被強(qiáng)行關(guān)閉時(shí),這些線程都會(huì)被強(qiáng)行結(jié)束。
另外在使用關(guān)閉鉤子還要注意以下幾點(diǎn):
##2、 ActiveMQ消費(fèi)者的鉤子
先講一下我的消費(fèi)者整體情況:
1、使用Spring集成ActiveMQ,用Spring容器進(jìn)行bean的管理
2、用DefaultMessageListenerContainer來監(jiān)聽處理隊(duì)列里的消息
直接貼代碼:
//消費(fèi)者是普通的java工程,通過這個(gè)類的main方法啟動(dòng),這里只貼出main函數(shù)里的代碼 public static void main( String[] args ) {log.info("start APP......");ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/applicationContext.xml");//testContainer是在配置文件中配置的監(jiān)聽器final DefaultMessageListenerContainer container = (DefaultMessageListenerContainer)context.getBean("testContainer");Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {public void run() {System.out.println("-------------------- 消費(fèi)者JVM即將關(guān)閉,執(zhí)行清場操作 --------------------");//關(guān)閉線程池,等待線程池積壓消息處理container.shutdown();System.out.println("-------------------- 消費(fèi)者關(guān)閉,線程池處理完畢 --------------------");//不要在鉤子里面執(zhí)行System.exit,調(diào)用halt()是可以正常關(guān)閉系統(tǒng)的,但是貌似沒這個(gè)必要//Runtime.getRuntime().halt(0);}})); }為了可以更直觀的看到這個(gè)等待任務(wù)線程處理完的一個(gè)過程,在任務(wù)線程里添加sleep代碼。
public class TestMessageListener implements SessionAwareMessageListener {public void onMessage(Message message, Session session) {if (message instanceof TextMessage) {TextMessage textMsg = (TextMessage) message;try {Thread.sleep(1000L);System.out.println(Thread.currentThread().getName() + ",接收到一個(gè)純文本消息,消息內(nèi)容是:" + textMsg.getText());} catch (JMSException e) {e.printStackTrace();}catch (InterruptedException e) {e.printStackTrace();}}} }運(yùn)行結(jié)果如下:
##3、 關(guān)閉消費(fèi)者
關(guān)閉消費(fèi)者的時(shí)候也很重要,不要使用kill -9的方式來殺進(jìn)程,這是無腦殺。
ref:
- 深入JVM關(guān)閉與關(guān)閉鉤子
- JAVA虛擬機(jī)關(guān)閉鉤子(Shutdown Hook)
- Java消息隊(duì)列任務(wù)的平滑關(guān)閉
- 使用后臺(tái)進(jìn)程和 Shutdown Hook 友好地關(guān)閉 Tomcat
總結(jié)
以上是生活随笔為你收集整理的ActiveMQ消费者平滑关闭的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 几种限流器(RateLimiter)原理
- 下一篇: 计算机的定点运算器原理,计算机组成原理定