Oslo系列之oslo.service

生命力的好处在于拚搏,因为世界本身就是一个竞技场。

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

oslo.service的实现原理

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

Service类

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

除了Service类外,oslo.service还提供了一个Services类来管理一组服务。其除了定义了run_service()、stop()、wait()、restart()等生命周期管理方法之外,还定义了一个add()方法用于为Services对象添加服务。

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对象的

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()方法启动服务。

oslo.service的使用方法

本节主要以nova组件的nova-api服务的启动为例,阐述oslo.service的使用方法。通常,启动nova-api服务首先都会调用nova.cmd.api模块下的main()方法。其源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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组件来管理自身的服务。

oslo.service组件的其他使用

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

sslutils模块

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

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),运行周期性任务。

wsgi模块

wsgi模块主要提供WSGI服务管理的实现框架。其中,主要包含三个重要的类:

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

systemd模块

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

loopingcall模块

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

threadgroup模块

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

原文链接:https://blog.csdn.net/Bill_Xiang_/article/details/78492967

-------------本文结束 感谢您的阅读-------------
作者Magiceses
有问题请 留言 或者私信我的 微博
满分是10分的话,这篇文章你给几分