天天看點

openstack分析——NOVA中的RabbitMQ解析

轉載自:http://blog.csdn.net/gaoxingnengjisuan

相關文章:

http://blog.csdn.net/gaoxingnengjisuan/article/category/1461395/2

    本篇文章是由本人閱讀NOVA源碼過程中的心得、RabbitMQ的官方文檔以及網上的一些資料整理總結而成的,也為了友善以後對這部分内容的複習。

    NOVA是OpenStack系統的核心子產品,主要負責虛拟機執行個體的生命周期管理、網絡管理(前幾個版本)、存儲卷管理(前幾個版本)、使用者管理以及其他相關雲平台管理功能,在能力上類似于Amazon EC2和Rackspace Cloud Servers。

   消息隊列(Queue)與資料庫(Database)作為Nova總體架構中的兩個重要組成部分,二者通過系統内消息傳遞和資訊共享的方式實作任務之間、子產品之間、接口之間的異步部署,在系統層面大大簡化了複雜任務的排程流程與模式,是整個OpenStack Nova系統的核心功能子產品。終端使用者(DevOps、Developers和其他OpenStack元件)主要通過Nova API實作與OpenStack系統的互動,同時Nova守護程序之間通過消息隊列和資料庫來交換資訊以執行API請求,完成終端使用者的雲服務請求。

    Nova采用無共享、基于消息的靈活架構,意味着Nova的元件有多種安裝方式,可以将每個Nova-Service子產品單獨安裝在一台伺服器上,同時也可以根據業務需求将多個子產品組合安裝在多台伺服器上。

1.RabbitMQ

    OpenStack Nova系統目前主要采用RabbitMQ作為資訊交換中樞。

    RabbitMQ是一種處理消息驗證、消息轉換和消息路由的架構模式,它協調應用程式之間的資訊通信,并使得應用程式或者軟體子產品之間的互相意識最小化,有效實作解耦。

    RabbitMQ适合部署在一個拓撲靈活易擴充的規模化系統環境中,有效保證不同子產品、不同節點、不同程序之間消息通信的時效性;而且,RabbitMQ特有的叢集HA安全保障能力可以實作資訊樞紐中心的系統級備份,同時單節點具備消息恢複能力,當系統程序崩潰或者節點當機時,RabbitMQ正在處理的消息隊列不會丢失,待節點重新開機之後可根據消息隊列的狀态資料以及資訊資料及時恢複通信。

    RabbitMQ在功能性、時效性、安全可靠性以及SLA方面的出色能力可有效支援OpenStack雲平台系統的規模化部署、彈性擴充、靈活架構以及資訊安全的需求。

2.AMQP

    AMQP是應用層協定的一個開放标準,為面向消息的中間件而設計,其中RabbitMQ是AMQP協定的一個開源實作,OpenStack Nova各軟體子產品通過AMQP協定實作資訊通信。AMQP協定的設計理念與資料通信網絡中的路由協定非常類似,可歸納為基于狀态的面向無連接配接通信系統模式。不同的是,資料通信網絡是基于通信鍊路的狀态決定用戶端與服務端之間的連結,而AMQP是基于消息隊列的狀态決定消息生産者與消息消費者之間的連結。對于AMQP來講,消息隊列的狀态資訊決定通信系統的轉發路徑,連結兩端之間的鍊路并不是專用且永久的,而是根據消息隊列的狀态與屬性實作資訊在RabbitMQ伺服器上的存儲與轉發,正如資料通信網絡的IP資料包轉發機制,所有的路由器是基于通信鍊路的狀态而形成路由表,IP資料包根據路由表實作封包的本地存儲與逐級轉發,二者在實作機制上具有異曲同工之妙。

    AMQP的目标是實作端到端的資訊通信,那麼必然涉及兩個基本的概念:AMQP實作通信的因素是什麼以及AMQP實作通信的實體以及機制是什麼。

    AMQP是面向消息的一種應用程式之間的通信方法,也就是說,“消息”是AMQP實作通信的基本因素。AMQP有兩個核心要素——交換器(Exchange)與隊列(Queue)通過消息的綁定與轉發機制實作資訊通信。其中,交換器是由消費者應用程式建立,并且可與其他應用程式實作共享服務,其功能與資料通信網絡中的路由器非常相似,即接收消息之後通過路由表将消息準确且安全的轉發至相應的消息隊列。一台RabbitMQ伺服器或者由多台RabbitMQ伺服器組成的叢集可以存在多個交換器,每個交換器通過唯一的Exchange ID進行識别。

    交換器根據不同的應用程式的需求,在生命周期方面也是靈活可變的,主要分為三種:持久交換器、臨時交換器與自動删除交換器。持久交換器是在RabbitMQ伺服器中長久存在的,并不會因為系統重新開機或者應用程式終止而消除,其相關資料長期駐留在硬碟之上;臨時交換器駐留在記憶體中,随着系統的關閉而消失;自動删除交換器随着宿主應用程式的中止而自動消亡,可有效釋放伺服器資源。

    隊列也是由消費者應用程式建立,主要用于實作存儲與轉發交換器發送來的消息,隊列同時也具備靈活的生命周期屬性配置,可實作隊列的持久儲存、臨時駐留與自動删除。

    由以上可以看出,消息、隊列和交換器是構成AMQP的三個關鍵元件,任何一個元件的實效都會導緻資訊通信的中斷,是以鑒于三個關鍵元件的重要性,系統在建立三個元件的同時會打上“Durable”标簽,表明在系統重新開機之後立即恢複業務功能。

    以上主要介紹構成AMQP的三個關鍵要素,那麼它們之間是如何工作的呢?

