RabbitMQ之Queue屬性測試

dy223 9年前發布 | 20K 次閱讀 RabbitMQ 消息系統

本篇圍繞 RabbitMQ 中最基本的 fabric – queue 進行討論,主要介紹其常用的幾個屬性設置,以及在實際使用中的約束條件。

常用queue屬性

rabbitmq-c代碼中可以看到如下代碼
RabbitMQ之Queue屬性測試
上圖所示為
queue聲明時使用的結構體。其中最容易讓使用者迷惑的3個屬性是durableexclusiveauto_delete
RabbitMQ之Queue屬性測試
上圖所示為
consumerqueue進行消息消費時用于設置屬性的結構體。其中最容易讓使用者迷惑的屬性是exclusive(上圖中的exclusive注釋有點問題,請忽略)

測試過程

在編寫python語言的測試程序時,我將行為分為以下幾步

  • 聲明7個具有不同屬性的queue,分別和名為test_exchage的exchange進行綁定(因為exchange為fanout類型,所以測試代碼中的routing_key其實是不起作用的);
  • 向exchange發送具有persistent屬性的消息(delivery_mode=2);
  • 創建7個消費者分別從上述7個queue中獲取消息;

RabbitMQ之Queue屬性測試

RabbitMQ之Queue屬性測試

RabbitMQ之Queue屬性測試

測試結果如下

RabbitMQ之Queue屬性測試

可以看到,所有的7個消費者均收到了對應的消息內容。 

下面我們從RabbitMQ服務器測查看以下上述測試能展現什么信息。

1.client和server建立了一條AMQP connection

RabbitMQ之Queue屬性測試

2.在該connection上使用了channel1進程AMQP協議通信。

RabbitMQ之Queue屬性測試

3.連接建立時的用戶名為guest,以及各種channel屬性設置情況。

RabbitMQ之Queue屬性測試

4.在當前channel上共存在7個消費者,分別從7個不同的queue上獲取消息;該channel上的消息均來自名為test_exchageexchange(請原諒我測試過程中的英文拼寫錯誤)。

RabbitMQ之Queue屬性測試

Exchanges選項卡上可以看到test_exchage下綁定了哪些queue

RabbitMQ之Queue屬性測試

Queues選項卡上可以看到全部7queue的屬性情況

RabbitMQ之Queue屬性測試

看到這里,眼尖的同學可能會發現問題所在了,那就是客戶端代碼中聲明的queue屬性并沒有全部生效,為什么會這樣呢?

首先分別看一下代碼中聲明的7queue在服務器側的詳細信息。

a.test_1_queue沒有設置任何屬性,在界面上沒有看到任何屬性。

RabbitMQ之Queue屬性測試

RabbitMQ之Queue屬性測試

b. test_2_queue設置了durable屬性,在界面上看到了“durable:true”。

RabbitMQ之Queue屬性測試

RabbitMQ之Queue屬性測試

 

c. test_3_queue設置了auto-delete屬性,在界面上看到了“auto-delete:true”。

RabbitMQ之Queue屬性測試

RabbitMQ之Queue屬性測試

d. test_4_queue同時設置了durableauto-delete屬性,在界面上看到了“durable:trueauto-delete:true”。

RabbitMQ之Queue屬性測試

RabbitMQ之Queue屬性測試

e. test_5_queue同時設置了durableexclusive屬性,但在界面上只看到了“Exlusive owner”的存在。

RabbitMQ之Queue屬性測試

RabbitMQ之Queue屬性測試

f. test_6_queue同時設置了auto_deleteexclusive屬性,在界面上同時看到“auto-delete:true”和“Exlusive owner”的存在。

RabbitMQ之Queue屬性測試

RabbitMQ之Queue屬性測試

g. test_7_queue同時設置了durableauto_deleteexclusive屬性,在界面上只看到了“auto-delete:true”和“Exlusive owner”的存在。

RabbitMQ之Queue屬性測試

RabbitMQ之Queue屬性測試

綜上,可以得出如下結論

  • durable屬性和auto-delete屬性可以同時生效
  • durable屬性和exclusive屬性會有性質上的沖突,兩者同時設置時,僅exclusive屬性生效
  • auto_delete屬性和exclusive屬性可以同時生效

除此之外,還能得到其它一些有趣的結論:

  • Queue的“Exlusive owner”對應的是connection而不是channel
  • Consumer存在于某個channel上的

 附上一張客戶端同時設置durableauto_deleteexclusive屬性的抓包截圖:

RabbitMQ之Queue屬性測試

下面通過改變client側代碼,模擬不同情況下各種屬性對queue的存在情況的影響。

a.在成功創建全部7queue后,通過Ctrl+C異常終止客戶端程序。

RabbitMQ之Queue屬性測試

(上圖為全部創建時的狀態)

 RabbitMQ之Queue屬性測試

 停止后,queue的情況如下圖所示。

RabbitMQ之Queue屬性測試

對比發現,此時只有 test_1_queue test_2_queue 仍舊存在,其它queue已經被RabbitMQ服務器刪除掉了(思考原因)。

b.客戶端側執行到消息發送后,結束當前操作(無consumer情況)。代碼調整如下

RabbitMQ之Queue屬性測試

此時仍舊可以看到queue的聲明和綁定都是成功的。

RabbitMQ之Queue屬性測試

此時客戶端程序執行后會自動退出

RabbitMQ之Queue屬性測試

再從web頁面查看queue的情況如下

RabbitMQ之Queue屬性測試

對比發現,此時僅test_1_queuetest_2_queuetest_3_queuetest_4_queue 存在(思考原因)。

      這里有個細節值得說一下:雖然最終我們在web頁面上只看到了4queue的存在,但其實7queue都被成功創建過(抓包可以證明),如果你夠幸運,你也可能在web頁面上看到一閃而過的另外3queue。通過對比可以發現,導致另外3queue消失的原因是exclusive屬性的設置,前面我已經說過,queue的“Exlusive owner”對應的是connection,所以在這個實驗中可以確定的是,connection仍舊是存在的(這里遺留個問題:為什么python執行退出后連接仍舊存在),而此時實際上不存在的是consumer,所以需要對之前得到的結論進行加強:具有exclusive屬性的queue的存在條件是在connection上存在某個consumer訂閱了該queue同樣可以得到另外一個結論:可以在沒有創建consumer的情況下,創建出具有auto-delete屬性的queue

RabbitMQ官方文檔中其實已經對上述現象進行了說明,只不過一語帶過,不注意的話容易忽略掉。在queue.declare方法中包含如下屬性說明

RabbitMQ之Queue屬性測試

此時肯定有人會問,除了queue.declare中具有exclusive屬性,basic.consume中也具有exclusive屬性,后者是什么含義呢?在文檔說明中有如下內容

RabbitMQ之Queue屬性測試

由此可以理解兩個屬性的差異和實際使用中應該注意的問題是什么!(自行思考)

在此情況下,若執行RabbitMQ server的重啟(rabbitmqctl stop_app;rabbitmqctl start_app),可以看到僅有test_2_queuetest_4_queue仍舊存在。

RabbitMQ之Queue屬性測試

測試版本

以上測試基于如下RabbitMQ版本

RabbitMQ之Queue屬性測試

為什么使用這個版本?(我猜肯定有人會問)因為這個實驗是我半年前就已經完成了的~~

來自:http://my.oschina.net/moooofly/blog/392239

 本文由用戶 dy223 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!