RabbitMQ 六种基本队列模式 ----- 路由(routing)

在之前的消息 订阅/发布 模式中已经实现了通过 Fanout 来向所有的接受者广播,在 routing 中就是在 订阅/发布 中增加指定发送的 routing key 即可。下面的图也来自于官方的实例,Q1 和 Q2 绑定到了 X 的交换机上边,Q1 绑定了 oragerouting keyQ2 绑定了 blackgreen 两个 routing key。这样在 p 使用 routing keyorange 发送时只有 Q1 会接收到消息。Q2 会将此消息抛弃。

https://img2022.cnblogs.com/blog/1106277/202201/1106277-20220128160520694-1068396519.jpg

使用 Java 来实现 发送者 和 接收者

  • 第一步当然还是导入 Maven 坐标。

    <!-- https://mvnrepository.com/artifact/com.rabbitmq/amqp-client -->
    <dependency>
        <groupId>com.rabbitmq</groupId>
        <artifactId>amqp-client</artifactId>
        <version>5.9.0</version>
    </dependency>
    
    <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-simple -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-simple</artifactId>
        <version>1.7.25</version>
    <!--            <scope>test</scope>-->
    </dependency>
    
  • 创建发送者端

    		private static final String EXCHANGE_NAME = "logs_routing";
    
        public static void main(String[] args) {
            try {
                ConnectionFactory factory = new ConnectionFactory();
                // 设置参数
                factory.setHost("192.168.3.64");
                factory.setPort(5672);
                factory.setVirtualHost("/default_virtual_host");
                factory.setUsername("admin");
                factory.setPassword("admin");
    
                Connection connection = factory.newConnection();
                Channel channel = connection.createChannel();
                // 创建交换机 此处不能用 FANOUT 作为交换机的类型了 ,需要换成 DIRECT
                channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT, true, false, false, null);
                // 声明两个队列
                channel.queueDeclare("log_fanout_queue1", false, false, false, null);
                channel.queueDeclare("log_fanout_queue2", false, false, false, null);
                // 绑定两个队列 (此处必须要要指定 routingkey)
                // 队列1只接收 info
                channel.queueBind("log_fanout_queue1", EXCHANGE_NAME, "info");
                // 队列2接收所有
                channel.queueBind("log_fanout_queue2", EXCHANGE_NAME, "info");
                channel.queueBind("log_fanout_queue2", EXCHANGE_NAME, "warn");
                channel.queueBind("log_fanout_queue2", EXCHANGE_NAME, "error");
    
                String message = "[日志][支付信息][订单号:" + new Date().getTime() + "][支付ID:10]";
                // 由于要使用 routing 模式发送所以就需要执行 routingkey
                channel.basicPublish(EXCHANGE_NAME, "info", null, message.getBytes(StandardCharsets.UTF_8));
                channel.basicPublish(EXCHANGE_NAME, "error", null, message.getBytes(StandardCharsets.UTF_8));
                // 释放资源
                channel.close();
                connection.close();
            } catch (IOException | TimeoutException e) {
                e.printStackTrace();
            }
        }
    
  • 创建第一个接受者

    private static final String EXCHANGE_NAME = "logs_routing";
    
        public static void main(String[] args) {
            try {
                ConnectionFactory factory = new ConnectionFactory();
                // 设置参数
                factory.setHost("192.168.3.64");
                factory.setPort(5672);
                factory.setVirtualHost("/default_virtual_host");
                factory.setUsername("admin");
                factory.setPassword("admin");
    
                Connection connection = factory.newConnection();
    
                Channel channel = connection.createChannel();
                channel.exchangeDeclare(EXCHANGE_NAME,
                        BuiltinExchangeType.DIRECT,
                        true,
                        false,false,
                        null);
    
                String queue1Name = "log_direct_queue1";
                DeliverCallback deliverCallback = (consumerTag, delivery) -> {
                    String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
                    System.out.println(" [info] Received '" + message + "'");
                };
                channel.basicConsume(queue1Name, true, deliverCallback, consumerTag -> {
                });
            } catch (IOException | TimeoutException e) {
                e.printStackTrace();
            }
    
        }
    
  • 创建第二个接受者

    private static final String EXCHANGE_NAME = "logs_routing";
    
        public static void main(String[] args) {
            try {
                ConnectionFactory factory = new ConnectionFactory();
                // 设置参数
                factory.setHost("192.168.3.64");
                factory.setPort(5672);
                factory.setVirtualHost("/default_virtual_host");
                factory.setUsername("admin");
                factory.setPassword("admin");
    
                Connection connection = factory.newConnection();
    
                Channel channel = connection.createChannel();
                channel.exchangeDeclare(EXCHANGE_NAME,
                        BuiltinExchangeType.DIRECT,
                        true,
                        false,false,
                        null);
    
                String queue1Name = "log_direct_queue2";
                DeliverCallback deliverCallback = (consumerTag, delivery) -> {
                    String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
                    System.out.println(" [info,error,warn] Received '" + message + "'");
                };
                channel.basicConsume(queue1Name, true, deliverCallback, consumerTag -> {
                });
            } catch (IOException | TimeoutException e) {
                e.printStackTrace();
            }
    
        }
    

    在发送者发送消息到指定的队列这时候两个接受者返回的消息为

    https://img2022.cnblogs.com/blog/1106277/202201/1106277-20220128160520924-533757211.png

    https://img2022.cnblogs.com/blog/1106277/202201/1106277-20220128160520683-583661682.png

    通过查看以上代码可以看出这个和 pub/sub 方式是一样,只不过是把广播模式切换成了指定方向的发送。然后在通道上绑定队列的时候要指定 routingKey 即可。

posted @ 2022-01-28 16:06  奔跑的砖头  阅读(87)  评论(0编辑  收藏  举报