本系列是「RabbitMQ實戰:高效部署分散式訊息佇列」書籍的總結筆記。
本篇是「RabbitMQ實戰」系列的最後一篇,主要介紹RabbitMQ外掛,瞭解如何安裝和啟用它,列舉一些常用的外掛,以及如何自定義。
在介紹之前,先總結下本系列的主要內容,把它們串起來。
系列總結
開篇時,這樣定義過RabbitMQ:它是一個開源的訊息代理和佇列伺服器,可以通過基本協議在完全不同的應用之間共享資料,可以將作業排隊以便讓分散式服務進行處理。
這句話有幾個關鍵詞:訊息代理、佇列伺服器、共享資料、分散式處理,分別來說明下,以加深理解。
訊息代理:可以把RabbitMQ看成一個代理伺服器,一方面把訊息生產者和消費者進行了解耦,更靈活;一方面,訊息如何分發不用生產者考慮了,RabbitMQ提供多種分發策略。
佇列伺服器:訊息最終是快取在佇列中的,消費者從指定的佇列中消費訊息,所以需要管理佇列和佇列中的訊息。
共享資料:主要是說訊息可以在不同應用間傳輸資料,通過AMQP協議進行規範,達到共享資料的目的。
分散式處理:多個消費者可以訂閱同一個佇列,這樣,多臺機器就可以同時處理同一批資料,達到分散式處理的效果。
如果理解AMQP基本元素和訊息模型,上面的概念會很好理解,有2篇文章重點介紹了這塊。
有些場景,對RabbitMQ可用性要求比較高,不容許有訊息的丟失,需要了解RabbitMQ的可用性保障和實現。另外, 要能夠實時監控RabbitMQ的本身及各個元件的執行情況,有問題時及時報警,快速進行處理。
如果訊息量和併發量比較高,需要根據不同的業務場景,在可用性和效能上進行平衡,以滿足業務的需要。
有些訊息比較敏感,在傳輸的過程中要進行加密處理,通過ssl協議可以很好的解決。
最後,RabbitMQ提供了一些列的外掛,為我們提供了很多有用的功能,比如Web管理介面外掛、Shovel跨機房複製外掛等,還允許我們自定義外掛,擴充套件需要的功能。
完整索引:
外掛介紹
當需要某些功能而伺服器沒有時,可以通過新增外掛的方式來進行增強,可以從網路上找,也可以自己編寫外掛。
用外掛可以做什麼
先簡單舉幾個例子,這些可以通過安裝外掛來解決:
- 支援AMQP以外的協議;
- 不同的認證機制(LDAP、自定義資料庫);
- 訊息複製;
- 新的交換器和路由演算法;
- 訊息日誌和審計;
STOMP是一個簡單的基於文字的協議,用於在應用之間傳輸資料,它可以與ActiveMQ伺服器一起工作,如果你的程式碼基於ActiveMQ和STOMP,但想使用RabbitMQ,就可以使用STOMP外掛進行適配。
假設你的系統中所有的使用者管理均通過LDAP,想在RabbitMQ中使用它進行認證,可以使用rabbitmq-auth-backend-ldap外掛進行整合。
LDAP是輕量目錄訪問協議,一個為查詢、瀏覽和搜尋而優化的專業分散式資料庫,它呈樹狀結構組織資料,就好象Linux/Unix系統中的檔案目錄一樣。目錄資料庫和關聯式資料庫不同,它有優異的讀效能,但寫效能差,並且沒有事務處理、回滾等複雜功能,不適於儲存修改頻繁的資料。所以目錄天生是用來查詢的,就好象它的名字一樣。
還可以自定義路由規則的交換器,下面會詳細介紹。
查詢和管理外掛
可以檢視 官網頁面,查詢到維護和實驗階段的外掛。
再來看看外掛的一些管理命令:
開啟外掛,外掛開啟後,需要重啟RabbitMQ伺服器:
./rabbitmq-plugins enable <plugin-name>
複製程式碼
禁用外掛,禁用外掛後,需要重啟RabbitMQ伺服器:
./rabbitmq-plugins disable <plugin-name>
複製程式碼
檢視啟用的外掛:
./rabbitmq-plugins list -e
複製程式碼
自定義外掛
使用一個具體的例子來介紹自定義外掛的開發,有這樣一個場景:使用RabbitMQ為聊天應用建模,該模型中有一個全域性聊天室,所有的使用者都連線到這裡,每位使用者擁有自己的佇列,繫結到全域性fanout交換器上。
每次發訊息到該交換器上時,該訊息會群發給所有繫結的佇列上,但如果有一個新的客戶端連線到這個聊天室,只會得到傳送給聊天室的新訊息,無法瞭解在加入之前會話的上下文。
如果能將最近的訊息傳送給新來的客戶,使用者體驗更更好點,可以通過自定義交換器實現這個功能。
外掛開發環境和說明
RabbitMQ開發者制定了開發環境,即RabbitMQ Public Umbrella,通過把它從程式碼庫中籤出,然後把自己的外掛新增到專案結構中。
RabbitMQ是用Erlang語言開發的,Erlang原始碼是以模組的方式組織起來的,模組內的函式實現了應用程式需要提供的功能,外掛只需要一個模組來包含自定義互動器的實現。
在物件導向程式設計中,擁有介面的概念,在Erlang中有相同的概念:behavious(行為)。
Erlang behavior 確定了模組需要實現和匯出哪些函式,這樣呼叫該模組的程式碼才知道該如何使用它。
另一個不同的地方在於,Erlang沒有java那樣可見性概念,擁有的就是一個模組匯出列表,如果模組實現了函式fun1、fun2和fun3,但只匯出fun1的話,fun2和fun3將無法被外界呼叫。
另外,還有一個函式引數數量的概念,可以接受名字相同、引數數量不同的函式,因此behavious可以確定函式fun1/1和fun1/2是兩個不同的函式。
一般步驟
首先,確認要擴充套件的behavios,RabbitMQ暴露了一個交換器behavious,名為rabbit_exchange_type,它會明確需要實現哪些函式來成為一個符合要求的交換器。
然後,梳理實現思路:我們要實現的是一個加強版的fanout型別交換器,快取最近20條訊息,可以基於RabbitMQ上的fanout交換器進行實現。
- 需要快取已路由的訊息,每當交換器路由訊息的時候,就將該訊息儲存到某個資料庫中,該功能可在函式route/2中實現;
- 當佇列繫結到交換器時,需要把快取的訊息投遞過去,該功能可在函式add_binding/3中實現;
- 當交換器刪除的時候,需要丟棄快取的訊息,該功能可在函式delete/3中實現;
然後,實現交換器behavious,我沒有看相關實現細節,感興趣的可以檢視實現程式碼:傳送門。
最後,將交換器註冊到RabbitMQ,RabbitMQ維護了一個登錄檔,用這張表來跟蹤所有的交換器型別及其模組名稱,假設將訊息釋出到fanout交換器上,RabbitMQ會進入登錄檔,檢查由哪個模組來實現fanout交換器,找到後,會繼續呼叫該模組的路由函式。
所以,需要找到一個方法將自定義交換器新增到登錄檔中,RabbitMQ支援啟動步驟的概念,當伺服器啟動時會呼叫一系列步驟,可以在模組中新增一個啟動步驟,RabbitMQ啟動是,會將自定義交換器新增到rabbit_registry登錄檔中。
-rabbit_boot_step({rabbit_exchange_type_rh_registry,
[{description, "recent history exchange type: registry"},
{mfa, {rabbit_registry, register,
[exchange, <<"x-recent-history">>,
?MODULE]}}, //註冊自定義交換器
{requires, rabbit_registry},
{enables, kernel_ready}]}).
複製程式碼
以上,自定義交換器就完成了,可以編寫程式進行驗證。
require_once('../lib/php-amqplib/amqp.inc');
define('HOST', 'localhost');
define('PORT', 5672);
define('USER', 'guest');
define('PASS', 'guest');
define('VHOST', '/');
$exchange = 'rh-exchange';
$conn = new AMQPConnection(HOST, PORT, USER, PASS, VHOST);
$ch = $conn->channel();
$ch->exchange_declare($exchange,
'x-recent-history', //使用自定義交換器
false,
true,
false);
複製程式碼
歡迎掃描下方二維碼,關注我的個人微信公眾號,分享我的工作、學習和生活 ~