RabbitMQ 入門系列:2、基礎含義理解:鏈接、通道、隊列、交換機

系列目錄

RabbitMQ 入門系列:1、MQ的應用場景的選擇與RabbitMQ安裝。

RabbitMQ 入門系列:2、基礎含義:鏈接、通道、隊列、交換機。

RabbitMQ 入門系列:3、基礎含義:持久化、排它性、自動刪除、強制性、路由鍵。

RabbitMQ 入門系列:4、基礎編碼:官方SDK使用:鏈接創建、單例改造、發送消息、接收消息。

RabbitMQ 入門系列:5、基礎編碼:交換機的進階介紹及編碼方式。

RabbitMQ 入門系列:6、保障消息:不丟失:發送方、Rabbit存儲端、接收方。

RabbitMQ 入門系列:7、保障消息:不重複消費:產生消息的唯一ID。

RabbitMQ 入門系列:8、擴展內容:接收資訊時:可否根據RoutingKey過濾監聽資訊,答案是不能。

RabbitMQ 入門系列:9、擴展內容:死信隊列:真不適合當延時隊列。

RabbitMQ 入門系列:10、擴展內容:延時隊列:延時隊列插件及其有限的適用場景。

前言:

本系列介紹RabbitMQ,介紹RabbitMQ的基礎概念的含義。

並掃清網路上的一些錯誤或容易誤導人的內容,幫助網友快速正確理解並掌握RabbitMQ。 

下面開始本篇內容相關介紹。

1、上圖管理中心圖:

 

從管理中心可以看到,主要有以下幾個大菜單:

1、Overview:概述,就是基礎監控。

2、Connections:鏈接

3、Channels:通道

4、Queues:隊列

5、Admin:管理 

除去概述和管理,剩下三個是理解RabbitMQ的重要指標。

下面進行基本概念介紹,涉及的程式碼,下一篇再介紹:

1、鏈接:

比如用官方的SDK創建一個鏈接:

using RabbitMQ.Client;

var factory = new ConnectionFactory()
{
    HostName = "127.0.0.1",
    UserName = "guest",
    Password = "guest",
    VirtualHost = "/"
};

var connection = factory.CreateConnection();

即產生一個鏈接:

 

對於這段程式碼,如果在一個Web應用程式中不斷執行,在大並發請求下會產生大量的鏈接,這是不可取的。 

如果再加上分散式部署,大量Web應用再加大量並發,鏈接資源就不夠用了。

因此,官網的建議,是用戶應該把它做成單例,一個應用盡量使用1個鏈接。

官方為了讓多個執行緒共享一個鏈接,又不互相影響,做出了通道的概念。

2、通道:

為了減少鏈接數,降低資源開銷,RabbitMQ設計了通道的概念。

1個鏈接可以創建無數個通道,然後主要的編碼,就是針對通道編碼。

using RabbitMQ.Client;
using System.Text;
using RabbitMQ.Client.Events;

var factory = new ConnectionFactory()
{
    HostName = "127.0.0.1",
    UserName = "guest",
    Password = "guest",
    VirtualHost = "/"
};

var connection = factory.CreateConnection();

var channel = connection.CreateModel();

 

 

當然,這樣編碼在Web應用程式是不可取的,應該把鏈接那一塊的創建整成單例,下面示例中將忽略獲取鏈接這一塊。

因此,後續編碼都是在獲取單例鏈接,創建通道,然後再進行一步操作。

3、隊列:創建隊列,發送消息、監聽隊列,獲取消息。

這裡先描述隊列,交換機這種多出來的概念,放到後面再進行描述:

隊列,即數據存檔和獲取數據的地方。

簡單需求下,只需要給把資訊發給隊列,然後監聽隊列獲取資訊就完事了。

發送消息:

...
var channel = connection.CreateModel();

channel.QueueDeclare("FirstQueue", false, false, false);//創建隊列
channel.BasicPublish("", "FirstQueue", false, null, Encoding.UTF8.GetBytes("這是要發送的內容"));
channel.Close();

 

 監聽隊列,並獲取資訊:

...
var channel = connection.CreateModel();

var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) =>
{
    var message = Encoding.UTF8.GetString(ea.Body.ToArray());
    Console.WriteLine("收到默認消息 {0}", message);
};
string msg = channel.BasicConsume(queue: "FirstQueue",
                      autoAck: true,
                      consumer: consumer);

 

對於以上的發送到監聽,都不涉及到交換機,直接來,直接去即可。

那麼,交換機概念的引入,有什麼作用呢?

4、交換機:

如果通道的出現,是為了降低鏈接數,那麼交換機的出現,竟然不是為了降低隊列數。

示例說明:比如一開始創建了一個用戶隊列:User :用它發送存儲用戶的註冊資訊隊列

後面新增需求,發現User要實現很多個分支:

按照常規模式,也能實現,創建多個隊列,可以滿足需求。

但隨著業務和模組分支越來越多,隊列可能會太多,不便於管理和維護。 

一開始,以為:通過交換機,引入路由(routekey)後,結構會變化成:

後來,發現理解錯了,特別是被網上的教程誤導,發現隊列是沒有子隊列或根據routekey過濾拿數據的功能的。

路由真實的效果是:允許發送一次,Copy資訊同時發散到多個多隊:

 

發送: (可以發送1條,同時到匹配路由的3個隊列去)

channel.BasicPublish("User", "#.user", false, null, Encoding.UTF8.GetBytes("這是要發送的內容"));

交換機有好幾種路由功能,這些先放到後面,放這裡不便於入門理解。

對交換機的功能,理解上面中提到的路由真實的效果那一句話即可。

總結:

本篇介紹RabbitMQ的基礎概念的含義,有助於快速理解並掌握RabbitMQ。