1.声明
当前内容主要用于本人学习和复习之用,当前内容包括使用发布者实现消息分发到不同的队列中,以及测试BCC和CC的区别
当前内容来源:RabbitMQ官方文档
分析消息分发:一般我们发送消息的时候需要指定routeKey或者使用不同的exchange类型来实现消息的分发。但是并不是发布者指定的分发,而是routeKey或者exchange实现的
2.官方Sender-selected Distribution介绍
The routing logic in AMQP 0-9-1 does not offer a way for message publishers to select intended recipients unless they bind their queues to the target destination (an exchange).
这个AMQP 0-9-1 协议中路由并没提供一个让消息发布者选择发送消息给收件人的方法,除非将队列绑定到目的地(一个exchange)
分析:通过上面发现,发布者的消息分发不是AMQP 0-9-1协议中的一部分
The RabbitMQ broker treats the the “CC” and “BCC” message headers in a special way to overcome this limitation. This is the equivalent of entering multiple recipients in the “CC” or “BCC” field of an email.
这个RabbitMQ的broker以特殊的方式处理具有CC和BCC的消息的标头,以克服此限制。这相当于在电子邮件的“抄送”或“密件抄送”字段中输入多个收件人。
The values associated with the “CC” and “BCC” header keys will be added to the routing key if they are present. The message will be routed to all destinations matching the routing key supplied as a parameter to the basic.publish method, as well as the routes supplied in the “CC” and “BCC” headers. The type of “CC” and “BCC” values must be an array of longstr and these keys are case-sensitive. If the header does not contain “CC” or “BCC” keys then this extension has no effect.
The “BCC” key and value will be removed from the message prior to delivery, offering some confidentiality among consumers. This feature is a deviation from the AMQP 0-9-1 specification which forbids any message modification, including headers. This feature imposes a small performance penalty.
如果在路由key中添加了CC或者BCC的headers内容。如果使用basic.publish方法发送消息,那么这个消息将会被发送到匹配CC和BCC的路由
,以及本身消息的routeky的队列中。这个CC和BCC的扩展将无效
这个BCC这个key和其对应的值将会在被发送到消费者之前自动移除
。从而为消费者提供了一些机密性。此功能与AMQP 0-9-1规范不同,后者禁止任何消息修改,包括标头。此功能会降低性能。
(本人表示不明白)
分析发现:在发送消息的时候指定headers为BCC或者CC就可实现同时匹配routeKey和CC或者BCC的对应的routeKey了,实现了定向发送,BCC在发送的时候会自动删除BCC的key和value,并且是区分大小写的
3.测试使用CC和BCC发送消息的区别
1.创建exchange(city-exchange)
2.创建队列(wh-queue和bj-queue)
3.将city-exchabge与常见的队列分别进行绑定
- city-exchange 绑定到wh-queue的routeKey为wh
- city-exchange 绑定到bj-queue的routeKey为bj
4.创建消息生产者(用于生产具有CC或者BCC的消息)
public class SenderSelectedMain {
public static void main(String[] args) {
RabbitMqUtils mqUtils=new RabbitMqUtils();
BasicProperties.Builder builder=new BasicProperties.Builder();
Map<String, Object> headers=new HashMap<String, Object>(8);
headers.put("CC", new String[] {"bj"}); //CC和BCC的区别就是,CC转发的时候不会清除CC,headers的数据,而这个BCC会清除BCC这个key和对应的value
// headers.put("BCC", new String[] {"bj"});
headers.put("tag", "标记");
builder.headers(headers);
BasicProperties props = builder.build();
mqUtils.send("city-exchange", "wh", true, props, "发送rounteKey为wh的数据操作!");
}
}
5.创建两个消费者分别消费wh-queue和bj-queue的
wh-queue的消费者
/**
* @description 用于处理bj-queue队列中的消息
* @author hy
* @date 2020-05-19
*/
public class BJQueueConsumerTest {
public static void main(String[] args) throws IOException {
RabbitMqUtils mqUtils = new RabbitMqUtils();
Connection connection = mqUtils.getConnection();
final Channel chan = connection.createChannel();
try {
chan.basicConsume("bj-queue", true, "bj-queue-consumer-tag", new DefaultConsumer(chan) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties,
byte[] body) throws IOException {
System.out.println("消费者开始处理【bj-queue】消息===>" + new String(body, "utf-8")); // 获取传递标记
Map<String, Object> headers = properties.getHeaders();
System.out.println(headers);
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
}
bj-queue的消费者
/**
* @description 用于处理wh-queue队列中的消息
* @author hy
* @date 2020-05-19
*/
public class WHQueueConsumerTest {
public static void main(String[] args) throws IOException {
RabbitMqUtils mqUtils = new RabbitMqUtils();
Connection connection = mqUtils.getConnection();
final Channel chan = connection.createChannel();
try {
chan.basicConsume("wh-queue", true, "wh-queue-consumer-tag", new DefaultConsumer(chan) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties,
byte[] body) throws IOException {
System.out.println("消费者开始处理【wh-queue】消息===>" + new String(body, "utf-8")); // 获取传递标记
Map<String, Object> headers = properties.getHeaders();
System.out.println(headers);
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
}
6.启动两个消费者
7.测试启动消息生产者(将设置CC为bj)并查看结果
wh-queue的消费者的结果
bj-queue的消费者的结果
发现发送的CC还是存在的
8.测试启动消息生产者(将设置BCC为bj)并查看结果
发现当前的BCC标记消失了
4.总结
1.如果要实现发布者消息分发可以使用发送消息的时候添加headers参数为CC或者BCC来实先于routeky进行匹配的分发操作
,和routeKey一起都可以匹配
2.BCC在发送的时候会出现删除自身key的操作,具有安全性
以上纯属个人见解,如有问题请联本人!