如何让HornetQ停止尝试重新投递消息?
当然有办法搞定这个需求!HornetQ早就为这种场景提供了专门的API,能让你主动告诉队列「这消息不用重试了,直接丢去死信队列」,完全不用纠结要不要吞掉消息。下面给你具体讲两种实现方式:
方法一:用标准JMS的
Session.reject()方法 HornetQ实现了标准JMS的Session.reject()接口,调用这个方法就相当于明确告诉队列:我拒绝处理这条消息,而且别再重新投递了,直接转去死信队列。
给你写个示例代码参考:
try { Message message = consumer.receive(); // 先判断这条消息是不是属于不值得重试的情况 if (isUnrecoverableFailure()) { // 直接拒绝,消息会被送入DLQ session.reject(message); return; } // 正常处理消息的逻辑 processMessage(message); // 处理成功,提交会话 session.commit(); } catch (JMSException e) { // 如果是临时网络故障这类需要重试的问题,回滚会话触发重投 session.rollback(); }
这里要注意:调用reject()之后,不用再调用commit()或者rollback(),因为reject()已经直接处理了消息的状态。
方法二:用HornetQ原生API的重载方法
如果你项目里直接用了HornetQ的原生API(而非标准JMS),还可以用HornetQSession的重载版reject()方法,更直观地控制是否重投:
// 把标准Session转成HornetQ的原生Session HornetQSession hornetQSession = (HornetQSession) session; // 第二个参数设为false,就是告诉队列不用重投,直接去DLQ hornetQSession.reject(message, false);
几个关键注意点
- 先确保你的队列已经配置了死信队列:要在HornetQ的配置文件(比如
hornetq-jms.xml)里给目标队列指定对应的DLQ,不然拒绝的消息可能没地方去。举个配置例子:
<queue name="businessQueue"> <entry name="/queue/businessQueue"/> <!-- 指定死信队列地址 --> <dead-letter-address>/queue/DLQ</dead-letter-address> </queue> <!-- 定义死信队列本身 --> <queue name="DLQ"> <entry name="/queue/DLQ"/> </queue>
- 清晰区分两种失败场景:临时网络故障这类可重试的情况,你还是可以通过抛出异常或者回滚会话来触发重投;只有遇到明确不值得重试的问题时,再调用
reject()把消息送进DLQ,这样逻辑就清晰多了。
内容的提问来源于stack exchange,提问作者BillyBadBoy
相关产品推荐
相关产品推荐

