1.什么是死信
“死信”是RabbitMQ中的一种消息机制,当你在消费消息时,如果队列里的消息出现以下情况:
- 消息被否定确认,使用 channel.basicNack 或 channel.basicReject ,并且此时requeue 属性被设置为false。
- 消息在队列的存活时间超过设置的TTL时间。
- 消息队列的消息数量已经超过最大队列长度。
那么该消息将成为“死信”。
“死信”消息会被RabbitMQ进行特殊处理,如果配置了死信队列信息,那么该消息将会被丢进死信队列中,如果没有配置,则该消息将会被丢弃。
2. 配置
spring:
rabbitmq:
host: localhost
username: admin
password: admin
listener:
simple:
default-requeue-rejected: false
acknowledge-mode: manual
3.配置队列
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class RabbitMqConfiguration {
public static final String DEAD_LETTER_EXCHANGE = "dead.letter.exchange";
public static final String DEAD_LETTER_QUEUE = "dead.letter.queue";
public static final String DEAD_LETTER_ROUTING_KEY = "dead.letter.routingKey";
public static final String EXCHANGE = "exchange";
public static final String QUEUE = "queue";
public static final String ROUTING_KEY = "routingKey";
/**
* 配置死信交换器
*/
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange(DEAD_LETTER_EXCHANGE);
}
/**
* 配置死信队列
*/
@Bean
public Queue deadLetterQueue() {
return new Queue(DEAD_LETTER_QUEUE);
}
/**
* 死信队列绑定
* @return
*/
@Bean
public Binding deadLetterBinding() {
return BindingBuilder.bind(deadLetterQueue())
.to(deadLetterExchange())
.with(DEAD_LETTER_ROUTING_KEY);
}
/**
* 业务交换器
* @return
*/
@Bean
public DirectExchange businessExchange() {
return new DirectExchange(EXCHANGE);
}
/**
* 业务队列
* @return
*/
@Bean
public Queue businessQueue() {
Map<String, Object> args = new HashMap<>(2);
// 配置当前队列绑定的死信交换器
args.put("x-dead-letter-exchange", DEAD_LETTER_EXCHANGE);
// 配置当前队列的死信队列路由key,如果不设置默认为当前队列的路由key
args.put("x-dead-letter-routing-key", DEAD_LETTER_ROUTING_KEY);
return QueueBuilder.durable(QUEUE).withArguments(args).build();
}
/**
* 业务队列绑定
* @return
*/
@Bean
public Binding queueBinding() {
return BindingBuilder.bind(businessQueue())
.to(businessExchange())
.with(ROUTING_KEY);
}
}
4.消息接收者
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
public class RabbitmqReceiver {
@RabbitListener(queues = RabbitMqConfiguration.DEAD_LETTER_QUEUE)
public void deadLetterMsgReceive(Message message, Channel channel) throws IOException {
System.out.println("收到死信消息:" + new String(message.getBody()));
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
}
@RabbitListener(queues = RabbitMqConfiguration.QUEUE)
public void buinessMsgReceive(Message message, Channel channel) throws IOException {
String msg = new String(message.getBody());
System.out.println("收到消息:" + msg);
if (msg.startsWith("false")) {
System.out.println("消费失败:" + msg);
channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
} else {
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
}
}
}
5. 消息发送者
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class RabbitmqSender {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendBuinessMsg(String msg) {
rabbitTemplate.convertAndSend(RabbitMqConfiguration.EXCHANGE,
RabbitMqConfiguration.ROUTING_KEY, msg);
}
}