RabbitMQ——RabbitMQ的Direct消息模型
在 Fanout 消息模型中,使用Fanout交换机,一条消息发出去后,会被交换机发送给所有订阅的队列,再被队列对应的消费者消费。但是,再某些情况下,我们希望不同的消息能被不同的队列消费。这时就要用到Direct消息模型的Direct交换机。
Direct消息模型结构图
P:生产者,向Exchange发送消息,发送消息时,会指定一个routing key。
X:Exchange(交换机),接收生产者的消息,然后把消息递交给与routing key完全匹配的队列.
C1:消费者,其所在队列指定了需要routing key为error的消息
C2:消费者,其所在队列指定了需要routing key为info、error、warning的消息
队列与交换机之间通过指定一个 RoutingKey(路由key)进行绑定
消息生产者在向 Exchange交换机发送消息时,也必须给消息指定一个RoutingKey(路由key)
Exchange交换机不再把消息发送给每一个绑定的队列,而是根据消息的RoutingKey进行判断,只有队列的RoutingKey和消息的RoutingKey一致,才能接收到消息。
1、Direct消息模型之发布者发布消息
消息生产者的开发
消息发送者发送消息时指定的routingKey为"info"
public class Provider {
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection = ConnectUtils.getConnection("121.199.53.150", 5672, "/ems", "ems", "ems");
Channel channel = connection.createChannel();
//将通道绑定到交换机上,参数一:交换机名称,如果没有,会自动创建,参数二:交换机类型 direct直连交换机
channel.exchangeDeclare("logs_direct","direct");
//定义RoutingKey
String routingKey = "info";
//发送消息
channel.basicPublish("logs_direct",routingKey, null,("direct rabbitmq,routingKey: "+routingKey).getBytes());
channel.close();
connection.close();
}
}
2、Direct消息模型之消费者消费消息
消息消费者的开发
ConsumerA:ConsumerA队列的指定的routingKey为 “info”,“error”,“warning”
public class ConsumerA {
public static void main(String[] args) throws IOException {
Connection connection = ConnectUtils.getConnection("121.199.53.150", 5672, "/ems", "ems", "ems");
Channel channel = connection.createChannel();
//声明与通道连接的交换机
channel.exchangeDeclare("logs_direct","direct");
//创建临时队列
String queue = channel.queueDeclare().getQueue();
//通道绑定队列和交换机
channel.queueBind(queue,"logs_direct","info");
channel.queueBind(queue,"logs_direct","error");
channel.queueBind(queue,"logs_direct","warning");
//消费消息
channel.basicConsume(queue,true,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("consumerA direct rabbitmq:" + new String(body)+ "routingKey:" + envelope.getRoutingKey());
}
});
}
}
ConsumerB:ConsumerB队列的指定的routingKey为 “error”,
public class ConsumerB {
public static void main(String[] args) throws IOException {
Connection connection = ConnectUtils.getConnection("121.199.53.150", 5672, "/ems", "ems", "ems");
Channel channel = connection.createChannel();
//声明与通道连接的交换机
channel.exchangeDeclare("logs_direct","direct");
//创建临时队列
String queue = channel.queueDeclare().getQueue();
//通道绑定队列和交换机
channel.queueBind(queue,"logs_direct","error");
//消费消息
channel.basicConsume(queue,true,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("consumerB direct rabbitmq:" + new String(body)+ "routingKey:" + envelope.getRoutingKey());
}
});
}
}
先执行两个消息消费者,监听队列中的消息,再执行消息生产者发送消息,查看控制台的输出信息:
此时只有ConsumerA能接受到消息,因为ConsumerA队列的routingKey和消息发送者发送消息时指定的routingKey相同,都是“info”
ConsumerA:
修改消息发送者发送消息时指定的routingKey为 “error”,再执行消息生产者发送消息,查看控制台的输出信息:
此时ConsumerA和ConsumerB都能接受到消息。