RabbitMQ學習系列(二):簡單隊列詳解

(一)RabbitMQ的使用教程

RabbitMQ的官網提供了RabbitMQ的六種創建消息傳遞應用程序的方式https://www.rabbitmq.com/getstarted.html

分別是簡單隊列、工作隊列、Publish/Subscribe訂閱模式、routing路由模式、Topics主題模式和RPC,首先介紹簡單隊列。maven項目依賴如下:

<dependency>
    <groupId>com.rabbitmq</groupId>
    <artifactId>amqp-client</artifactId>
    <version>4.0.2</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.28</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.12</version>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>

(二)Rabbit的簡單隊列

簡單隊列的模型結構如下圖所示:

簡單隊列主要由三大結構組成:

P:producer生產者 發送消息的部分

紅色部分:一個隊列

C:consumer消費者 用於獲取隊列中的消息

簡單隊列即生產者將消息發送到隊列中,當消費者要用的時候直接在隊列中取即可。通過實際操作來模擬簡單隊列的運行流程

2.1 新建工具類

首先寫一個連接工具類,用戶獲取rabbitmq的連接:

public class ConnectionUtil {
    public static Connection getConnection() throws IOException, TimeoutException {
        //定義一個連接工廠
        ConnectionFactory factory=new ConnectionFactory();
        //設置服務地址
        factory.setHost("127.0.0.1");
        //設置AMQP端口
        factory.setPort(5672);
        //設置VHOSTS
        factory.setVirtualHost("/vhosts_sdxb");
        //設置用戶名
        factory.setUsername("user_sdxb");
        factory.setPassword("123456");
        return factory.newConnection();
    }
}

需要注意的是連接工廠中設置的端口不是rabbitmq可視化界面的端口,而是AMQP協議的端口,這個端口號可在rabbitmq的可視化界面中查看到:

2.2 創建生產者

public class Send {
    private static final String QUEUE_NAME="simple_queue";
    public static void main(String[] args) throws IOException, TimeoutException {
        //獲取一個連接
        Connection connection = ConnectionUtil.getConnection();
        //從連接中獲取一個通道
        Channel channel = connection.createChannel();
        //創建隊列聲明
        channel.queueDeclare(QUEUE_NAME,false,false,false,null);
        String msg="Hello rabbitmq";
        //發佈隊列
        channel.basicPublish("",QUEUE_NAME,null,msg.getBytes());
        channel.close();
        connection.close();
    }
}

這段代碼創建了一個名爲simple_queue的隊列,並且發佈了一條msg到隊列中,可在rabbitmq的可視化界面看到詳情:

標記1處表示隊列的名稱,標記2處代表此時隊列中的消息數。

上面一段代碼中有幾個方法的參數介紹一下:

channel.queueDeclare(String queue , boolean durable , boolean exclusive , boolean autoDelete , Map arguments);
queue:隊列名稱
durable:是否設置持久化,隊列中的消息是存放在內存中的,理論上如果隊列掛掉消息也就消失了,
因此持久化參數可以讓隊列消息持久化到硬盤
exclusive:設置是否排他,即如果一個隊列被聲明爲排他隊列,該隊列僅對首次聲明它的連接可見
autoDelete:設置是否自動刪除,爲true則設置隊列爲自動刪除
arguments:設置隊列的其他一些參數

其中現在不懂的參數會在接下來幾種模式的學習中學到。

channel.basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body)
exchange:交換器名稱
routingKey:路由鍵
props:有14個應用程序標識號 - 生成消息的應用程序標識符
body:真正要發送的消息

2.3 創建消費者

public class Receive {
    private static final String QUEUE_NAME = "simple_queue";

    public static void main(String[] args) throws IOException, TimeoutException {
        //獲取一個連接
        Connection connection = ConnectionUtil.getConnection();
        //從連接中獲取一個通道
        Channel channel = connection.createChannel();
        //創建隊列聲明
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        //創建消費者監聽方法
        Consumer consumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String msg = new String(body, "utf-8");
                System.out.println("receive:" + msg);
            }
        };
        //監聽隊列
        channel.basicConsume(QUEUE_NAME, true, consumer);
    }
}

通過重寫DefaultConsumer的handleDelivery方法來獲取隊列中的消息,並通過channel.basicConsume來監聽隊列,一旦隊列中有消息存在就取出。

(三)簡單隊列的不足

簡單隊列耦合性高,一個消費者對應於一個生產者,無法處理多個消費者同時調用消息隊列的情況。

要變換隊列名稱時,需要同時該表消費者和生產者中隊列的名稱,麻煩並且容易遺漏。

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