ActiveMQ消费者平滑关闭

平滑关闭的思路就是让正在执行的任务线程正常执行完毕,然后再关闭JVM。在JVM关闭之前触发一个shutdown hook,jvm自带这个hook,在java启动时候就可以注册这样的hook。

##1、简述JVM关闭钩子(shutdown hook) 首先JVM的关闭方式可以分为三种:

  • 正常关闭:当最后一个非守护线程结束或者调用了System.exit或者通过其他特定平台的方法关闭(发送SIGINT,SIGTERM信号等)

  • 强制关闭:通过调用Runtime.halt方法或者是在操作系统中直接kill(发送SIGKILL信号)掉JVM进程

  • 异常关闭:运行中遇到RuntimeException异常等。

在某些情况下,我们需要在JVM关闭时做些扫尾的工作,比如删除临时文件、停止日志服务以及内存数据写到磁盘等,为此JVM提供了关闭钩子(shutdown hooks)来做这些事情。另外特别注意的是:如果JVM因异常关闭,那么子线程(Hook本质上也是子线程)将不会停止。但在JVM被强行关闭时,这些线程都会被强行结束。

另外在使用关闭钩子还要注意以下几点:

  1. 不能在钩子调用System.exit(),否则卡住JVM的关闭过程,但是可以调用Runtime.halt()。
  2. 不能再钩子中再进行钩子的添加和删掉操作,否则将会抛出IllegalStateException。
  3. 在System.exit()之后添加的钩子无效。
  4. 当JVM收到SIGTERM命令(比如操作系统在关闭时)后,如果钩子线程在一定时间没有完成,那么Hook线程可能在执行过程中被终止。
  5. Hook线程中同样会抛出异常,如果抛出异常又不处理,那么钩子的执行序列就会被停止。

##2、 ActiveMQ消费者的钩子

先讲一下我的消费者整体情况:

1、使用Spring集成ActiveMQ,用Spring容器进行bean的管理

2、用DefaultMessageListenerContainer来监听处理队列里的消息

直接贴代码:

//消费者是普通的java工程,通过这个类的main方法启动,这里只贴出main函数里的代码
public static void main( String[] args ) {
	log.info("start APP......");
	ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/applicationContext.xml");
	 //testContainer是在配置文件中配置的监听器
	final DefaultMessageListenerContainer container = (DefaultMessageListenerContainer)context.getBean("testContainer");

	Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
		public void run() {
			System.out.println("-------------------- 消费者JVM即将关闭,执行清场操作 --------------------");
			//关闭线程池,等待线程池积压消息处理
			container.shutdown();

			System.out.println("-------------------- 消费者关闭,线程池处理完毕 --------------------");
			//不要在钩子里面执行System.exit,调用halt()是可以正常关闭系统的,但是貌似没这个必要
			//Runtime.getRuntime().halt(0);
		}
	}));
}

为了可以更直观的看到这个等待任务线程处理完的一个过程,在任务线程里添加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() + ",接收到一个纯文本消息,消息内容是:" + textMsg.getText());
			} catch (JMSException e) {
				e.printStackTrace();
			}catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

运行结果如下:

输入图片说明

##3、 关闭消费者

关闭消费者的时候也很重要,不要使用kill -9的方式来杀进程,这是无脑杀。

ref:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Spring Boot中集成ActiveMQ消费者,你需要执行以下步骤: 1. 添加Maven依赖:在你的`pom.xml`文件中添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-activemq</artifactId> </dependency> ``` 2. 配置ActiveMQ连接:在`application.properties`文件中添加以下配置: ```properties spring.activemq.broker-url=tcp://localhost:61616 spring.activemq.user=admin spring.activemq.password=admin ``` 3. 创建消息监听器:创建一个类来实现`MessageListener`接口,用于处理接收到的消息。例如: ```java import javax.jms.Message; import javax.jms.MessageListener; public class MyMessageListener implements MessageListener { @Override public void onMessage(Message message) { // 处理接收到的消息 } } ``` 4. 注册消费者:在你的Spring Boot应用程序中,使用`@JmsListener`注解注册消息监听器。例如: ```java import org.springframework.jms.annotation.JmsListener; import org.springframework.stereotype.Component; @Component public class MyMessageConsumer { @JmsListener(destination = "myQueue") public void receiveMessage(String message) { System.out.println("Received message: " + message); } } ``` 在上面的例子中,我们使用`@JmsListener`注解来指定要监听的目标队列名字为`myQueue`,并在`receiveMessage()`方法中处理接收到的消息。 现在,当有消息到达`myQueue`队列时,`receiveMessage()`方法将被调用,并打印接收到的消息。 这就是在Spring Boot中集成ActiveMQ消费者的基本步骤。你可以根据自己的需求进行进一步的配置和处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值