ActiveMQ 重发与确认实践
原文链接:https://www.cnblogs.com/sjshare/p/8962340.html
一、配置spring-activemq.xml
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 <!-- 第三方MQ工厂: ConnectionFactory --> 7 <bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"> 8 <!-- ActiveMQ Address --> 9 <property name="brokerURL" value="${activemq.brokerURL}"/> 10 <property name="userName" value="${activemq.userName}"/> 11 <property name="password" value="${activemq.password}"/> 12 <!-- 是否异步发送 --> 13 <property name="useAsyncSend" value="true"/> 14 <!-- 引用重发机制 --> 15 <property name="redeliveryPolicy" ref="activeMQRedeliveryPolicy" /> 16 <!-- 消息传输监听器 处理网络及服务器异常 --> 17 <!--<property name="transportListener">--> 18 <!--<bean class="com.schooling.activemq.ActiveMQTransportListener"/>--> 19 <!--</property>--> 20 </bean> 21 22 <!-- 23 ActiveMQ为我们提供了一个PooledConnectionFactory,通过往里面注入一个ActiveMQConnectionFactory 24 可以用来将Connection、Session和MessageProducer池化,这样可以大大的减少我们的资源消耗,要依赖于 activemq-pool包 25 --> 26 <bean id="pooledConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory"> 27 <property name="connectionFactory" ref="targetConnectionFactory"/> 28 <property name="maxConnections" value="${activemq.pool.maxConnections}"/> 29 </bean> 30 31 <!-- 定义ReDelivery(重发机制)机制 ,重发时间间隔是100毫秒,最大重发次数是3次 --> 32 <bean id="activeMQRedeliveryPolicy" class="org.apache.activemq.RedeliveryPolicy"> 33 <!--是否在每次尝试重新发送失败后,增长这个等待时间 --> 34 <property name="useExponentialBackOff" value="true"/> 35 <!--重发次数,默认为6次 这里设置为1次 --> 36 <property name="maximumRedeliveries" value="2"/> 37 <!--重发时间间隔,默认为1秒 --> 38 <property name="initialRedeliveryDelay" value="1000"/> 39 <!--第一次失败后重新发送之前等待500毫秒,第二次失败再等待500 * 2毫秒,这里的2就是value --> 40 <property name="backOffMultiplier" value="2"/> 41 <!--最大传送延迟,只在useExponentialBackOff为true时有效(V5.5),假设首次重连间隔为10ms,倍数为2,那么第二次重连时间间隔为 20ms, 42 第三次重连时间间隔为40ms,当重连时间间隔大的最大重连时间间隔时,以后每次重连时间间隔都为最大重连时间间隔。 --> 43 <property name="maximumRedeliveryDelay" value="1000"/> 44 </bean> 45 46 <!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory --> 47 <bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory"> 48 <!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory --> 49 <property name="targetConnectionFactory" ref="pooledConnectionFactory"/> 50 </bean> 51 52 <!--这个是目的地--> 53 <bean id="msgQueue" class="org.apache.activemq.command.ActiveMQQueue"> 54 <constructor-arg value="${activemq.queueName}"/> 55 </bean> 56 57 <!-- Spring提供的JMS工具类,它可以进行消息发送、接收等 --> 58 <!-- 队列模板 --> 59 <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"> 60 <!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 --> 61 <property name="connectionFactory" ref="connectionFactory"/> 62 <property name="defaultDestinationName" value="${activemq.queueName}"/> 63 </bean> 64 65 <!-- 配置自定义监听:MessageListener --> 66 <bean id="msgQueueMessageListener" class="com.schooling.activemq.consumer.MsgQueueMessageListener"/> 67 68 <!-- 将连接工厂、目标对了、自定义监听注入jms模板 --> 69 <bean id="sessionAwareListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer"> 70 <property name="connectionFactory" ref="connectionFactory"/> 71 <property name="destination" ref="msgQueue"/> 72 <property name="messageListener" ref="msgQueueMessageListener"/> 73 <!--应答模式是 INDIVIDUAL_ACKNOWLEDGE--> 74 <property name="sessionAcknowledgeMode" value="4"/> 75 </bean> 76 77 </beans>
二、生产者
1 @Service("activeMQProducer") 2 public class ActiveMQProducer { 3 4 private JmsTemplate jmsTemplate; 5 6 public JmsTemplate getJmsTemplate() { 7 return jmsTemplate; 8 } 9 10 @Autowired 11 public void setJmsTemplate(JmsTemplate jmsTemplate) { 12 this.jmsTemplate = jmsTemplate; 13 } 14 15 public void sendMessage(final String info) { 16 jmsTemplate.send(new MessageCreator() { 17 public Message createMessage(Session session) throws JMSException { 18 return session.createTextMessage(info); 19 } 20 }); 21 } 22 }
三、消费者(监听模式)
1 public class MsgQueueMessageListener implements SessionAwareMessageListener<Message> { 2 3 @Override 4 public void onMessage(Message message, Session session) throws JMSException { 5 6 if (message instanceof TextMessage) { 7 8 String msg = ((TextMessage) message).getText(); 9 10 System.out.println("============================================================"); 11 System.out.println("消费者收到的消息:" + msg); 12 System.out.println("============================================================"); 13 14 try { 15 if ("我是队列消息002".equals(msg)) { 16 throw new RuntimeException("故意抛出的异常"); 17 } 18 // 只要被确认后 就会出队,接受失败没有确认成功,会在原队列里面 19 message.acknowledge(); 20 } catch (Exception e) { 21 // 此不可省略 重发信息使用 22 session.recover(); 23 } 24 } 25 } 26 }
四、测试方法
1 @Test 2 public void send() { 3 for (int i = 1; i < 5; i++) { 4 this.activeMQProducer.sendMessage("我是队列消息00" + i); 5 } 6 while (true) {} 7 }
五、测试结果
六、测试小结
“我是队列消息002”由于异常,未接收成功。在重发2次都失败的情况下被发送到“死信队列”。其他4条信息都接收成功。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)