OpenStack源码解析系列 -- 5、服务启动流程 以nova-computer为例

  先看一下整体架构

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  从图中,可以知道几个点:

  交互

1)、 终端用户(DevOps, Developers 和其他的 OpenStack 组件)通过和nova-api对话来与OpenStack Compute交互。
2)、 OpenStack Compute守护进程(nova-api守护进程)之间通过队列(行为)和数据库(信息)来交换信息,以执行API请求。
3)、 OpenStack Glance基本上是独立的基础架构,OpenStack Compute通过Glance API来和它交互。

  各个进程的作用

1)、nova-api守护进程是OpenStack Compute的核心。为所有的API提供端点
2)、nova-compute是虚拟机实例操作的Worker守护进程,虚拟机实例操作过程很复杂。但是nova-compute原理很简单:就是从队列中接收行为,然后更新数据库状态,然后执行一系列的系统命令来执行他们
3)、nova-volume管理映射到计算机实例的卷的创建、附加和取消。这些卷可以来自很多提供商,比如,ISCSI和AoE。
4)、Nova-network worker,它从队列中接收网络任务,然后执行任务以操控网络,比如创建bridging interfaces或改变iptables rules。
5)、Queue提供中心hub,为守护进程传递消息。当前用RabbitMQ实现。但是理论上能是python ampqlib支持的任何AMPQ消息队列。
6)、 SQL database存储云基础架构中的绝大多数编译时和运行时状态。这包括了可用的实例类型,在用的实例,可用的网络和项目。理论上,OpenStack Compute能支持SQL-Alchemy支持的任何数据库,但是当前广泛使用的数据库是sqlite3(仅适合测试和开发工作),MySQL和PostgreSQL。
7)、 OpenStack Glance,是一个单独的项目,镜像管理。
8) 、最后,user dashboard是另一个可选的项目。OpenStack Dashboard提供了一个OpenStack Compute界面来给应用开发者和devops staff类似API的功能。当前它是作为Django web Application来实现的。当然,也有其他可用的Web前端。

  nova-compute的启动流程

  项目结构

在这里插入图片描述
  启动函数在项目的/cmd目录下,nova为例的话:/nova/cmd

  源码解析nova-compute启动过程

  1、compute.py

位置:/nova/cmd/compute.py

def main():
    # 解析参数
    config.parse_args(sys.argv)
    # 设置日志
    logging.setup(CONF, 'nova')
    # 定义特权上下文
    priv_context.init(root_helper=shlex.split(utils.get_root_helper()))
    objects.register_all()
    # 配置gmr_opts
    gmr_opts.set_defaults(CONF)
    # Ensure os-vif objects are registered and plugins loaded
    # 网络虚拟插件
    os_vif.initialize()

    # 启动进程监视
    gmr.TextGuruMeditation.setup_autorun(version, conf=CONF)

    # 阻塞等待数据库连接
    cmd_common.block_db_access('nova-compute')
    # conductor api实例化:实例时重点在获取rabbitmq中conductor队列的操作封装(RPCClient)
    objects_base.NovaObject.indirection_api = conductor_rpcapi.ConductorAPI()

    objects.Service.enable_min_version_cache()
    # rpc服务器的信息进行封装
    server = service.Service.create(binary='nova-compute',
                                    topic=compute_rpcapi.RPC_TOPIC)
    # 将rpc服务器信息记录并将其加入service列表,开一个协程启动service(nova-compute)
    service.serve(server)
    service.wait()

可以看出重点在于service.server(server, workers=None)这个函数

  2、service.server(server, workers=None)函数

位置:/nova/volume/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')

直接追踪到service.launch(conf, service, workers=1, restart_method=‘reload’)中去

  3、service.launch(conf, service, workers=1, restart_method=‘reload’)

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,
        type should be int.
    :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 not isinstance(workers, six.integer_types):
        raise TypeError(_("Type of workers should be int!"))

    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

这里可看到launcher为ServiceLauncher或ProcessLauncher,那看一下这个类究竟是什么吧
在这里插入图片描述

扫描二维码关注公众号,回复: 8647765 查看本文章
  揭开launch的面纱

位置:oslo_service下的service.py

class Launcher(object):
    """启动一个或多个服务,等待它们完成"""

    def __init__(self, conf, restart_method='reload'):
        """Initialize the service launcher.
		:parm conf: ConfigOpts的实例
        :param restart_method: 如果为'reload',则在SIGHUP上调用	  reload_config_files;如果为'mutate',则在SIGHUP上调用mutate_config_files。其他值会产生ValueError
        :returns: None

        """
        self.conf = conf
        conf.register_opts(_options.service_opts)
        self.services = Services(restart_method=restart_method)
        self.backdoor_port = (
            eventlet_backdoor.initialize_if_enabled(self.conf))
        self.restart_method = restart_method

看看一看launch_service()方法

    def launch_service(self, service, workers=1):
        """Load and start the given service.

        :param service: The service you would like to start, must be an
                        instance of :class:`oslo_service.service.ServiceBase`
        :param workers: This param makes this method compatible with
                        ProcessLauncher.launch_service. It must be None, 1 or
                        omitted.
        :returns: None

        """
        if workers is not None and workers != 1:
            raise ValueError(_("Launcher asked to start multiple workers"))
        _check_service_base(service)
        service.backdoor_port = self.backdoor_port
        self.services.add(service)
发布了87 篇原创文章 · 获赞 28 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/shuzishij/article/details/103098813