openstack分析——NOVA中的RabbitMQ解析

    由圖中可以看出,交換器接收發送端應用程式的消息,通過設定的路由轉發表與綁定規則将消息轉發至相比對的消息隊列,消息隊列繼而将接收到的消息轉發至對應的接收端應用程式。資料通信網絡通過IP位址形成的路由表實作IP封包的轉發,在AMQP環境中的通信機制也非常類似,交換器通過AMQP消息頭(Header)中的路由選擇關鍵字(Routing Key)而形成的綁定規則(Binding)來實作消息的轉發,也就是說,“綁定”即連接配接交換機與消息隊列的路由表。消息生産者發送的消息中所帶有的Routing Key是交換器轉發的判斷因素,也就是AMQP中的“IP位址”,交換器擷取消息之後提取Routing Key觸發路由,通過綁定規則将消息轉發至相應隊列,消息消費者最後從隊列中擷取消息。AMQP定義三種不同類型的交換器:廣播式交換器(Fanout Exchange)、直接式交換器(Direct Exchange)和主題式交換器(Topic Exchange),三種交換器實作的綁定規則也有所不同。

3.Nova中的RabbitMQ應用

3.1RabbitMQ在Nova中的實作

    RabbitMQ是OpenStackNova系統的資訊中樞,目前Nova中的各個子產品通過RabbitMQ伺服器以RPC(遠端過程調用)的方式實作通信,而且各子產品之間形成松耦合關聯關系,在擴充性、安全性以及性能方面均展現優勢。由前文可知,AMQP的交換器有三種類型:Direct、Fanout和Topic,而且消息隊列是由消息消費者根據自身的功能與業務需求而生成。

    首先說說三個比較重要的概念:

   交換器:

    接受消息并且将消息轉發給隊列。在每個尋你主機的内部,交換器有唯一對應的名字。應用程式在他的權限範圍之内可以建立、删除、使用 和共享交換器執行個體。交換器可以是持久的,臨時的或者自動删除的。持久的交換器會一直存在于Server端直到他被顯示的删除;臨時交換器在伺服器關閉時停 止工作;自動删除的交換器在沒有應用程式使用它的時候被伺服器删除。

   隊列:

    “消息隊列”,它是一個具名緩沖區,它代表一組消費者應用程式儲存消息。這些應用程式在它們的權限範圍内可以建立、使用、共享消息隊列。類似于交換器,消息隊列也可以是持久的,臨時的或者自動删除的。臨時消息隊列在伺服器被關閉時停止工作;自動删除隊列在沒有應用程式使用它的時候被伺服器自動删 除。消息隊列将消息儲存在記憶體、硬碟或兩者的組合之中。消息隊列儲存消息,并将消息發給一個或多個用戶端,特别的消息隊列會跟蹤消息的擷取情況,消息要出對就必須被擷取,這樣可以阻止多個用戶端同時消費同一條消息的情況發生,同時也可以被用來做單個隊列多個消費者之間的負載均衡。

   綁定:

    可以了解為交換器和消息隊列之間的一種關系,綁定之後交換器會知道應該把消息發給那個隊列,綁定的關鍵字稱為binding_key。在程式中我們這樣使用:

    channel.queue_bind(exchange='direct_logs',queue=queue_name,routing_key=binding_key)

    Exchange和Queue的綁定可以是多對多的關系,每個發送給Exchange的消息都會有一個叫做routing_key的關鍵字,交換器要想把消息發送給某個特定的隊列,那麼該隊列與交換器的binding_key必須和消息的routing_key相比對才OK。

    介紹一下RabbitMQ的三種類型的交換器:

   廣播式交換器類型(fanout)

    該類交換器不分析所接收到消息中的Routing Key,預設将消息轉發到所有與該交換器綁定的隊列中去。廣播式交換器轉發效率最高,但是安全性較低,消費者應用程式可擷取本不屬于自己的消息。

    廣播交換器是最簡單的一種類型,就像我們從字面上了解到的一樣,它把所有接受到的消息廣播到所有它所知道的隊列中去,不論消息的關鍵字是什麼,消息都會被路由到和該交換器綁定的隊列中去。

    它的工作方式如下圖所示:

