Openstack nova service 启动过程

来源:互联网 发布:软文写作 知乎 编辑:程序博客网 时间:2024/05/26 22:10

Openstack 中nova主要是用作运算,其是有多个service组成的。

在每个service启动的时候都会注册一个RPC server(nova-api 除外)以供RPC的client调用。

nova compute

nova/cmd/compute.py

def main():    config.parse_args(sys.argv)    logging.setup('nova')    utils.monkey_patch()    objects.register_all()    gmr.TextGuruMeditation.setup_autorun(version)    if not CONF.conductor.use_local:        block_db_access()        objects_base.NovaObject.indirection_api = \            conductor_rpcapi.ConductorAPI()   <em><strong> server = service.Service.create(binary='nova-compute',                                    topic=CONF.compute_topic,                                    db_allowed=CONF.conductor.use_local)    service.serve(server)    service.wait()</strong></em>

service在程序的开头通过import导入

from nova import service

Service 是定义在nova/service .py 里面的一个类

其create方法使用@classmethod 修饰因此可以直接使用类名调用。此方法的作用是返回一个service的对象。

def create(cls, host=None, binary=None, topic=None, manager=None,               report_interval=None, periodic_enable=None,               periodic_fuzzy_delay=None, periodic_interval_max=None,               db_allowed=True):        """Instantiates class and passes back application object.        :param host: defaults to CONF.host        :param binary: defaults to basename of executable        :param topic: defaults to bin_name - 'nova-' part        :param manager: defaults to CONF.<topic>_manager        :param report_interval: defaults to CONF.report_interval        :param periodic_enable: defaults to CONF.periodic_enable        :param periodic_fuzzy_delay: defaults to CONF.periodic_fuzzy_delay        :param periodic_interval_max: if set, the max time to wait between runs        """        if not host:            host = CONF.host        if not binary:            binary = os.path.basename(sys.argv[0])        if not topic:            topic = binary.rpartition('nova-')[2]        if not manager:            manager_cls = ('%s_manager' %                           binary.rpartition('nova-')[2])            manager = CONF.get(manager_cls, None)        if report_interval is None:            report_interval = CONF.report_interval        if periodic_enable is None:            periodic_enable = CONF.periodic_enable        if periodic_fuzzy_delay is None:            periodic_fuzzy_delay = CONF.periodic_fuzzy_delay        debugger.init()        service_obj = cls(host, binary, topic, manager,                          report_interval=report_interval,                          periodic_enable=periodic_enable,                          periodic_fuzzy_delay=periodic_fuzzy_delay,                          periodic_interval_max=periodic_interval_max,                          db_allowed=db_allowed)        return service_obj

<em><strong>service.serve(server)</strong></em>
用来启动service

nova/service.py

def serve(server, workers=None):    global _launcher    if _launcher:        raise RuntimeError(_('serve() can only be called once'))    _<strong><em>launcher = service.launch(server, workers=workers)</em></strong>

在 service.py 中 service在开头import

from nova.openstack.common import service

service中的launch的实现为(nova/openstack/common/service.py)

def launch(service, workers=1):    if workers is None or workers == 1:        launcher = ServiceLauncher()        launcher.launch_service(service)    else:        launcher = ProcessLauncher()        launcher.launch_service(service, workers=workers)    return launcher
此处有两种加载方法ServiceLauncher和ProcessLauncher

ServiceLauncher类中的launch_service 实现为:注意ServiceLauncher类中并没有单独定义此方法而是继承自其父类Launcher
<pre name="code" class="python"> def launch_service(self, service):        """Load and start the given service.        :param service: The service you would like to start.        :returns: None        """        service.backdoor_port = self.backdoor_port        self.services.add(service)


services.add()方法实现使用了GreenThread关于Greenthraed会在单独一个文章里面介绍。

def add(self, service):        self.services.append(service)        self.tg.add_thread(self.run_service, service, self.done)
def run_service(service, done):        """Service start wrapper.        :param service: service to run        :param done: event to wait on until a shutdown is triggered        :returns: None        """        service.start()        done.wait()


greenthread会执行run_service()方法。run_service()方法执行service.start()和done.wait(),完成了服务的启动,然后等待,一开始我看到Service类中有个start()方法,知道一个服务的启动实质性的内容都在这个方法里,但是就是找不到在哪里调用了这个方法,原来是在这里。。


    def start(self):        verstr = version.version_string_with_package()        LOG.audit(_('Starting %(topic)s node (version %(version)s)'),                  {'topic': self.topic, 'version': verstr})        self.basic_config_check()        self.manager.init_host()        self.model_disconnected = False        ctxt = context.get_admin_context()        try:            self.service_ref = self.conductor_api.service_get_by_args(ctxt,                    self.host, self.binary)            self.service_id = self.service_ref['id']        except exception.NotFound:            try:                self.service_ref = self._create_service_ref(ctxt)            except (exception.ServiceTopicExists,                    exception.ServiceBinaryExists):                # NOTE(danms): If we race to create a record with a sibling                # worker, don't fail here.                self.service_ref = self.conductor_api.service_get_by_args(ctxt,                    self.host, self.binary)        self.manager.pre_start_hook()        if self.backdoor_port is not None:            self.manager.backdoor_port = self.backdoor_port        LOG.debug("Creating RPC server for service %s", self.topic)        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()        self.manager.post_start_hook()        LOG.debug("Join ServiceGroup membership for this service %s",                  self.topic)        # Add service to the ServiceGroup membership group.        self.servicegroup_api.join(self.host, self.topic, self)        if self.periodic_enable:            if self.periodic_fuzzy_delay:                initial_delay = random.randint(0, self.periodic_fuzzy_delay)            else:                initial_delay = None            self.tg.add_dynamic_timer(self.periodic_tasks,                                     initial_delay=initial_delay,                                     periodic_interval_max=                                        self.periodic_interval_max)

def get_server(target, endpoints, serializer=None):    assert TRANSPORT is not None    serializer = RequestContextSerializer(serializer)    return messaging.get_rpc_server(TRANSPORT,                                    target,                                    endpoints,                                    executor='eventlet',                                    serializer=serializer)



                                             
0 0
原创粉丝点击