在西方有一句諺語,叫做“Don’t Reinvent the Wheel!”。直譯過來就是不要在重新發明輪子了。也就是說我們應該避免做一些重複性的工作,如果一個東西別人已經做過了,那麼我們拿來直接用就行了,沒有必要重新制作,這一點在軟件開發裏尤爲突出。所以在OpenStack的開發中也借鑑了這一思想,OpenStack利用了大量的現有庫,這加快了OpenStack的開發,使得開發人員可以集中精力研究難點。下面我們就來一起討論一下OpenStack的通用技術。
一、消息總線
OpenStack的設計原則:項目之間通過RESTful API進行通信;項目內部通過,不同服務進程之間通過消息總線進行通訊。這種設計思想保證了各個項目對外可以被不同類型的客戶端接受,同時也保證了內部項目通信接口的可擴展性和可靠性,以支持大規模的部署。
軟件的開發經歷了三個階段,從最初的面向過程到面向對象,然後再到面向服務。在面向服務的軟件開發中,我們需要考慮的就是如何保持各個服務之間的通信。這裏OpenStack借鑑了計算機硬件總線的思想,引入了消息總線。一些服務向總線上發送消息,另一些服務從總線上獲取獲取消息。
OpenStack利用開源庫實現了以下兩種類型的用於在內部服務進行之間的通訊。
(1)事件通知
某個服務進程可以把事件通知發送到消息總線上,該消息總線上所有對此類事件感興趣的服務進程,都可以獲得此事件通知並進行進一步的處理,但是處理的結果不會返回給事件發送者。
(2)遠程過程調用(RPC)
通過遠程調用,一個服務進程可以調用其他遠程服務進程的方法,並且有阻塞和非阻塞兩種方式。
OpenStack已經支持了一些常見的消息總線,如下表。
名稱 | 特點 |
---|---|
RabbitMQ | 實現了AMQP的消息中間件服務,支持多種協議網關和編程語言 |
Qpid | Apache基金會下的頂層項目,實現了AMQP協議 |
ZeroMQ | 開源的高性能異步消息庫,可以在沒有Server/Broker的情況下工作 |
二、AMQP的實現原理
OpenStack所支持的消息總線類型中(上表),大部分是基於AMQP(Advanced Message Queuing Protocol)的,AMQP是一個異步消息傳遞所使用的開放的應用層協議規範,主要包括了消息的導向、隊列、路由、可靠性和安全性。下面我們來詳細的學習一下AMQP的原理。
如上圖所示,AMQP的主要參與者有以下幾個:
- Producer:消息的產生者
- Comsumer:消息的接收者
- Exchange:交換部件,根據消息的條件選擇不同的消息接收者。
- Queue:消息隊列,暫時緩存到達消費者的消息
- Server/Broker:實現了AMQP的中間件服務
消息的傳遞過程:
1、產生
生產者服務器進程產生消息,消息是由消息頭和消息體組成的,消息頭指定了消息的接收條件,即哪些接收者可以接收這條消息。
2、交換(路由)
Exchange部件類似於網絡中的路由器,負責將消息轉發到合適的接收者那裏。在Exchange有一張表格,類似於路由表。在這張表中存放了所有的Queue的binding key,binding key的作用就是表示這個queue可以接收那些類型的消息。同時每一個消息頭中都攜帶着一個routing key,表示這條消息可以被那些Queue接收。當一條消息到達Exchange時,Exchange會遍歷這張表格,如果一個Queue的bing key與消息的routing key相匹配,那麼就將消息轉發到這個Queue。Exchange與路由器一樣,通過通配符也可以支持多播(組播)和廣播。
3、緩存
Queue是接收者的緩存部件,是爲了防止消費者無法接收消息,或者接收消息的速度不夠快時消息不會被新到的消息覆蓋。Queue會把消息緩存在內存或磁盤上。
三、基於AMQPRPC的實現原理
消息發送過程:
1、客戶端發送一個請求消息給Exchange,指定routing key爲”op_queue“,同時指明一個消息隊列名用來獲取響應,圖中爲“res_queue”。
2、Exhange把此消息轉發到消息隊列op_queue。
3、消息隊列op_queue把消息推送到服務端,服務端執行此RPC調用對應的任務。執行結束後,服務端把響應的結果發送給消息隊列,指明routing key爲”res_queue“。
4、Exchange把此消息轉發到消息隊列res_queue。
5、客戶端從消息隊列res_queue中獲取響應。