RPC機制之AMQP協議
Openstack 的主要組件有 Nova、Cinder、Neutron、Glance 等,分別負責雲平臺的計算、存儲、網絡資源管理。OpenStack 各組件之間是通過 REST 接口進行相互通信,而各組件內部則采用了RPC通信。
什麽是RPC
RPC即Remote Procedure Call(遠程方法調用),是Openstack中一種用來實現跨進程(或者跨機器)的通信機制。Openstack中同項目內(如nova, neutron, cinder…)各服務(service)均通過RPC實現彼此間通信。Openstack中還有另外兩種跨進程的通信方式:數據庫和Rest API
Openstack中服務主要以進程的形式實現。也可以以線程的形式實現,但是Python中的線程是協作模型,無法發揮系統中多CPU(或多CPU核心)的能力。RCP只定義了一個通信接口,其底層的實現可以各不相同。目前Openstack中的主要采用AMQP的實現滿足組件內部的松耦合性。
什麽是AMQP
AMQP即Advanced Message Queuing Protocol()是一種基於隊列的可靠消息服務協議,具體可參考http://en.wikipedia.org/wiki/Advanced_Message_Queuing_Protocol。作為一種通信協議,AMQP同樣存在多個實現,如Apache Qpid、RabbitMQ、ZeroMQ等。
AMQP模型
AMQP概念
AMQP 是一個定義了在應用或者組織之間傳送消息的協議的開放標準 (an open standard for passing business messages between applications or organizations),它最新的版本是 1.0。AMQP 目標在於解決在兩個應用之間傳送消息存在的下列問題:
網絡是不可靠的 =>消息需要保存後再轉發並有出錯處理機制
與本地調用相比,網絡速度慢 =>得異步調用
應用之間是不同的(比如不同語言實現、不同操作系統等) =>得與應用無關
應用會經常變化 =>同上
AMQP 使用異步的、應用對應用的、二進制數據通信來解決這些問題。
Publisher:消息發送者,將消息發送到Exchange並指明Routing Key,以便Message Queue可以正確的收到消息
Exchange:交換器,從Producer接受消息, 根據Bindings中配置的Routing key, 把消息分派到對應的Message Queue中
Routing key:路由鍵,用於Exchange判斷哪些消息需要發送對應的Message Queue
Bindings: 描述了Exchange和Queue之間的關系。Exchange 根據消息內容 (routing key), 和Binding配置來決定把消息分派到哪個Queue中
Message Queue: 存儲消息, 並把消息傳遞給最終的 Consumer
Consumer:消息接受者,從Message Queue獲取消息,一個Consumer可以訂閱多個Queue, 來接受Queue中的消息
AMQP 定義了三種類型的 Exchange,不同類型 Exchange 實現不同的 routing 算法:
Direct Exchange:Point-to-Point 消息模式,消息點對點的通信模式,Direct Exchange 根據 Routing Key 進行精確匹配,只有對應的 Message Queue 會接受到消息
Topic Exchange:Publish-Subscribe(Pub-sub)消息模式,Topic Exchange 根據 Routing Key 進行模式匹配,只要符合模式匹配的 Message Queue 都會收到消息
Fanout Exchange:廣播消息模式,Fanout Exchange 將消息轉發到所有綁定的 Message Queue
AMQP模型
AMQP工作原理:
消息發布者Publisher將Message發送給Exchange並且說明Routing Key。Exchange 負責根據 Message 的Routing Key和binding 的Message Queue進行路由,將 Message 正確地轉發給相應的 Message Queue。監聽在 Message Queue 上的 Consumer 將會從 Queue 中讀取消息。
Routing Key 是 Exchange 轉發信息的依據,因此每個消息都有一個 Routing Key 表明可以接受消息的目的地址,而每個 Message Queue 都可以通過將自己想要接收的 Routing Key 告訴 Exchange 進行 binding,這樣 Exchange 就可以將消息正確地轉發給相應的 Message Queue。
下面的圖顯示了整體AMQP模型:
Server就是中間件服務器:它是一個接受消息的數據服務器,並主要做兩件事情,依據條件將消息路由給不同的消費者,當消費者消費速度不夠快時,它會把消息緩存在內存或磁盤上。
在AMQP之前的服務器中,它們會通過實現了特定類型路由和緩存的龐大引擎來完成. AMQ模塊使用較小的模塊結合更多樣和穩健的方案來實現. 它把這些任務分成了兩個不同角色:
交換器, 它接受來自生產者的消息並將它們路由到消息隊列
消息隊列, 它存儲消息消息並把它們轉發給消費者應用程序
在交換器和消息隊列之間有一個明顯的界面,稱為綁定(binding)。
消息流
下面的圖展示了通過AMQ模塊服務器的消息流:
一個AMQP消息由一組屬性和不透明的內容組成。一個新消息是由生產者應用程序通過使用AMQP client API來創建的.生產者將“內容”附著在消息中,並對其設置一些消息“屬性”。生產者使用路由信息來標記消息,其表面上類似於地址,但幾乎可以創建任何模式。然後,生產者將消息發送到服務器上的交換器中。
當消息到達服務器時,交換器通常會將消息路由到一級存在於服務器上的消息隊列中.如果消息不能路由,交換器會默默地丟棄或者將其返回給生產者. 生產者可以選擇如何來處理未路由消息。
單個消息可存在於多個消息隊列. 服務器可以不同方式進行處理,如通過拷貝消息或通過引用計數器等. 這不影響互操作性。然而,當一個消息被路由到多個消息隊列時,它在每個消息隊列上都是一樣的。沒有獨特的標識符來區分不同的副本。
當消息到達消息隊列時,消息隊列會通過AMQP,立即嘗試將消息傳遞給消費者應用程序.如果不行,消息隊列會存儲消息(按發布者要求存儲在內存或磁盤中),並等待消費者準備好.如果沒有消費者,消息隊列通過AMQP將消息返回給生產者(再次地,如果生產者對此有要求的話)。
當消息隊列把消息投遞給消費者後,它會從內部緩沖區中刪除消息.這有可能立即發生,也有可能在消費者應答它已成功處理之後刪除.消費者可選擇如何以及何時來應答消息.同樣地, 消費者也可以拒絕消息(一個否定應答)。
生產者消息和消費者應答可以組成事務. 當一個應用程序同時扮演兩種角色時,通常它會做混合工作:發送消息和發送應答,然後提交或回滾事務。
從服務器投遞消息給消費者,這個過程不是事務的,它只能通過消息應答來處理。
交換器Exchange功能說明
交換器是一個虛擬主機內的消息路由代理。交換器實例(我們通常稱之為“交換器”)接受消息和路由信息-主要是一個路由鍵-或者將消息傳遞到消息隊列,或到內部服務。交換器是基於每個虛擬主機命名的。
應用程序可以在權限範圍內自由地創建、共享、使用和銷毀交換器實例。交換器可能是持久的、臨時的或自動刪除的。持久化的交換器會持續到他們被刪除,臨時的交換器會持續到服務器關閉。自動刪除的交換器直到他們不再使用。服務器提供了一組特定的交換器類型。每個交換器類型都實現了一個特定的匹配和算法,如下一節中定義的。AMQP只要求少量的交換器類型,並推薦了一些。此外,每個服務器實現可以添加自己的交換類型。
交換器可以將單個消息並發地路由到的消息隊列中。這將創建一個獨立消息的多個實例。
Direct交換器類型
direct 交換器按如下方式來工作:
1. 消息隊列使用路由鍵K來綁定交換器
2. 發布者使用路由鍵R來向交換器發送消息
3. 在K=R時,消息會傳遞到消息隊列中
Direct 類似於我們生活中的快遞, 填寫對方的地址, 郵局會根據唯一地址, 來投遞郵件。
1) [Producer] 在消息體中, 填寫 Routing key
2) [Exchange] 根據Routing key, 在 Binding 中查找和Routing key綁定的 Queue
3) [Exchange] 發送消息到Queue
Topic交換器類型
topic交換器類型按如下方式來工作:
1. 消息隊列使用路由模式P來綁定到交換器
2. 發布者使用路由鍵R來向交換器發送消息
3. 當R匹配P時,消息將被傳遞到消息隊列
用於topic交換器的路由鍵必須由0個或多個由點號.分隔的單詞組成。每個單詞必須包含字母A-Z和a-z 以及數字0-9。路由模式與路由鍵遵循相同的規則,* 用於匹配單個單詞,# 用於匹配0個或多個單詞。
因此路由模式*.stock.# 會匹配路由鍵usd.stock 和eur.stock.db 但不匹配stock.nasdaq。
Topic Exchange 和Direct Exchange比較類似, 但是Topic Exchange支持模糊匹配 (#, * 等等)。
Topic 類似於我們生活中的報刊訂閱. 使用關鍵字”體育”訂閱雜誌後, 郵局會把”體育周刊” 和”體育日報” 都發送給你。
1) [Producer] 在消息體中, 填寫 Routing key
2) [Exchange] 根據Routing key, 在 Binding 中, 通過模糊匹配, 查找和Routing key綁定的 Queue
3) [Exchange] 發送消息到Queue
Fanout 交換器類型
fanout交換器類型按如下方式來工作:
1. 消息隊列不使用參數來綁定交換器
2. 發布者向交換器發送消息
3. 消息無條件傳遞給消息隊列
Fanout Exchange 不需要任何 Routing key
Fanout 類似於我們生活中的廣播. 任何人無需訂閱, 都可以收聽到
Fanout Exchange 接收到消息之後, 會把消息發送給所有綁定的Queue中
測試
發現一個很好玩的網站,上面提供在線RabbitMQ 模擬器,可以幫助理解Exchange/queue/binding概念。
http://tryrabbitmq.com/
按照規則配置好規則之後,點擊send,就可以看到數據流量走向。
RPC機制之AMQP協議