學習在.NET Core中使用RabbitMQ進行訊息傳遞之持久化(二

yzf01發表於2021-09-09

上一節我們簡單介紹了RabbitMQ和在安裝後啟動所出現的問題,本節我們開始正式進入RabbitMQ的學習,對於基本概念請從官網上查閱,我這裡不介紹基礎性東西,只會簡單提一下,請知悉。

RabbitMQ持久化

在RabbitMQ中存在四種交換機,一是直連交換機(Direct Exchange),二是廣播交換機(Fantout Exchange),三是主體交換機(Topic Exchange),四是頭交換機(Header Exchange),每種交換機都有其對應場景,後面會一一講到。任何處理訊息的開源庫都離不開兩個角色,一是生產者(Producer),二是消費者(Consumer),訊息從生產者到達消費者需經過三個階段也就是我們需要知道的三個概念,一是交換機,二是佇列,三是繫結,初次見此三者概念感覺很高大上是不是,其實不過是高度抽象了而已,同時看到很多部落格上對此三者解釋的還是非常深刻,我這裡就不過多細說。我們先看別人部落格上對整個RabbitMQ架構用圖來進行標識,然後對照我對交換機、佇列、繫結一言以蔽之進行如下概括您就明白他們具體是幹什麼了。

交換機是生產者釋出訊息的入口點,佇列是消費者獲取訊息的容器,繫結是將交換機連線到佇列的規則
圖片描述

我們簡單過一下訊息從生產者到達消費者的大概過程,生產者也就是上述圖中的ClientA和ClientB,傳送訊息到交換機,這裡交換機可以是一個或者多個,然後透過路由鍵繫結到佇列,那麼消費者如何知道繫結到了哪個佇列呢?然後消費者也就是上述Client1、Client2、Client3也要宣告交換機、佇列、繫結,這樣整個過程就串起來了,原理大概就是這樣。接下來我們透過程式碼來實現生產者傳送訊息(請透過NuGet安裝RabbitMQ客戶端)。

public class RabbitMQService
{
    public IConnection GetRabbitMQConnection()
    {
        var connectionFactory = new ConnectionFactory
        {
            HostName = "localhost",
            UserName = "guest",
            Password = "guest"
        };
        return connectionFactory.CreateConnection();
    }
}

第一步當然是需要建立連線,連線到RabbitMQ服務,接下來則是在我們建立連線的基礎上建立通道,然後上述我們所說訊息從生產者到達消費者的過程就是在此通道上進行。

        var rabbitMQService = new RabbitMQService();
        var connection = rabbitMQService.GetRabbitMQConnection();
        var model = connection.CreateModel();

接下來則是宣告交換機、佇列、透過路由鍵將交換機和佇列繫結在一起。

    static void InitialTopicQueue(IModel model)
    {
        model.QueueDeclare("queueDeclare", true, false, false, null);
        model.ExchangeDeclare("exchangeDeclare", ExchangeType.Topic);
        model.QueueBind("queueDeclare", "exchangeDeclare", "routeKey");
    }

如上我們宣告佇列名稱為queueDeclare且該佇列持久化,然後宣告交換機名稱為exchangeDeclare,交換機型別為主題,最後透過QueueBind方法透過routekey路由鍵將宣告的交換機和佇列繫結在一起。接下來我們開始釋出訊息。

        var basicProperties = model.CreateBasicProperties();
        basicProperties.DeliveryMode = 1;
        var payload = Encoding.UTF8.GetBytes("這是來自執行VS2017控制檯發出的訊息");
        var address = new PublicationAddress(ExchangeType.Topic, "exchangeDeclare", "routeKey");
        model.BasicPublish(address, basicProperties, payload);

然後我們在控制檯中執行上述程式,然後在RabbitMQ UI上來檢視宣告的交換機、佇列、繫結的路由鍵以及承載的訊息。

圖片描述
圖片描述
圖片描述

一切如正常執行,其我們釋出的訊息在佇列中處於Ready狀態,接下來我們在服務中關閉RabbitMQ服務代理,然後重啟模擬當機的情況。

圖片描述
圖片描述

因為在宣告佇列中第二個引數可指定該佇列是否可持久化,我們指定為True即持久化,所以即使RabbitMQ Broker重啟佇列依然還在,這個時候我們會發現在佇列中的資料被扔掉了,也就是說此時的佇列為空。那是因為我們指定訊息為非持久化,如下指定傳輸模式即DeliveryModel屬性為1,1代表非持久化,2為可持久化。所以如果我們指定DeliveryMode等於2即使RabbitMQ代理當機,重啟後訊息依然還在。

        var basicProperties = model.CreateBasicProperties();
        basicProperties.DeliveryMode = 2;

同理切換到ExchangeType介面時,此時我們宣告的交換機不存在了,如下:
圖片描述

因為宣告交換機時ExchangeDeclare方法有過載,第三個引數可指定是否持久化,預設為非持久化,如果我們進行如下指定為持久化,那麼和在佇列中的訊息一樣即使RabbitMQ代理重啟交換機依然還在,這個就不需要我再過多囉嗦了。

model.ExchangeDeclare("exchangeDeclare", ExchangeType.Topic, true);

從如上演示我們可看出在RabbitMQ中關於持久化,可對交換機(ExChange)、佇列(Queue)、訊息(Message)分別指定持久化,而且在大部分情況下這也是我們想要的。因為這至少可以保證訊息從生產者傳遞消費者的過程中不會丟失。那麼對於持久化和非持久化RabbitMQ是如何進行處理的呢?

持久化:將訊息儲存到磁碟上,因此即使在伺服器重新啟動後它們仍然可用,只不過在讀取和儲存訊息時會產生一些額外的開銷罷了。
非持久化:將訊息被儲存在記憶體中,雖然它們在伺服器重啟後將會消失,但提供更快的訊息處理。

總結

今天我們詳細講解了RabbitMQ中的持久化,我們可從交換機、佇列、訊息三個層面去設定持久化。這只是小試牛刀,下節開始討論細枝末節,學習的過程也是發現問題的過程,我們下節再會。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2334/viewspace-2800829/,如需轉載,請註明出處,否則將追究法律責任。

相關文章