ActiveMQ笔记(7):如何清理无效的延时消息?

ActiveMQ的延时消息是一个让人又爱又恨的功能,具体使用可参考上篇ActiveMQ笔记(6):消息延时投递,在很多需要消息延时投递的业务场景十分有用,但是也有一个缺陷,在一些大访问量的场景,如果瞬间向MQ发送海量的延时消息,超过MQ的调度能力,就会造成很多消息到了该投递的时刻,却没有投递出去,形成积压,一直停留在ActiveMQ web控制台的Scheduled面板中。

下面的代码演示了,如何清理activemq中的延时消息(包括:全部清空及清空指定时间段的延时消息),这也是目前唯一可行的办法。

为了演示方便,先封装一个小工具类:

其中主要就用到了convertAndSend(Object message, MessagePostProcessor messagePostProcessor) 这个方法,其它代码可以无视。

先来模拟瞬间向MQ发送大量延时消息:

1
2
3
4
5
6
7
8
9
10
11
/**
 * 发送延时消息
 *
 * @param messageUtil
 */
private static void sendScheduleMessage(MessageUtil messageUtil) {
    for (int i = 0; i < 10000; i++) {
        Object obj = "test:" + i;
        messageUtil.convertAndSend(obj, new ScheduleMessagePostProcessor(1000 + i * 1000));
    }
}

这里向MQ发送了1w条延时消息,每条消息延时1秒*i,上面代码中的ScheduleMessagePostProcessor类可在上篇中找到。

运行完之后,MQ中应该堆积着了很多消息了:

下面的代码可以清空所有延时消息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
 * 删除所有延时消息
 *
 * @param connectionFactory
 * @throws JMSException
 */
private static void deleteAllScheduleMessage(final ConnectionFactory connectionFactory) throws JMSException {
    Connection conn = connectionFactory.createConnection();
    Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
    Destination management = session.createTopic(ScheduledMessage.AMQ_SCHEDULER_MANAGEMENT_DESTINATION);
    MessageProducer producer = session.createProducer(management);
    Message request = session.createMessage();
    request.setStringProperty(ScheduledMessage.AMQ_SCHEDULER_ACTION, ScheduledMessage.AMQ_SCHEDULER_ACTION_REMOVEALL);
    producer.send(request);
}

清空所有延时消息,有些用力过猛了,很多时候,我们只需要清理掉过期的延时消息(即:本来计划是8:00投递出去的消息,结果过了8点还没投递出去) 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
 * 删除过期的延时消息
 *
 * @param connectionFactory
 * @throws JMSException
 */
private static void deleteExpiredScheduleMessage(final ConnectionFactory connectionFactory) throws JMSException {
    long start = System.currentTimeMillis() - TimeUnit.HOURS.toMillis(12);//删除:当前时间前12小时范围的延时消息
    long end = System.currentTimeMillis();
    Connection conn = connectionFactory.createConnection();
    Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
    Destination management = session.createTopic(ScheduledMessage.AMQ_SCHEDULER_MANAGEMENT_DESTINATION);
    MessageProducer producer = session.createProducer(management);
    Message request = session.createMessage();
    request.setStringProperty(ScheduledMessage.AMQ_SCHEDULER_ACTION, ScheduledMessage.AMQ_SCHEDULER_ACTION_REMOVEALL);
    request.setStringProperty(ScheduledMessage.AMQ_SCHEDULER_ACTION_START_TIME, Long.toString(start));
    request.setStringProperty(ScheduledMessage.AMQ_SCHEDULER_ACTION_END_TIME, Long.toString(end));
    producer.send(request);
}

与上一段代码基本相似,只是多指定了删除消息的起止时间段。  

最后贴一段spring的配置文件及main函数入口

复制代码
 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
 5 
 6     <bean id="jmsFactory" class="org.apache.activemq.pool.PooledConnectionFactory" destroy-method="stop">
 7         <property name="connectionFactory">
 8             <bean class="org.apache.activemq.ActiveMQConnectionFactory">
 9                 <property name="brokerURL"
10                           value="failover:(tcp://localhost:61616,tcp://localhost:61626)?randomize=false&amp;backup=true"/>
11                 <property name="maxThreadPoolSize" value="100"/>
12             </bean>
13         </property>
14     </bean>
15 
16     <bean id="messageUtil" class="cn.mwee.utils.mq.MessageUtil">
17         <constructor-arg index="0" ref="jmsFactory"/>
18         <constructor-arg index="1" value="10000"/>
19         <constructor-arg index="2">
20             <list>
21                 <value>dest1</value>
22                 <value>dest2</value>
23             </list>
24         </constructor-arg>
25         <property name="autoBackup" value="true"/>
26     </bean>
27 
28 </beans>
View Code
复制代码

main函数:

1
2
3
4
5
6
7
8
    public static void main(String[] args) throws InterruptedException, JMSException {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-sender.xml");
        ConnectionFactory connectionFactory = context.getBean(ConnectionFactory.class, "jmsFactory");
        MessageUtil messageUtil = context.getBean(MessageUtil.class);
//        sendScheduleMessage(messageUtil);
//        deleteAllScheduleMessage(connectionFactory);
        deleteExpiredScheduleMessage(connectionFactory);
    }

参考文章:

Enhanced JMS Scheduler in ActiveMQ

posted @   菩提树下的杨过  阅读(5165)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
历史上的今天:
2013-09-04 航空货运:运价类别Rate Class
2010-09-04 FluorineFx:视频录制及回放(Flash/AS3环境)
2008-09-04 WCF Testing Tool(转)
2008-09-04 [转自雨痕]RESTful WCF
2008-09-04 [转]用HTTP/Post与WCF互操作
2008-09-04 [转载]利用SQL SERVER2005发送邮件
2008-09-04 [转贴]三种Ext提交数据的方法
点击右上角即可分享
微信分享提示