openstack分析——NOVA中的RabbitMQ解析

    在程式中申明一個廣播式交換器的代碼如下:

    channel.exchange_declare(exchange='fanout',type='fanout')

   直接式交換器類型(direct)

    該類交換器需要精确比對Routing Key與BindingKey,如消息的Routing Key = Cloud,那麼該條消息隻能被轉發至Binding Key = Cloud的消息隊列中去。直接式交換器的轉發效率較高,安全性較好,但是缺乏靈活性,系統配置量較大。

    相對廣播交換器來說,直接交換器可以給我們帶來更多的靈活性。直接交換器的路由算法很簡單——一個消息的routing_key完全比對一個隊列的 binding_key,就将這個消息路由到該隊列。綁定的關鍵字将隊列和交換器綁定到一起。當消息的routing_key和多個綁定關鍵字比對時消息 可能會被發送到多個隊列中。

    我們通過下圖來說明直接交換器的工作方式:

openstack分析——NOVA中的RabbitMQ解析

    如圖:Q1,Q2兩個隊列綁定到了直接交換器X上,Q1的binding_key是“orange”,Q2有兩個綁定,一個binding_key是black,另一個binding_key是green。在這樣的關系下,一個帶有 “orange” routing_key的消息發送到X交換器之後将會被X路由到隊列Q1,一個帶有 “black” 或者 “green”  routing_key的消息發送到X交換器之後将會被路由到Q2。而所有其他消息将會被丢失掉。

   主題式交換器(Topic Exchange)

    該類交換器通過消息的Routing Key與Binding Key的模式比對,将消息轉發至所有符合綁定規則的隊列中。Binding Key支援通配符,其中“*”比對一個詞組,“#”比對多個詞組(包括零個)。例如,Binding Key=“*.Cloud.#”可轉發Routing Key=“OpenStack.Cloud.GD.GZ”、“OpenStack.Cloud.Beijing”以及“OpenStack.Cloud”的消息,但是對于Routing Key=“Cloud.GZ”的消息是無法比對的。

openstack分析——NOVA中的RabbitMQ解析

    這裡的routing_key可以使用一種類似正規表達式的形式,但是特殊字元隻能是“*”和“#”,“*”代表一個單詞,“#”代表0個或是多個單詞。這樣發送過來的消息如果符合某個queue的routing_key定義的規則,那麼就會轉發給這個queue。

   在Nova中主要實作Direct和Topic兩種交換器的應用,在系統初始化的過程中,各個子產品基于Direct交換器針對每一條系統消息自動生成多個隊列注入RabbitMQ伺服器中,依據Direct交換器的特性要求,Binding Key=“MSG-ID”的消息隊列隻會存儲與轉發Routing Key=“MSG-ID”的消息。同時,各個子產品作為消息消費者基于Topic交換器自動生成兩個隊列注入RabbitMQ伺服器中。

    Nova各個子產品之間基于AMQP消息實作通信,但是真正實作消息調用的應用流程主要是RPC機制。Nova基于RabbitMQ實作兩種RPC調用:RPC.CALL和RPC.CAST,其中RPC.CALL基于請求與響應方式,RPC.CAST隻是提供單向請求,兩種RPC調用方式在Nova中均有不同的應用場景。

    Nova的各個子產品在邏輯功能是可以劃分為兩種:Invoker和Worker,其中Invoker子產品主要功能是向消息隊列中發送系統請求消息,如Nova-API和Nova-Scheduler;Worker子產品則從消息隊列中擷取Invoker子產品發送的系統請求消息以及向Invoker子產品回複系統響應消息,如Nova-Compute、Nova-Volume和Nova-Network。Invoker通過RPC.CALL和RPC.CAST兩個程序發送系統請求消息;Worker從消息隊列中接收消息,并對RPC.CALL做出響應。Invoker、Worker與RabbitMQ中不同類型的交換器和隊列之間的通信關系如圖所示。

