schedule_and_build_instances()函数对应的服务端的代码在文件nova/conductor/manager.py中的类ComputeTaskManager中,现在分析一下类ComputeTaskManager中的函数如何成为服务端的函数。
在文件./nova/cmd/conductor.py中定义了一个main()函数,这个函数在和在./nova/cmd/目录中其它的文件中定义的main函数一样,是入口函数,在项目的启动的时候就执行,./nova/cmd/conductor.py文件中main()函数的定义如下:
def main():
config.parse_args(sys.argv)
logging.setup(CONF, "nova")
utils.monkey_patch()
objects.register_all()
objects.Service.enable_min_version_cache()
gmr.TextGuruMeditation.setup_autorun(version)
server = service.Service.create(binary='nova-conductor',
topic=CONF.conductor.topic)
workers = CONF.conductor.workers or processutils.get_worker_count()
service.serve(server, workers=workers)
service.wait()
main()函数调用service.Service.create()创建一个Service类对象,这里的'nova-conductor'对应的类为nova.conductor.manager.ConductorManager,即在文件./nova/conductor/manager.py中定义的类ConductorManager,
SERVICE_MANAGERS = {
'nova-compute': 'nova.compute.manager.ComputeManager',
'nova-console': 'nova.console.manager.ConsoleProxyManager',
'nova-consoleauth': 'nova.consoleauth.manager.ConsoleAuthManager',
'nova-conductor': 'nova.conductor.manager.ConductorManager',
'nova-metadata': 'nova.api.manager.MetadataManager',
'nova-scheduler': 'nova.scheduler.manager.SchedulerManager',
'nova-cells': 'nova.cells.manager.CellsManager',
}
service.Service.create()函数的定义在文件./nova/service.py文件中,功能为创建一个Service类对象,并设置默认的线程数为1000,Service类中包含的变量如下所示:
self.host = host
self.binary = binary
self.topic = topic
self.manager_class_name = manager
self.servicegroup_api = servicegroup.API()
manager_class = importutils.import_class(self.manager_class_name)
self.manager = manager_class(host=self.host, *args, **kwargs)
self.rpcserver = None
self.report_interval = report_interval
self.periodic_enable = periodic_enable
self.periodic_fuzzy_delay = periodic_fuzzy_delay
self.periodic_interval_max = periodic_interval_max
self.saved_args, self.saved_kwargs = args, kwargs
self.backdoor_port = None
创建了Service类对象server后,main()函数调用service.serve(server, workers=workers)函数启动server服务,serve()函数的定义在文件./nova/service.py中,代码如下:
def serve(server, workers=None):
global _launcher
if _launcher:
raise RuntimeError(_('serve() can only be called once'))
_launcher = service.launch(CONF, server, workers=workers,
restart_method='mutate')
serve()函数调用文件./oslo_service/service.py中定义的launch()函数,代码如下:
def launch(conf, service, workers=1, restart_method='reload'):
"""Launch a service with a given number of workers.
:param conf: an instance of ConfigOpts
:param service: a service to launch, must be an instance of
:class:`oslo_service.service.ServiceBase`
:param workers: a number of processes in which a service will be running
:param restart_method: Passed to the constructed launcher. If 'reload', the
launcher will call reload_config_files on SIGHUP. If 'mutate', it will
call mutate_config_files on SIGHUP. Other values produce a ValueError.
:returns: instance of a launcher that was used to launch the service
"""
if workers is not None and workers <= 0:
raise ValueError(_("Number of workers should be positive!"))
if workers is None or workers == 1:
launcher = ServiceLauncher(conf, restart_method=restart_method)
else:
launcher = ProcessLauncher(conf, restart_method=restart_method)
launcher.launch_service(service, workers=workers)
return launcher
launch()函数最终调用./oslo_service/service.py中类Services定义的add()函数,代码如下:
def add(self, service):
"""Add a service to a list and create a thread to run it.
:param service: service to run
"""
self.services.append(service)
self.tg.add_thread(self.run_service, service, self.done)
add()函数创建一个线程,执行run_service(),该函数调用service.start(),service.start()函数的在./nova/service.py文件中的类Serivce中定义,核心代码如下:
def start(self):
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)
serializer = objects_base.NovaObjectSerializer()
self.rpcserver = rpc.get_server(target, endpoints, serializer)
self.rpcserver.start()
messaging.Target(topic=self.topic, server=self.host)定义了一个接收rpc调用的服务端,类Target的定义在文件./oslo_messaging/target.py中,在这里,endpoints中的self.manager为./nova/conductor/manager.py文件中定义的类ConductorManager,self.manager.service_name为“conductor”,additional_endpoints为类ComputeTaskManager。serializer与信息传输中的序列化有关,rpc.get_server(target, endpoints, serializer)最终调用的代码为./oslo_messaging/rpc/server.py文件中的get_rpc_server()函数,代码如下:
def get_rpc_server(transport, target, endpoints,
executor='blocking', serializer=None, access_policy=None):
dispatcher = rpc_dispatcher.RPCDispatcher(endpoints, serializer,
access_policy)
return RPCServer(transport, target, dispatcher, executor)
这里的transport变量与上一篇中客户端的描述中的transport变量是同一个,dispatcher与消息下发有关,稍后再分析,该函数主要是创建一个RPCServer类对象。
self.rpcserver.start()即调用RPCServer类的start()函数,该函数的主要功能是最终调用文件./oslo_messaging/server.py中类MessageHandlingServer的start()函数,MessageHandlingServer类为RPCServer类的父类,核心代码如下:
@ordered(reset_after='stop')
def start(self, override_pool_size=None):
try:
self.listener = self._create_listener()
except driver_base.TransportDriverError as ex:
raise ServerListenError(self.target, ex)
self.listener.start(self._on_incoming)
self._create_listener()最终调用_driver.listen()创建一个网络监听,这里的_driver与上一篇中客户端中的driver是同一个,默认为rabbitmq。self.listener.start(self._on_incoming)启动这个监听,并设置消息的处理函数为self._on_incoming()函数。
至此,服务端的监听程序启动了。