当前位置: 首页 > 工具软件 > oslo.cache > 使用案例 >

OpenStack公共组件oslo之五——oslo.service

龚勇锐
2023-12-01

        oslo.service为OpenStack各组件提供了一个定义新的长运行服务的框架;包括带有SSL和WSGI,周期性操作,结合systemd等的长运行应用。

1. oslo.service的实现原理

        在oslo.service的实现中,核心是oslo_service.service模块中的Service类和Launcher类。下面分别介绍这两个类:

1.1 Service类

        Service类的对象描述了一个服务,其定义了一套管理服务生命周期的方法,包括启动服务start()、停止服务stop()、等待服务wait()、重置服务reset()等管理方法。另外,在实例化Service对象时,可以传入一个threads的参数创建一个包含threads个线程的线程组ThreadGroup对象,用来管理服务中的所有线程。
        除了Service类外,oslo.service还提供了一个Services类来管理一组服务。其除了定义了run_service()、stop()、wait()、restart()等生命周期管理方法之外,还定义了一个add()方法用于为Services对象添加服务。

1.2 Launcher类

        Launcher类主要用来启动一个或多个服务并等待其完成。其定义了launcher_service(service, workers)、stop()、wait()、restart()方法管理Launcher对象中所有服务的生命周期;在实例化Launcher对象时,需要传入两个参数conf和restart_method,其中,conf表示加载的服务配置文件,restart_method表示重启服务的方式,在oslo.service中,定义了两种服务重启方式:reload方式表示重启服务时重新加载配置文件,mutate则表示重启服务时改变服务配置文件。
        在oslo.service中,Launcher类主要有两个实现方案:ServiceLauncher类和ProcessLauncher类。其中,ServiceLauncher类是在一个一个父进程中启动一个或多个服务,其通过一个单实例的SignalHandler类监听针对服务的信号。而ProcessLauncher类则是在给定数量的worker中运行一个或多个服务,其启动服务时,首先将服务、workers封装为ServiceWrapper对象;然后,调用ProcessLauncher对象的_start_child()方法启动一个子进程,并在子进程中运行服务。

1.3 launch()方法

        在其他OpenStack组件的实际使用中,通常都会调用oslo_service.service模块下的launch()方法启动相应的服务。该方法需要传入一下几个参数:
  • conf:对应服务的配置参数对象,即oslo.config中的ConfigOpt对象;
  • service:一个实例化的Service对象;
  • workers:为一个服务启动的worker数,如果workers为空或为1,则使用ServiceLauncher启动服务,如果workers>1,则使用ProcessLauncher类启动服务;
  • restart_method:服务重启方式。
        launch()方法会根据上述给定的参数创建服务启动方法类,并调用其launcher_service()方法启动服务。

2. oslo.service的使用方法

        本节主要以nova组件的nova-api服务的启动为例,阐述oslo.service的使用方法。通常,启动nova-api服务首先都会调用nova.cmd.api模块下的main()方法。其源码如下:
def main():
    config.parse_args(sys.argv)
    logging.setup(CONF, "nova")
    utils.monkey_patch()
    objects.register_all()
    gmr_opts.set_defaults(CONF)
    if 'osapi_compute' in CONF.enabled_apis:
        # NOTE(mriedem): This is needed for caching the nova-compute service
        # version.
        objects.Service.enable_min_version_cache()
    log = logging.getLogger(__name__)

    gmr.TextGuruMeditation.setup_autorun(version, conf=CONF)

    launcher = service.process_launcher()
    started = 0
    for api in CONF.enabled_apis:
        should_use_ssl = api in CONF.enabled_ssl_apis
        try:
            server = service.WSGIService(api, use_ssl=should_use_ssl)
            launcher.launch_service(server, workers=server.workers or 1)
            started += 1
        except exception.PasteAppNotFound as ex:
            log.warning("%s. ``enabled_apis`` includes bad values. "
                        "Fix to remove this warning.", ex)

    if started == 0:
        log.error('No APIs were started. '
                  'Check the enabled_apis config option.')
        sys.exit(1)

    launcher.wait()
        从nova-api启动程序源码可知,在启动服务时,系统首先调用nova.service的process_launcher()方法创建了一个ProcessLauncher对象launcher;然后根据配置文件配置的enabled_apis创建了WSGIService对象;接着,调用launcher对象的launch_service()方法启动WSGI服务;最后,当所有enabled_apis中配置的api服务都启动后,调用launcher.wait()方法使所有api服务都处于等待状态等待外部请求。
        在上述服务启动过程中,调用了nova.service模块中的WSGIService类,该类为nova组件自身封装的一个用于启动WSGI服务的Service子类;除此之外,nova.service模块中还定义了一个继承oslo.service Service类的子类Service。由此可知,在OpenStack各组件使用oslo.service时,还可以根据自身需求,实现自身的Service子类以便更好的使用oslo.service组件来管理自身的服务。

3. oslo.service组件的其他使用

        本文开头介绍了oslo.service除了为OpenStack各组件提供了一个定义新的长运行服务的框架外,还可以实现带有SSL和WSGI,周期性操作,结合systemd等的长运行应用。本节将对这些实现进行简单介绍。

3.1 sslutils模块

        sslutils模块主要提供一个wrap(conf, sock)方法,根据服务的配置文件,为基于SSL协议的服务添加ssl认证。

3.2 periodic_task模块

        periodic_task模块主要提供对周期性任务的管理方法。其中,主要包括一个类和一个方法:
  • periodic_task(*args, **kwargs)方法:为周期性任务提供一个装饰器。如果某周期性方法没有@periodic_task装饰器,则其将默认每隔60s运行一次;而如果其带有@periodic_task(spacing=N [, run_immediately=[True|False]] [, name=[None|"string"])装饰器,表示该方法将每隔Ns运行一次,如果run_immediately不为空,且设置为True,则表示该方法第一次运行将会马上执行,否则第一次运行将在Ns后执行。
  • PeriodicTasks类:封装了周期性任务的管理,其提供两个主要方法:add_periodic_task(task),为PeriodicTask对象添加周期性任务task;run_periodic_tasks(context, raise_on_error=False),运行周期性任务。

3.3 wsgi模块

        wsgi模块主要提供WSGI服务管理的实现框架。其中,主要包含三个重要的类:
  • Loader类:主要用于加载WSGI的配置文件(如nova的api-paste.ini文件),主要提供load_app(name)加载WSGI配置文件,并返回一个WSGI应用的URLMap对象。
  • Router类:主要用于缓存WSGI各REST API请求的路由信息,并在接收到请求时解析url并路由到具体的实现方法进行处理。
  • Server类:一个Service子类,主要实现了定义一个WSGI服务和管理该WSGI服务的生命周期。

3.4 systemd模块

        systemd模块是一个用于通知systemd服务准备就绪的辅助类。使用onready(notify_socket, timeout)方法监听systemd服务准备就绪通知;使用notify()、notify_once()方法通知systemd服务准备就绪。

3.5 loopingcall模块

        loopingcall模块主要实现了一组管理回路调用的类。实现了动态回路调用、回滚回路调用、异常回路调用以及重试调用等多种回路调用策略。

3.6 threadgroup模块

        threadgroup模块首先通过Thread类封装了一个线程的生命周期管理;然后通过ThreadGroup类管理一组线程的生命周期。
 类似资料: