nova源码分析--rpc(2)

本文详细分析了Nova中ComputeTaskManager如何作为服务端函数运行。通过阅读nova/conductor/manager.py,发现服务端启动在./nova/cmd/conductor.py的main()函数中,使用Service.create()创建ConductorManager实例。接着,通过Service.serve()启动服务,涉及oslo_service的launch()、add()函数,最终通过rpc.get_server()创建RPCServer并启动,监听网络消息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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()函数。

至此,服务端的监听程序启动了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值