DLQ用于Spring引导主题
我正在使用SpringBoot和ActiveMQ。我想发送和接收来自某个主题的消息。这很有效。我的代码如下所示:DLQ用于Spring引导主题,spring,spring-boot,jms,activemq,Spring,Spring Boot,Jms,Activemq,我正在使用SpringBoot和ActiveMQ。我想发送和接收来自某个主题的消息。这很有效。我的代码如下所示: @RunWith(SpringRunner.class) @SpringBootTest(classes = { JmsSpike.TestListener1.class, JmsSpike.TestListener2.class, JmsSpike.Config.class }) @TestPropertySource(propert
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {
JmsSpike.TestListener1.class,
JmsSpike.TestListener2.class,
JmsSpike.Config.class
})
@TestPropertySource(properties = {
"spring.activemq.broker-url: tcp://localhost:61616",
"spring.activemq.password: admin",
"spring.activemq.user: admin",
"spring.jms.pub-sub-domain: true", // queue vs. topic
})
@EnableJms
@EnableAutoConfiguration
public class JmsSpike {
@Autowired
private JmsTemplate jmsTemplate;
@Test
public void sendMessage() throws Exception {
sendMessageInThread();
Thread.sleep(10000);
}
private void sendMessageInThread() {
new Thread() {
public void run() {
jmsTemplate.convertAndSend("asx2ras", "I'm a test");
}
}.start();
}
@TestComponent
protected static class TestListener1 {
@JmsListener(destination = "asx2ras")
public void receiveMessage(String message) {
System.out.println("****************** 1 *******************");
System.out.println("Hey 1! I got a message: " + message);
System.out.println("****************** 1 *******************");
}
}
@TestComponent
protected static class TestListener2 {
@JmsListener(destination = "asx2ras")
public void receiveMessage(String message) {
throw new RuntimeException("Nope");
}
}
@Configuration
protected static class Config {
@Bean
public RedeliveryPolicy redeliveryPolicy() {
RedeliveryPolicy topicPolicy = new RedeliveryPolicy();
topicPolicy.setMaximumRedeliveries(1);
return topicPolicy;
}
@Bean
public ConnectionFactory connectionFactory(@Value("${spring.activemq.user}") final String username,
@Value("${spring.activemq.password}") final String password,
@Value("${spring.activemq.broker-url}") final String brokerUrl) {
ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory(username, password, brokerUrl);
cf.setRedeliveryPolicy(redeliveryPolicy());
return cf;
}
}
}
- 我可以发个信息
- 我与两位听众一起收到消息
- 一个监听器将始终工作,只需打印一些控制台消息
- 另一个侦听器总是抛出异常
编辑 这是我的
activemq.xml
(只是broker
标记):
根据,您可以覆盖客户端的代理配置:
代理将其首选的默认交付策略传输给
他的BrokerInfo命令包中的客户端连接。但客户可以
通过使用
ActiveMQConnection.getRedeliveryPolicy()方法:
因此,您配置重新交付策略的方式似乎还可以
我看到的唯一问题是当您创建一个新的RedeliveryPolicy
实例并只设置一个字段topicPolicy.setMaximumRedeliveries(1)代码>作为基本体的所有其他字段将被指定默认值。您可能应该在现有的重新交付策略实例上设置最大重新交付:
RedeliveryPolicy policy = cf.getRedeliveryPolicy();
policy.setMaximumRedeliveries(1);
编辑
另外,确保使用@JmsListener
时未使用客户端确认
。根据这一点,当使用CLIENT\u ACKNOWLEDGE
时,消息将不会重新传递。您可以在这里发布activemq.xml中的代理配置是什么吗。你在使用持久性吗?来自官方文档:“默认情况下,ActiveMQ不会将无法传递的非持久性消息放置在死信队列上。”@IulianRosca当然。我更新了我的问题。谢谢更新。此时,我将尝试在activemq.xml内将maximumRedeliveries设置为1。默认情况下,值设置为6()。在这种配置之后,如果消息最终出现在DLQ中,这意味着当客户端重写代理重新交付策略时,该机制存在问题。如果启用调试日志记录,您可以看到协商值(WireFormat)。@IulianRosca您是对的!当我从Java配置中删除“RedeliveryPolicy”bean时,消息最终出现在一个DLQ(“ActiveMQ.advision.MessageDLQd.Queue.asx2ras”)上。您知道如何在客户端配置DLQ而不是“activemq.xml”吗?
RedeliveryPolicy policy = connection.getRedeliveryPolicy();
policy.setInitialRedeliveryDelay(500); policy.setBackOffMultiplier(2);
policy.setUseExponentialBackOff(true);
policy.setMaximumRedeliveries(2);
RedeliveryPolicy policy = cf.getRedeliveryPolicy();
policy.setMaximumRedeliveries(1);