1. 程式人生 > >openstack學習之RPC服務實現分析

openstack學習之RPC服務實現分析

openstack中的服務主要有兩種:一種是rest服務,提供Rest API;一種RPC服務,提供RPC API。本文討論RPC服務的實現。Rest服務的實現在《openstack學習之各種API》有所涉及。 RPC服務其實就是一個RPC server,client(客戶)可以通過RPC API進行呼叫。以nova為例,nova中的多數服務(service)都是一個RPC server。比如nova-conductor,nova-compute,nova-consoleauth,nova-scheduler...等 實現一個rpc server需要幾個部分: 1)啟動命令程式碼 2)Service定義 3)Manager定義 4)功能實現程式碼
其中1)2)3)屬於框架性程式碼,每個rpc server的實現都差不多;4)和rpc server要實現的功能相關。 以nova為例,來分析這些部分的實現。 nova.cmd package中定義了所有服務的啟動程式碼,包括rpc server和rest api服務。api.py,api_ec2.py,api_metadata.py,api_os_compute.py是rest api服務。這個目錄中還包含了一些命令工具(utility command),如manage.py。讀者可自行檢視。 rpc server的啟動程式碼基本類似: 1)定義main 2) 載入配置檔案 3) 配置log 4) 建立server物件 5)啟動service. 步驟4的程式碼compute:     server = service.Service.create(binary='nova-compute',                                     topic=CONF.compute_topic,                                     db_allowed=CONF.conductor.use_local) 步驟4的程式碼schduler:     server = service.Service.create(binary='nova-scheduler',                                     topic=CONF.scheduler_topic) 步驟4的程式碼conductor:     server = service.Service.create(binary='nova-conductor',                                     topic=CONF.conductor.topic,                                     manager=CONF.conductor.manager) 步驟5的程式碼,3者一致     service.serve(server)     service.wait() Service物件
Service位於nova.service.py 該物件繼承於nova.openstack.common.service.py中的Service __init__方法 初始化幾個重要的成員         self.host = host         self.binary = binary         self.topic = topic         self.manager_class_name = manager 引數有啟動命令提供。host如果沒有傳入,從配置檔案讀取。host = CONF.host start方法: 該方法用來啟動rpc server。 該方法的主要功能就是建立RPC佇列並繫結到exchang上。         target = messaging.Target(topic=self.topic, server=self.host)         endpoints = [             self.manager,             baserpc.BaseRPCAPI(self.manager.service_name, self.backdoor_port)         ]         endpoints.extend(self.manager.additional_endpoints) target用來指定該rpc server監聽在哪些佇列上。
target指定了2個引數:topic和server。檢視target程式碼(olso.messaging: oslo.messaging.target.py)     :param server: Clients can request that a message be directed to a specific       server, rather than just one of a pool of servers listening on the topic.     :param topic: A name which identifies the set of interfaces exposed by a       server. Multiple servers may listen on a topic and messages will be       dispatched to one of the servers in a round-robin fashion. 底層如何使用target建立RPC佇列並繫結到exchang上,可以檢視程式碼 transport._listen   self._driver.listen(target) amqpdriver.listen   conn.declare_topic_consumer(target.topic, listener)   conn.declare_topic_consumer('%s.%s' % (target.topic, target.server),                                     listener)   conn.declare_fanout_consumer(target.topic, listener) 從程式碼中可以看到建立了3個佇列,這個3個系列用來實現《openstack學習之RPC》提到的3種RPC場景 隨機呼叫某server上的一個方法: 通過第一個佇列實現 呼叫某特定server上的一個方法: 通過第二個佇列實現,這個佇列通過server引數來唯一標識一個佇列 呼叫所有server上的一個方法:通過第三個佇列實現,exchange type為fantout型別 關於佇列的概念可以參考另一篇博文《openstack學習之RPC》 endpoints用來定義該rpc server支援哪些API。
manager中部分方法其實就是RPC API的方法,比如ComputeManager中有reboot_instance,這個方法就是一個RPC API。 client呼叫RCP API時會給出topic,方法名,方法引數等資訊。oslo.messaging中的RPCDispatch會根據這些資訊將該請求直接轉化為對manager的相應方法的呼叫,並將方法引數準備好。 還可以看到openstack會給每個rpc server加一個額外的API(BaseRPCAPI),這個API目前只有一個ping方法。openstack內部會用這個方法檢測一個服務是否已經啟動完畢,如果啟動完畢,就可以相應ping呼叫。 Service物件還提供了另外一個功能,定時任務。             self.tg.add_dynamic_timer(self.periodic_tasks,                                      initial_delay=initial_delay,                                      periodic_interval_max=                                         self.periodic_interval_max) self.periodic_tasks會呼叫manager.periodic_tasks。 綜上,Service物件的核心功能就是建立監聽佇列,並將收到的訊息轉化為對manager物件的方法呼叫。每個openstack專案實現都有定義一個自己的Service物件(如nova.service.py,cinder.service.py,neutron.service.py),這些物件的程式碼基本類似,相信後邊社群會對這些程式碼進行重構。 Manager物件

如前所述,Manager物件其實就是RPC API的入口。每個RPC API最終會轉化為對Manger相應方法的呼叫,這個方法就是該RPC API的最終實現。

每個服務都會有一個相應的Manager物件,因為一般每個服務所提供的API都是不同的。每個服務的實現都會有一個相應的python package(檔案系統中的目錄),如conductor,compute,consoleauth,scheduler等。每個package中又會有一個manager.py。這個manager.py就定義了這個服務的Manager物件。如compute.manager.py定義了ComputeManager。nova boot命令最終會呼叫這個物件中的run_instance方法。 要想進一步看懂Manager中的程式碼,就需要對相應問題領域(problem domain,也就是我們常說的業務流程)比較熟悉了。ComputeManager是處理虛擬機器生命週期的,我們要對虛擬機器有了解,才能讀懂其中的程式碼。
掌握了Service + Manager,基本上就瞭解了RPC server是如何工作的,學習openstack程式碼就比較直觀了。