前言
一、死信交换机的简介
1. 简单概述
2. 优缺点
优点 | 说明 |
数据包安全性和可靠性 | 由于数据包不会直接从一个端口发送到另一个端口,攻击者无法窃取数据包并篡改其内容。这确保了数据包的安全性和可靠性。 |
数据包完整性验证 | 当数据包到达死信邮箱时,接收方可以确认接收到的数据包的完整性并进行相关操作。这有助于防止数据包在传输过程中被篡改或损坏。 |
防止拒绝服务攻击 | 死信交换机可以用于防止拒绝服务攻击。在这些攻击中,攻击者会向目标服务器发送大量垃圾流量,以使其崩溃或过载。使用死信交换机可以避免这种情况的发生,因为攻击者无法直接攻击目标服务器,而只能攻击死信交换机上的邮箱地址。 |
缺点 | 说明 |
对服务器和数据库性能要求高(要求高) | 由于死信交换机需要处理大量数据包和请求,因此对服务器和数据库的性能要求较高。如果服务器或数据库性能不足,可能会导致数据包处理延迟或丢失。 |
处理大量订单力不从心(效率低) | 对于需要处理大量订单的应用程序,死信交换机可能无法满足实时性的要求。由于数据包需要经过多个中间节点,可能会导致处理时间延迟。 |
配置和维护复杂(成本高) | 死信交换机需要正确配置和持续维护,以确保其正常工作并保持最佳性能。这可能需要较高的技术水平和资源投入。 |
3. 实现的流程
图解说明
模拟业务图解说明
视频讲解
阿里一面——说说RabbitMQ死信队列、延时队列
二、死信交换机实战
1. 创建队列
// 创建两个队列
@Bean
// 声明第一个队列 。
public Queue queueA(){
return new Queue("queueA");
}
@Bean
// 声明第二个队列
public Queue queueB(){
return new Queue("queueB");
}
2. 创建交换机
// 创建两个交换机 一个是死信交换机 一个是普通交换机
@Bean
public DirectExchange exchangeA(){
return new DirectExchange("Exchange-A");
}
@Bean
public DirectExchange exchangeB (){
return new DirectExchange("Exchange-B");
}
3. 绑定交换机和队列关系
@Bean
public Binding bindingA(){
return BindingBuilder
.bind(queueA())
.to(exchangeA())
.with("A");
}
@Bean
public Binding bindingB(){
return BindingBuilder
.bind(queueB())
.to(exchangeB())
.with("B");
}
4. 配置死信队列
生产者
@Bean
// 声明第一个队列 。
public Queue queueA(){
Map<String, Object> config = new HashMap<>();
//message在该队列queue的存活时间最大为10秒
config.put("x-message-ttl", 10000);
//x-dead-letter-exchange参数是设置该队列的死信交换器(DLX)
config.put("x-dead-letter-exchange", "ExchangeB");
//x-dead-letter-routing-key参数是给这个DLX指定路由键
config.put("x-dead-letter-routing-key", "BB");
return new Queue("queueA",true,false,false,config);
}
@RequestMapping("/send7")
public String send7() {
// 向交换机发送消息
amqpTemplate.convertAndSend("ExchangeA","AA","25965616516646465");
return "木易Love馨月";
}
消费者
ReceiverQB.java
package com.yx.consumer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
@SuppressWarnings("all")
@Slf4j
@RabbitListener(queues = "queueB") //接收的队列
public class ReceiverQB {
@RabbitHandler
public void process(String id) {
log.warn("QB接收到:" + id);
}
}
测试
三、设置手动确认消息
listener:
simple:
acknowledge-mode: manual
ReceiverQA.java
package com.yx.consumer;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
@SuppressWarnings("all")
@Slf4j
@RabbitListener(queues = "queueA") //接收的队列
public class ReceiverQA {
@RabbitHandler
public void process(String id, Channel channel,@Header(AmqpHeaders.DELIVERY_TAG) long tag) throws IOException {
log.warn("QA接收到:" + id);
channel.basicAck(tag, true);//确认消息成功消费
}
}