文章目录

  • RabbitMQ——RabbitMQ的Direct消息模型
  • 1、Direct消息模型之发布者发布消息
  • 2、Direct消息模型之消费者消费消息


RabbitMQ——RabbitMQ的Direct消息模型

在 Fanout 消息模型中,使用Fanout交换机,一条消息发出去后,会被交换机发送给所有订阅的队列,再被队列对应的消费者消费。但是,再某些情况下,我们希望不同的消息能被不同的队列消费。这时就要用到Direct消息模型的Direct交换机。

Direct消息模型结构图

rabbitmq对consume设置qos rabbitmq的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:

rabbitmq对consume设置qos rabbitmq的direct_rabbitmq_02

修改消息发送者发送消息时指定的routingKey为 “error”,再执行消息生产者发送消息,查看控制台的输出信息:

此时ConsumerA和ConsumerB都能接受到消息。