• 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 即可。

  • 相关阅读:
    视图的作用,视图可以更改么?
    数据库事务的四个特性及含义
    mysql 设置隔离级别
    如何避免事务的并发问题?
    事务控制语言(TCL)
    事务的并发问题有哪些?
    事务的隔离级别: 事务并发问题如何发生?
    DDL 语言
    DML 语言
    TRUNCATE、Drop、Delete 的用法
  • 原文地址:https://www.cnblogs.com/l5gw/p/15853003.html
Copyright © 2020-2023  润新知