RabbitMQ——消息發佈訂閱

消息訂閱發佈

在這裏插入圖片描述

  • 一個生產者,多個消費者
  • 每個消費者都有自己的隊列
  • 生產者,沒有直接把消息發送到隊列,而是先發送到交換機
  • 每個隊列都要綁定到交換機
  • 生產者發送的消息 經過交換機,到達隊列,就能實現一個消息被多個消費者消費

話不多說,直接擼代碼:

老套路,首先還是生產者:

public class Send {

    private static final String EXCHANGE_NAME = "test_exchange";

    public static void main(String[] args) throws IOException, TimeoutException {
        Connection connection = RabbitConnection.getConnection(); //看前面文章寫的工具類
        Channel channel = connection.createChannel();
        channel.exchangeDeclare(EXCHANGE_NAME, "fanout"); //聲明exchange,這裏爲什麼是fanout待會下面解釋
        //send a msg
        String msg = "hello exchange";
        channel.basicPublish(EXCHANGE_NAME, "", null, msg.getBytes());
        System.out.println("send:"+msg);
        channel.close();
        connection.close();
    }
}

消費者1:

public class ReceiveOne {
    private static final String QUEUE_NAME = "receive1_queue";  //這裏我們重新申請一個新的隊列
    private static final String EXCHANGE_NAME = "test_exchange";

    public static void main(String[] args) throws IOException, TimeoutException {
        Connection connection = RabbitConnection.getConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);

        channel.basicQos(1);
        channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, ""); //這裏需要綁定exchange,其他的和前面的work_queue是一樣的

        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody(), "UTF-8");
            System.out.println(" [ConsumerOne is] Received '" + message + "'");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                channel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);  //這裏是手動應答
            }
        };
        boolean autoAck = false;
        channel.basicConsume(QUEUE_NAME, autoAck, deliverCallback, consumerTag -> { });
    }
}

消費者2:

public class ReceiveTwo {

    private static final String QUEUE_NAME = "receive2_queue";
    private static final String EXCHANGE_NAME = "test_exchange";


    public static void main(String[] args) throws IOException, TimeoutException {
    Connection connection = RabbitConnection.getConnection();
    Channel channel = connection.createChannel();
    channel.queueDeclare(QUEUE_NAME, false, false, false, null);

    channel.basicQos(1);
    channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "");

    DeliverCallback deliverCallback = (consumerTag, delivery) -> {
        String message = new String(delivery.getBody(), "UTF-8");
        System.out.println(" [ConsumerTwo is] Received '" + message + "'");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            channel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);  //這裏是手動應答
        }
    };
    boolean autoAck = false;
    channel.basicConsume(QUEUE_NAME, autoAck, deliverCallback, consumerTag -> { });    }
}

我們啓動send和兩個消費者,消費者同時消費,同一個消息,
在這裏插入圖片描述

在這裏插入圖片描述
在這裏插入圖片描述
再回到控制檯,發現綁定了兩個隊列:
在這裏插入圖片描述

關於send中那個fanout參數,有必要講一下,它表示不處理路由鍵,具體路由鍵是怎麼回事,可參考下面這個博客:

路由鍵

至此消息訂閱發佈模式結束。

發佈了138 篇原創文章 · 獲贊 42 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章