openstack分析——NOVA中的RabbitMQ解析

    Nova根據Invoker和Worker之間的通信關系可邏輯劃分為兩個交換域:Topic交換域與Direct交換域,兩個交換域之間并不是嚴格割裂,在資訊通信的流程上是深度嵌入的關系。Topic交換域中的Topic消息生産者(Nova-API或者Nova-Scheduler)與Topic交換器生成邏輯連接配接,通過PRC.CALL或者RPC.CAST程序将系統請求消息發往Topic交換器。Topic交換器根據系統請求消息的Routing Key分别送入不同的消息隊列進行轉發,如果消息的Routing Key=“NODE-TYPE.NODE-ID”,則将被轉發至點對點消息隊列;如果消息的Routing Key=“NODE-TYPE”,則将被轉發至共享消息隊列。Topic消息消費者探測到新消息已進入響應隊列,立即從隊列中接收消息并調用執行系統消息所請求的應用程式。每一個Worker都具有兩個Topic消息消費者程式,對應點對點消息隊列和共享消息隊列,連結點對點消息隊列的Topic消息消費者應用程式接收RPC.CALL的遠端調用請求,并在執行相關計算任務之後将結果以系統響應消息的方式通過Direct交換器回報給Direct消息消費者;同時連結共享消息隊列的Topic消息消費者應用程式隻是接收RPC.CAST的遠端調用請求來執行相關的計算任務,并沒有響應消息回報。是以,Direct交換域并不是獨立運作,而是受限于Topic交換域中RPC.CALL的遠端調用流程與結果,每一個RPC.CALL激活一次Direct消息交換的運作,針對每一條系統響應消息會生成一組相應的消息隊列與交換器組合。是以,對于規模化的OpenStack雲平台系統來講,Direct交換域會因大量的消息處理而形成整個系統的性能瓶頸點。

3.2Nova系統RPC.CALL以及RPC.CAST調用流程

    由前文可以看出,RPC.CALL是一種雙向通信流程,即Worker程式接收消息生産者生成的系統請求消息,消息消費者經過處理之後将系統相應結果回報給Invoker程式。

    例如,一個使用者通過外部系統将“啟動虛拟機”的需求發送給NOVA-API,此時NOVA-API作為消息生産者,将該消息包裝為AMQP資訊以RPC.CALL方式通過Topic交換器轉發至點對點消息隊列,此時,Nova-Compute作為消息消費者,接收該資訊并通過底層虛拟化軟體執行相應虛拟機的啟動程序;待使用者虛拟機成功啟動之後,Nova-Compute作為消息生産者通過Direct交換器和響應的消息隊列将“虛拟機啟動成功”響應消息回報給Nova-API,此時Nova-API作為消息消費者接收該消息并通知使用者虛拟機啟動成功,一次完整的虛拟機啟動的RPC.CALL調用流程結束。其具體流程如圖所示:

openstack分析——NOVA中的RabbitMQ解析

    (1)Invoker端生成一個Topic消息生産者和一個Direct消息消費者。其中,Topic消息生産者發送系統請求消息到Topic交換器;Direct消息消費者等待響應消息。

    (2)Topic交換器根據消息的Routing Key轉發消息,Topic消費者從相應的消息隊列中接收消息,并傳遞給負責執行相關任務的Worker。

    (3)Worker根據請求消息執行完任務之後,配置設定一個Direct消息生産者,Direct消息生産者将響應消息發送到Direct交換器。

    (4)Direct交換器根據響應消息的Routing Key轉發至相應的消息隊列,Direct消費者接收并把它傳遞給Invoker。

    RPC.CAST的遠端調用流程與RPC.CALL類似,隻是缺少了系統消息響應流程。一個Topic消息生産者發送系統請求消息到Topic交換器,Topic交換器根據消息的Routing Key将消息轉發至共享消息隊列,與共享消息隊列相連的所有Topic消費者接收該系統請求消息,并把它傳遞給響應的Worker進行處理,其調用流程如圖所示:

openstack分析——NOVA中的RabbitMQ解析

繼續閱讀