我很难在Spring AMQP / Rabbit MQ中找到预定/延迟消息的方法,并在这里找到了解决方案。但我仍然有一个问题 关于Spring AMQP / Rabbit MQ,它无法接收任何消息。
我的来源如下:
@Configuration
public class AmqpConfig {
@Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
connectionFactory.setAddresses("172.16.101.14:5672");
connectionFactory.setUsername("admin");
connectionFactory.setPassword("admin");
connectionFactory.setPublisherConfirms(true);
return connectionFactory;
}
@Bean
@Scope("prototype")
public RabbitTemplate rabbitTemplate() {
RabbitTemplate template = new RabbitTemplate(connectionFactory());
return template;
}
@Bean
CustomExchange delayExchange() {
Map<String, Object> args = new HashMap<String, Object>();
args.put("x-delayed-type", "direct");
return new CustomExchange("my-exchange", "x-delayed-message", true, false, args);
}
@Bean
public Queue queue() {
return new Queue("spring-boot-queue", true);
}
@Bean
Binding binding(Queue queue, Exchange delayExchange) {
return BindingBuilder.bind(queue).to(delayExchange).with("spring-boot-queue").noargs();
}
@Bean
public SimpleMessageListenerContainer messageContainer() {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory());
container.setQueues(queue());
container.setExposeListenerChannel(true);
container.setMaxConcurrentConsumers(1);
container.setConcurrentConsumers(1);
container.setAcknowledgeMode(AcknowledgeMode.MANUAL);
container.setMessageListener(new ChannelAwareMessageListener() {
public void onMessage(Message message, Channel channel) throws Exception {
byte[] body = message.getBody();
System.err.println("receive msg : " + new String(body));
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false); //确认消息成功消费
}
});
return container;
}
}
@Component
public class Send implements RabbitTemplate.ConfirmCallback{
private RabbitTemplate rabbitTemplate;
@Autowired
public Send(RabbitTemplate rabbitTemplate) {
this.rabbitTemplate = rabbitTemplate;
this.rabbitTemplate.setConfirmCallback(this);
rabbitTemplate.setMandatory(true);
}
public void sendMsg(String content) {
CorrelationData correlationId = new CorrelationData(UUID.randomUUID().toString());
rabbitTemplate.convertAndSend("my-exchange", "", content, new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
message.getMessageProperties().setHeader("x-delay", 6000);
return message;
}
},correlationId);
System.err.println("delay message send ................");
}
/**
* 回调
*/
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
System.err.println(" callback id :" + correlationData);
if (ack) {
System.err.println("ok");
} else {
System.err.println("fail:" + cause);
}
}
}
是否有人可以提供帮助。
谢谢大家。
答案 0 :(得分:2)
延迟消息传递与Spring amqp无关,它是一个驻留在您的代码中的库,因此库无法保存任何消息。您可以尝试两种方法:
旧方法: 在每个消息/队列(策略)中设置TTL(生存时间)标头,然后引入DLQ来处理它。一旦ttl过期,您的消息将从DLQ移动到主队列,以便您的侦听器可以处理它。
最新方法: 最近,RabbitMQ推出了 RabbitMQ延迟消息插件 ,使用它可以实现相同的功能,并且自RabbitMQ-3.5.8起支持此插件支持。
您可以使用x-delayed-message类型声明交换,然后使用自定义标头x-delay发布消息,以毫秒为单位表示消息的延迟时间。消息将在x延迟毫秒后传送到相应的队列
<强>详细信息:强> 要使用延迟消息传递功能,请使用x-delayed-message类型声明交换:
Map<String, Object> args = new HashMap<String, Object>();
args.put("x-delayed-type", "direct");
channel.exchangeDeclare("my-exchange", "x-delayed-message", true, false, args);
请注意,我们在路由部分下传递了一个名为x-delayed-type的额外标头。
我们宣布交换后,我们可以发布消息,提供一个标题告诉插件延迟消息的时间:
byte[] messageBodyBytes = "delayed payload".getBytes("UTF-8");
Map<String, Object> headers = new HashMap<String, Object>();
headers.put("x-delay", 5000);
AMQP.BasicProperties.Builder props = new AMQP.BasicProperties.Builder().headers(headers);
channel.basicPublish("my-exchange", "", props.build(), messageBodyBytes);
byte[] messageBodyBytes2 = "more delayed payload".getBytes("UTF-8");
Map<String, Object> headers2 = new HashMap<String, Object>();
headers2.put("x-delay", 1000);
AMQP.BasicProperties.Builder props2 = new AMQP.BasicProperties.Builder().headers(headers2);
channel.basicPublish("my-exchange", "", props2.build(), messageBodyBytes2);
在上面的例子中,我们发布了两条消息,用x-delay标头指定延迟时间。对于这个例子,插件将首先向我们的队列传递消息,其中包含正文&#34;更多延迟的有效负载&#34;然后是身体的那个&#34;延迟有效载荷&#34;。
如果x-delay标头不存在,那么插件将继续无延迟地路由消息。
更多信息:git