RabbitMQ的工作原理以及簡單的入門程序

一、RabbitMQ的工作原理

這裏給大家提供一個配套rabbitmq3.7.3和erlang20.3下載包(外網下載實在是慢啊):rabbitmq和erlang下載
下圖是RabbitMQ的基本結構:
在這裏插入圖片描述
組成部分說明如下:

  1. Broker:消息隊列服務進程,此進程包括兩個部分:Exchange和Queue。
  2. Exchange:消息隊列交換機,按一定的規則將消息路由轉發到某個隊列,對消息進行過慮。
  3. Queue:消息隊列,存儲消息的隊列,消息到達隊列並轉發給指定的消費方。
  4. Producer:消息生產者,即生產方客戶端,生產方客戶端將消息發送到MQ。
  5. Consumer:消息消費者,即消費方客戶端,接收MQ轉發的消息。

消息發佈接收流程:
-----發送消息-----

  1. 生產者和Broker建立TCP連接。
  2. 生產者和Broker建立通道。
  3. 生產者通過通道消息發送給Broker,由Exchange將消息進行轉發。
  4. Exchange將消息轉發到指定的Queue(隊列)

----接收消息-----

  1. 消費者和Broker建立TCP連接
  2. 消費者和Broker建立通道
  3. 消費者監聽指定的Queue(隊列)
  4. 當有消息到達Queue時Broker默認將消息推送給消費者。
  5. 消費者接收到消息。

二、rabbitmq入門程序

入門程序只是簡單的生產者發送消息,消費者接收消息!

如果是maven工程需要引入依賴

<dependencies>
        <dependency>
            <groupId>com.rabbitmq</groupId>
            <artifactId>amqp-client</artifactId>
            <version>4.0.3</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring‐boot‐starter‐logging</artifactId>
        </dependency>
    </dependencies>

生產者測試代碼

public class Producer01 {
    private static final String QUEUE = "helloworld";

    public static void main(String[] args) {
        //隊列
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("127.0.0.1");
        connectionFactory.setPort(5672); // 端口號
        connectionFactory.setUsername("guest");
        connectionFactory.setPassword("guest");
        // 設置虛擬機, 一個mq服務可以設置多個虛擬機,每個虛擬機就相當於一個獨立的mq
        connectionFactory.setVirtualHost("/");

        Connection connection = null;
        Channel channel = null;
        try {
            // 建立連接
            connection = connectionFactory.newConnection();
            // 創建會話通道,生產者和mq服務所有通信都在channel通道中完成
            channel = connection.createChannel();
            //聲明隊列,如果隊列在mq 中沒有則要創建
            //參數:String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments
            /**
             * 參數明細
             * 1、queue 隊列名稱
             * 2、durable 是否持久化,如果持久化,mq重啓後隊列還在
             * 3、exclusive 是否獨佔連接,隊列只允許在該連接中訪問,如果connection連接關閉隊列則自動刪除,如果將此參數設置true可用於臨時隊列的創建
             * 4、autoDelete 自動刪除,隊列不再使用時是否自動刪除此隊列,如果將此參數和exclusive參數設置爲true就可以實現臨時隊列(隊列不用了就自動刪除)
             * 5、arguments 參數,可以設置一個隊列的擴展參數,比如:可設置存活時間
             */
            channel.queueDeclare(QUEUE, true, false, false, null);

            /**
             * 參數明細:
             * 1、exchange,交換機,如果不指定將使用mq的默認交換機(設置爲"")
             * 2、routingKey,路由key,交換機根據路由key來將消息轉發到指定的隊列,如果使用默認交換機,routingKey設置爲隊列的名稱
             * 3、props,消息的屬性
             * 4、body,消息內容
             */
            //消息內容
            String message = "Test send Mq queue first!";
            channel.basicPublish("",QUEUE,null,message.getBytes());
            System.out.println("send to mq "+message);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }finally {
            //關閉連接
            //先關閉通道
            try {
                channel.close();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (TimeoutException e) {
                e.printStackTrace();
            }
            try {
                connection.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

結果:
在這裏插入圖片描述

消費者測試代碼

public class Consumer01 {
    private static final String QUEUE = "helloworld";

    public static void main(String[] args) throws IOException, TimeoutException {
        //通過連接工廠創建新的連接和mq建立連接
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("127.0.0.1");
        connectionFactory.setPort(5672);//端口
        connectionFactory.setUsername("guest");
        connectionFactory.setPassword("guest");
        //設置虛擬機,一個mq服務可以設置多個虛擬機,每個虛擬機就相當於一個獨立的mq
        connectionFactory.setVirtualHost("/");

        //建立新連接
        Connection connection = connectionFactory.newConnection();
        //創建會話通道,生產者和mq服務所有通信都在channel通道中完成
        Channel channel = connection.createChannel();

        //監聽隊列
        //聲明隊列,如果隊列在mq 中沒有則要創建
        //參數:String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments
        /**
         * 參數明細
         * 1、queue 隊列名稱
         * 2、durable 是否持久化,如果持久化,mq重啓後隊列還在
         * 3、exclusive 是否獨佔連接,隊列只允許在該連接中訪問,如果connection連接關閉隊列則自動刪除,如果將此參數設置true可用於臨時隊列的創建
         * 4、autoDelete 自動刪除,隊列不再使用時是否自動刪除此隊列,如果將此參數和exclusive參數設置爲true就可以實現臨時隊列(隊列不用了就自動刪除)
         * 5、arguments 參數,可以設置一個隊列的擴展參數,比如:可設置存活時間
         */
        channel.queueDeclare(QUEUE, true, false, false, null);

        //實現消費方法
        DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {

            /**
             * 當接收到消息後此方法將被調用
             * @param consumerTag  消費者標籤,用來標識消費者的,在監聽隊列時設置channel.basicConsume
             * @param envelope 信封,通過envelope
             * @param properties 消息屬性
             * @param body 消息內容
             * @throws IOException
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                //交換機
                String exchange = envelope.getExchange();
                //消息id,mq在channel中用來標識消息的id,可用於確認消息已接收
                long deliveryTag = envelope.getDeliveryTag();
                //消息內容
                String message = new String(body, "utf-8");
                System.out.println("receive message:" + message);
            }
        };

        //監聽隊列
        //參數:String queue, boolean autoAck, Consumer callback
        /**
         * 參數明細:
         * 1、queue 隊列名稱
         * 2、autoAck 自動回覆,當消費者接收到消息後要告訴mq消息已接收,如果將此參數設置爲tru表示會自動回覆mq,如果設置爲false要通過編程實現回覆
         * 3、callback,消費方法,當消費者接收到消息要執行的方法
         */
        channel.basicConsume(QUEUE, true, defaultConsumer);
    }
}

結果:
在這裏插入圖片描述
注:有兩條消息是因爲我再次重啓了生產者 消費則這邊因爲隊列還未斷開,所以會繼續接收。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章