1.声明
当前内容用于本人学习和复习RabbitMQ中的内容,当前内容主要为Topic的使用和测试
2.Topic Exchange的介绍
当前来源:RabbitMQ官方文档
-
主题根据消息路由键和用于将队列绑定到交换的模式之间的匹配
,将消息路由到一个或多个队列
。主题交换类型通常用于实现各种发布/订阅模式变体
。主题交换通常用于消息的多播路由。 -
主题交流有非常广泛的用例集。每当问题涉及多个使用者/应用程序,这些使用者/应用程序有选择地选择他们希望接收的消息类型时,应考虑使用主题交换。
-
示例使用:
3.1 分发与特定地理位置有关的数据,例如销售点
3.2 由多个工作人员完成的后台任务处理,每个工作人员都可以处理特定的任务集
3.3 股票价格更新(以及其他种类的财务数据的更新)
3.4 涉及分类或标记的新闻更新(例如,仅针对特定运动或团队)
3.5 云中各种服务的编排
3.6 分布式体系结构/特定于操作系统的软件构建或打包,其中每个构建器只能处理一个体系结构或OS
分析,将路由和队列进行结合?就是按照指定路由到特定队列?这个应该就是bind做的事情?感觉怎么和前面的Direct Exchange类似
3.模拟实现多名工作者一起做事
- 多个工人分别做:update、delete、select操作(每个人负责一个)
- 包工头负责查阅每个人做的事情(监督的作用)
1.创建job的topic
2.创建四个队列分别对应各个工人
3.将当前的topic的exchange和当前的queue进行绑定
这里注意当前的包工头使用的Routing Key为*就是匹配任何路由key,其他的只有符合key才能接收消息
4.编写四个消费者
public class Worker1MessageReceiver {
private final static String QUEUE_NAME = "worker1";
public static void main(String[] args) throws Exception {
RabbitMqUtils mqUtils = new RabbitMqUtils();
mqUtils.reciver(QUEUE_NAME, true, (consumerTag, delivery) -> {
System.out.println("【worker1】==>" + new String(delivery.getBody(), "utf-8"));
});
}
}
public class Worker2MessageReceiver {
private final static String QUEUE_NAME = "worker2";
public static void main(String[] args) throws Exception {
RabbitMqUtils mqUtils = new RabbitMqUtils();
mqUtils.reciver(QUEUE_NAME, true, (consumerTag, delivery) -> {
System.out.println("【worker2】==>" + new String(delivery.getBody(), "utf-8"));
});
}
}
public class Worker3MessageReceiver {
private final static String QUEUE_NAME = "worker3";
public static void main(String[] args) throws Exception {
RabbitMqUtils mqUtils = new RabbitMqUtils();
mqUtils.reciver(QUEUE_NAME, true, (consumerTag, delivery) -> {
System.out.println("【worker3】==>" + new String(delivery.getBody(), "utf-8"));
});
}
}
public class WorkHeaderMessageReceiver {
private final static String QUEUE_NAME = "workHeader";
public static void main(String[] args) throws Exception {
RabbitMqUtils mqUtils = new RabbitMqUtils();
mqUtils.reciver(QUEUE_NAME, true, (consumerTag, delivery) -> {
System.out.println("【workHeader】==>" + new String(delivery.getBody(), "utf-8"));
});
}
}
注意这里需要修改RabbitMqUtils,因为:当前的访问模式为route key方式
public boolean send(final String exchange, final String queue, final String msg) {
return send(exchange, queue, false, msg);
}
public boolean send(final String exchange/* , String queue */, final String routingKey, boolean durable,
BasicProperties props, final String msg) {
try (Connection connection = factory.newConnection(); Channel channel = connection.createChannel()) { //
//channel.queueDeclare(queue, durable, false, false, null);
channel.basicPublish(exchange, routingKey, props, msg.getBytes());
return true;
} catch (IOException | TimeoutException e) {
e.printStackTrace();
return false;
}
}
public boolean send(final String exchange, final String queue, boolean durable, final String msg) {
try (Connection connection = factory.newConnection(); Channel channel = connection.createChannel()) {
channel.queueDeclare(queue, durable, false, false, null);
channel.basicPublish(exchange, queue, null, msg.getBytes());
return true;
} catch (IOException | TimeoutException e) {
e.printStackTrace();
return false;
}
}
public void reciver(final String queue, DeliverCallback deliverCallback) throws Exception {
reciver(queue, false, deliverCallback);
}
public void reciver(final String queue, boolean durable, DeliverCallback deliverCallback) throws Exception {
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(queue, durable, false, false, null);
channel.basicConsume(queue, true, deliverCallback, consumerTag -> {
});
}
5.创建生产者
public class WorkerMessageSender {
String routeKey[] = { "select", "update", "delete" };
@Test
public void testSender() {
RabbitMqUtils mqUtils = new RabbitMqUtils();
for (int i = 0; i < 10; i++) {
int index = (i % routeKey.length);
String option = routeKey[index];
mqUtils.send("job", option, true, ("你好," + option + "!" + i));
}
}
}
6.启动四个消费者客户端
7.执行消息生产者查看结果
发现每个工作者都有自己的事情,并且包工头可以执行任何事情,测试成功
4.分析Topic Exchange
1.当前的topic非常类似前面的Direct Exchange(通过K=Q方式实现
),但是这里的Topic主要是通过routekey与当前的queue进行绑定
2.在使用routekey的时候可以使用正则表达式,例如这里的*
以上纯属个人见解,如有问题请联系本人!