消息的整个流转过程:
- producer发送一条消息到exchange
- 通过匹配routingKey将消息路由到指定队列
(发送消息时设置的routingKey和exchange和队列绑定时候的bindingKey去路由)- consumer端监听队列,消费消息
Exchange:交换机负责接收消息,并根据路由key将消息路由到指定队列
交换机的属性:
- name-交换机名称
- type-交换机类型direct(直连)、topic(主题)、fanout(广播)、headers
- durability-是否需要持久化,持久化后MQ server重启后交换机还在
- auto delete-当最后一个和该交换机绑定的队列被删除后,交换机自动删除
- arguments: 扩展参数
direct:消息进入其绑定key与消息的路由key完全匹配的队列,必须完全匹配
代码演示:
- 核心依赖包
<!--尽量安装的MQ和使用的rabbitmq客户端依赖版本统一,防止意外的幺蛾子-->
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>3.6.5</version>
</dependency>
- 生产者
- 消息routingKey分别为:info、debug和error
package com.vivo.demo1.direct;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* @author:luzaichun
* @Date:2020/12/13
* @Time:21:43
**/
public class Producer {
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("192.168.3.6");
factory.setPort(5672);
factory.setVirtualHost("/");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
for (int i=0;i<5;i++){
channel.basicPublish("direct_exchange","info",null,(i+"这是一条info消息").getBytes());
channel.basicPublish("direct_exchange","debug",null,(i+"这是一条warn消息").getBytes());
channel.basicPublish("direct_exchange","error",null,(i+"这是一条error消息").getBytes());
}
}
}
3. 消费者1
- 队列是:direct_other_log_queue
- 路由key:info 、warn 、debug
package com.vivo.demo1.direct;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.QueueingConsumer;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* @author:luzaichun
* @Date:2020/12/13
* @Time:21:18
**/
public class Consumer1 {
public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
ConnectionFactory factory = new ConnectionFactory();
factory.setPort(5672);
factory.setHost("192.168.3.6");
factory.setVirtualHost("/");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
String exchange = "direct_exchange";
channel.exchangeDeclare(exchange,"direct",false,false,null);
//info warn debug日志队列
channel.queueDeclare("direct_other_log_queue",false,false,false,null);
channel.queueBind("direct_other_log_queue",exchange,"info");
channel.queueBind("direct_other_log_queue",exchange,"debug");
channel.queueBind("direct_other_log_queue",exchange,"warn");
QueueingConsumer queueingConsumer = new QueueingConsumer(channel);
channel.basicConsume("direct_other_log_queue",true,queueingConsumer);
while (true){
QueueingConsumer.Delivery delivery = queueingConsumer.nextDelivery();
System.out.println("other的消息:"+new String(delivery.getBody()));
}
}
}
4. 消费者2
- 队列是:direct_error_log_queue
- 路由key:error
package com.vivo.demo1.direct;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.QueueingConsumer;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* @author:luzaichun
* @Date:2020/12/13
* @Time:21:18
**/
public class Consumer2 {
public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
ConnectionFactory factory = new ConnectionFactory();
factory.setPort(5672);
factory.setHost("192.168.3.6");
factory.setVirtualHost("/");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
String exchange = "direct_exchange";
channel.exchangeDeclare(exchange,"direct",false,false,null);
//error日志队列
channel.queueDeclare("direct_error_log_queue",false,false,false,null);
channel.queueBind("direct_error_log_queue",exchange,"error");
QueueingConsumer queueingConsumer = new QueueingConsumer(channel);
channel.basicConsume("direct_error_log_queue",true,queueingConsumer);
while (true){
QueueingConsumer.Delivery delivery = queueingConsumer.nextDelivery();
System.out.println("error的消息:"+new String(delivery.getBody()));
}
}
}
5. 测试
启动2个消费者后可以在管控台查看到exchange的绑定关系。
direct_exchange和2个队列绑定(direct_error_log_queue、direct_other_log_queue)
- error的路由key路由到direct_error_log_queue队列
- debug、info、warn的路由key路由到direct_other_log_queue队列
当我们在生产端发送消息的时候,routingKey字段需要完全匹配于交换机和队列的绑定key
6. 查看结果
可以看到routingKey为info和debug的消息,都路由到了consumer1也就是direct_other_log_queue;routingKey为error的消息都路由到了consuemr2也就是direct_error_log_queue队列,符合预期。