在使用RabbitMQ的时候,作为消息发送方希望杜绝任何消息丢失或者投递失败场景。RabbitMQ为我们提供了两种方式用来控制消息的投递可靠性模式。
rabbitmg整个消息投递的路径为:
producer—>rabbitmq broker—>exchange—>queue—>consumer
我们将利用这两个callback控制消息的可靠性投递
spring:
rabbitmq:
port: 5672
host: 192.168.253.129
virtual-host: /domo
username: lmx
password: 123456
publisher-confirm-type: correlated # 如果不加这个,confirm回调方法无法执行
@Test
void contextLoads() {
rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
@Override
public void confirm(CorrelationData correlationData, boolean b, String s) {
System.out.println("回调方法被执行======");
if (b){
System.out.println("接受信息成功"+s);
}else {
System.out.println("失败原因是"+s);
}
}
});
String s="waring级别的数据";
rabbitTemplate.convertAndSend(RabbitMQConfigure.TocpicExchangeName,"serve.order.warning",s);
// rabbitTemplate.convertAndSend("12","serve.order.warning",s);
spring:
rabbitmq:
port: 5672
host: 192.168.253.129
virtual-host: /domo
username: lmx
password: 123456
publisher-confirm-type: correlated # 如果不加这个,confirm回调方法无法执行
publisher-returns: true
@Test
void contextLoadsRunturnCallback() {
rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {
@Override
public void returnedMessage(ReturnedMessage returnedMessage) {
System.out.println("returncallback方法被执行");
System.out.println("信息是"+returnedMessage.getMessage());
// System.out.println(new String(returnedMessage.getMessage().getBody()));
System.out.println("交换机名称:"+returnedMessage.getExchange());
System.out.println("路由key民称:"+returnedMessage.getRoutingKey());
System.out.println("编码:"+returnedMessage.getReplyCode());
System.out.println("编码信息:"+returnedMessage.getReplyText());
}
});
String s="error级别的数据";
rabbitTemplate.convertAndSend(RabbitMQConfigure.TocpicExchangeName,"serve.order.error",s);
// rabbitTemplate.convertAndSend("12","serve.order.warning",s);
}
spring:
rabbitmq:
port: 5672
host: 192.168.253.129
virtual-host: /domo
username: lmx
password: 123456
listener:
direct: # 就是pub、sub模式
acknowledge-mode: manual
prefetch: 1000
simple: # 简单模式与workquene模式
acknowledge-mode: manual
prefetch: 1000
@RabbitListener(queues = "quneq1")
public void Lister(Message message, Channel channel) throws IOException {
long deliveryTag = message.getMessageProperties().getDeliveryTag();
try {
System.out.println("error级别的消息是" + new String(message.getBody()));
// System.out.println("交换机" + message.getMessageProperties().getReceivedExchange());
// System.out.println("路由信息" + message.getMessageProperties().getReceivedRoutingKey());
System.out.println("============================");
System.out.println("处理业务逻辑");
// int a=1/0;
channel.basicAck(deliveryTag,true);
}catch (Exception e){
e.printStackTrace();
channel.basicNack(deliveryTag,true,true);
}
spring:
rabbitmq:
port: 5672
host: 192.168.253.129
virtual-host: /domo
username: lmx
password: 123456
listener:
direct: # 就是pub、sub模式
acknowledge-mode: manual
prefetch: 1 # 每次拉去一条消息
simple: # 简单模式与workquene模式
acknowledge-mode: manual
prefetch: 1 # 每次拉去一条消息
@RabbitListener(queues = "quneq2")
public void Lister2(Message message, Channel channel) throws IOException, InterruptedException {
System.out.println("info或waring级别的消息是"+new String(message.getBody()));
// System.out.println("交换机"+message.getMessageProperties().getReceivedExchange());
// System.out.println("路由信息"+message.getMessageProperties().getReceivedRoutingKey());
// System.out.println("============================");
Thread.sleep(1000);
System.out.println("处理业务逻辑");
// 签收消息
channel.basicAck(message.getMessageProperties().getDeliveryTag(),true);
}
TTL全称Time To Live(存活时间/过期时间)。
当消息到达存活时间后,还没有被消费,会被自动清除。
向队列添加过期时间
@Bean
public Queue ttlqueue(){
// 设置队列过期时间
return QueueBuilder.durable(ttlqueue).ttl(5000).build();
}
@Test
public void TestTTl() {
MessagePostProcessor messagePostProcessor = new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置Expiration属性
message.getMessageProperties().setExpiration("5000");
return message;
}
};
rabbitTemplate.convertAndSend(RabbitMQConfigure.TocpicExchangeName, "123.ttl", "单独过期消息发送".getBytes(StandardCharsets.UTF_8),
messagePostProcessor);
}
// 设置死信交换机
@Bean
public Exchange dlxexchange() {
return ExchangeBuilder.topicExchange(dlxexchange).durable(true).build();
}
@Bean
public Queue dlxqueue() {
return QueueBuilder.durable(dlxqueue).build();
}
@Bean
public Binding dlxbinding() {
return BindingBuilder.bind(dlxqueue()).to(dlxexchange()).with("dlx.#").and(null);
}
@Bean
public Queue dlxtestqueue() {
return QueueBuilder.durable(dlxtestqueue).deadLetterExchange(dlxexchange).deadLetterRoutingKey("dlx.123").maxLength(10).build();
}
@Bean
public Binding Exchangedlxtest(){
return BindingBuilder.bind(dlxtestqueue()).to(TocpicExchange()).with("testdlx.#").and(null);
}
// 延迟队列,设置队列的过期时间是10秒
@Bean
public Queue yanchiqueue(){
return QueueBuilder.durable("yanchiqueue").deadLetterExchange(dlxexchange).ttl(10000).deadLetterRoutingKey("dlx.yanchi").build();
}
@Bean
public Binding yanchibing(){
return BindingBuilder.bind(yanchiqueue()).to(TocpicExchange()).with("yanchi.#").and(null);
}
@Test
public void errorTestYanchi2() throws InterruptedException {
LocalDateTime now = LocalDateTime.now();
rabbitTemplate.convertAndSend(RabbitMQConfigure.TocpicExchangeName, "yanchi.123", "商品订单2" + now);
for (int i=0;i<10;i++){
Thread.sleep(1000);
System.out.println(i+"秒----");
}
}