1. 程式人生 > >【openstack】openstack中的訊息佇列

【openstack】openstack中的訊息佇列

openstack中的訊息佇列

更新記錄:
2013.4.28  增加版本號

版本:Essex版

1      openstack中訊息佇列的使用

nova中的每個元件都會連線訊息伺服器,一個元件可能是一個訊息傳送者(如API、Scheduler),也可能是一個訊息接收者(如compute、volume、network)。傳送訊息有兩種方式:同步呼叫rpc.call和非同步呼叫rpc.cast

openstack內部一些物件:

l  Topic Publisher:該物件在進行rpc.call或rpc.cast時建立,每個物件都會連線同一個topic型別的交換器,訊息傳送完畢後物件被回收。

l  Direct Publisher:該物件在進行rpc.call呼叫時建立,用於向訊息傳送者返回響應。該物件會根據接收到的訊息屬性連線一個direct型別的交換器。

l  Direct Consumer:該物件在進行rpc.call呼叫時建立,用於接收響應訊息。每一個物件都會通過一個的佇列連線一個direct型別的交換器(佇列和交換器以UUID命名)。

l  Topic Consumer:該物件在內部服務初始化時建立,在服務過程中一直存在。用於從佇列中接收訊息,呼叫訊息屬性中指定的函式。該物件通過一個共享佇列或一個私有佇列連線一個topic型別的交換器。每一個內部服務都有兩個topic consumer,一個用於rpc.cast呼叫(此時連線的是binding-key為“topic”的共享佇列);另一個用於rpc.call呼叫(此時連線的是binding-key為“topic.host”的私有佇列)

l  Topic Exchange:topic型別交換器,每一個訊息代理節點只有一個topic型別的交換器。

l  Direct Exchange:direct型別的交換器,存在於rpc.call呼叫過程中,對於每一個rpc.call的呼叫,都會產生該物件的一個例項。

l  Queue Element:訊息佇列。可以共享也可以私有。routing-key為“topic”的佇列會在相同型別的服務中共享(如多個compute節點共享一個routing-key為“topic”的佇列)。

各個物件的工作模型:

  

       openstack中預設使用kombu(實現AMQP協議的Python函式庫)連線RabbitMQ伺服器。訊息的收/發者都需要一個Connetion物件連線RabbitMQ伺服器。

2      訊息佇列效能影響因素

訊息佇列在openstack整個架構中扮演著至關重要(交通樞紐)的作用,正是因為openstack部署的靈活性、模組的鬆耦合、架構的扁平化,反而使openstack更加依賴於訊息佇列(不一定使用RabbitMQ,可以是其他的訊息佇列產品),所以訊息佇列收發訊息的效能和訊息佇列的HA能力直接影響openstack的效能。

在openstack中的任意時間點,影響訊息伺服器效能的的因素如下:

l  在rpc.call呼叫過程中:rpc.call的呼叫數決定了direct型別的交換器個數,相關的私有佇列個數以及監聽私有佇列的direct consumer的個數。

l  工作者執行緒(內部服務)個數:相同屬性的工作者執行緒(如compute節點)會共享一個佇列,但每一個工作者執行緒都有一個私有佇列。相同屬性的工作者執行緒個數也決定了在topic型別交換器上的routing key的個數。

在實驗環境下,主機名為kong,openstack各個元件啟動後,會建立:

Ø  Exchanges

1.      nova (topic exchange)

Ø  Queues

1.      compute.kong

2.      compute

3.      network.kong

4.      network

5.      volume.kong

6.      volume

7.      scheduler.kong

8.      scheduler

使用訊息佇列時有如下幾個(Consumer類)屬性:

Ø  Durable:該屬性決定了交換器和佇列是否持久化,如持久化,則交換器和佇列在RabbitMQ服務重啟後仍然繼續工作,否則交換器和佇列的資訊被清空。AMQP協議規定,持久化的佇列只能繫結到持久化的交換器。

Ø  Auto_delete:如果設定,則當所有佇列結束後,交換器自動刪除。預設為False。

Ø  Exclusive:佇列是否私有,如果該屬性設定,則Auto_delete屬性會自動生效。預設為False。

Ø  Auto_ack:收到訊息時是否自動傳送回執。預設是False,要求訊息接收者手動處理回執。

Ø  No_ack:如果設定會提高效能,但會降低可靠性。

Ø  Delivery_mode:訊息的傳輸型別。目前RabbitMQ支援兩種型別:

n  1或者“transient”:訊息儲存在記憶體,當伺服器宕機或重啟時訊息丟失

n  2或者“persistent”:訊息會同時在記憶體和硬碟儲存,伺服器宕機或重啟時訊息不丟失

預設為2。

在大規模部署的情況下,勢必會對單節點的RabbitMQ server造成較大的負載,一旦發生單節點故障,整個openstack服務都會癱瘓。所以,部署時可以考慮使用RabbitMQ的HA等高階部署特性,具體參見RabbitMQ相關文件,在此不再贅述。

3      程式碼驗證

3.1      服務的啟動

根據以上分析可知,nova元件服務啟動時會建立TopicConsumer,以“nova-compute”服務啟動為例,在服務的啟動過程中,會呼叫service::start()方法,在該方法中:

            3.1.1conn是什麼?

是nova.openstack.common.amqp.ConnectionContext物件,這個物件是由RPC實現類呼叫create_connection()方法建立。RPC在openstack中有四種實現:

   具體使用哪一種根據配置檔案確定,預設的配置項是:

rpc_backend=nova.rpc.impl_kombu

ConnectionContext物件包含兩個欄位:

ü  connection_pool:一個Connection物件池(繼承自eventlet.pools.Pool),用於生成Connection物件。

ü  connection:由connection_pool 生成。nova.openstack.common.rpc.impl_komku.Connection物件。該物件在初始化時,會根據配置的引數和策略連線RabbitMQ伺服器。

3.1.2     rpc_dispatcher是什麼?

RpcDispatcher物件。該物件中有屬性callbacks,是一個包含ComputeManager物件的列表。用於接收到訊息之後的處理。

3.1.3     三個create_consumer方法幹了什麼?

以第一個為例,在該函式中,建立了TopicConsumer物件。

3.1.4     consume_in_thread方法

在方法的實現裡,又藉助了evlentlet庫建立超執行緒。在超執行緒主函式中呼叫了TopicConsumer物件的consume()方法(該類沒有實現該方法,直接呼叫父類)。

 對訊息的處理包括:從訊息中獲取介面名稱、獲取介面引數、呼叫ComputeManager物件相應方法。

至此,“nova-compute”服務啟動完成。

3.2      訊息的傳送

以建立虛擬機器為例,由前幾篇文章可知,經過Scheduler模組的過濾後,將建立虛擬機器訊息傳送到對應的compute節點。

  
 cast_to_compute_host
方法的實現:


 rpc.cast最終會建立一個TopicPublisher物件,並呼叫該物件的send方法。


 由上可知,
TopicConsumer物件會向名為“nova”的exchange上, 以 “compute.host”為routing-key傳送訊息。此時訊息會發送到在名為“compute.host”佇列上監聽的TopicConsumer物件。