RabbitMQ 六种基本队列模式 ----- 消息订阅(Publish/Subscribe)

我们将向多个消费者传递一条信息。这种模式称为“发布/订阅”

https://img2022.cnblogs.com/blog/1106277/202201/1106277-20220128160411067-1740606322.jpg

**在之前的文章 P 和 C 已经很清楚是什么意思了,这里面的X代表的是交换机(Exchange)。交换机只负责转发消息,不具有存储消息的能力,因此如果没有队列与交换机绑定,或者没有符合规则的队列,那么消息就会丢失**

交换机的类型

  • Fanout: 广播,发送到每个与交换机绑定的队列
  • Direct: 定向
  • Topic: 通配符
  • Headers: 参数匹配

使用 java 来实现简单的 Publish/Subscribe

  • 导入 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>
    
  • 编写 Publish 端代码

    public static void main(String[] args) {
            final String EXCHANGE_NAME = "logs";
            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.FANOUT, true, false, false, null);
                // 创建队列
                channel.queueDeclare("log_fanout_queue1", false, false, false, null);
                channel.queueDeclare("log_fanout_queue2", false, false, false, null);
                // 绑定队列
                channel.queueBind("log_fanout_queue1", EXCHANGE_NAME, "");
                channel.queueBind("log_fanout_queue2", EXCHANGE_NAME, "");
                // 发送消息
                String message = "[日志][支付信息][订单号:" + new Date().getTime() +"][支付ID:10]";
                channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes(StandardCharsets.UTF_8));
                // 释放资源
                channel.close();
                connection.close();
    
            } catch (IOException | TimeoutException e) {
                e.fillInStackTrace();
            }
        }
    
  • 编写第一个 Subscribe 端代码

    public static void main(String[] args) {
            final String EXCHANGE_NAME = "logs";
    
            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.FANOUT, true, false, false, null);
    
                String queue1Name = "log_fanout_queue1";
    
    //            channel.queueBind(queue1Name, EXCHANGE_NAME, "");
    
                DeliverCallback deliverCallback = (consumerTag, delivery) -> {
                    String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
                    System.out.println(" [x] Received '" + message + "'");
                };
                channel.basicConsume(queue1Name, true, deliverCallback, consumerTag -> {
                });
    
            } catch (IOException e) {
                e.printStackTrace();
            } catch (TimeoutException e) {
                e.printStackTrace();
            }
        }
    
  • 编写第二个 Subscribe 端代码

    
    public static void main(String[] args) {
            final String EXCHANGE_NAME = "logs";
    
            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.FANOUT, true, false, false, null);
    
                String queue2Name = "log_fanout_queue2";
    
    //            channel.queueBind(queue2Name, EXCHANGE_NAME, "");
    
                DeliverCallback deliverCallback = (consumerTag, delivery) -> {
                    String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
                    System.out.println(" [x] Received '" + message + "'");
                };
                channel.basicConsume(queue2Name, true, deliverCallback, consumerTag -> {
                });
    
            } catch (IOException e) {
                e.printStackTrace();
            } catch (TimeoutException e) {
                e.printStackTrace();
            }
        }
    
  • 启动消费者和生产者

    • 消息队列展示

      https://img2022.cnblogs.com/blog/1106277/202201/1106277-20220128160411129-182421192.png

    • 消费者接收到的消息

      https://img2022.cnblogs.com/blog/1106277/202201/1106277-20220128160411107-106205230.png

      https://img2022.cnblogs.com/blog/1106277/202201/1106277-20220128160411131-681827394.png

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