openstack學習之RPC服務實現分析
阿新 • • 發佈:2019-02-13
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物件
掌握了Service + Manager,基本上就瞭解了RPC server是如何工作的,學習openstack程式碼就比較直觀了。
其中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物件
如前所述,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程式碼就比較直觀了。