2025.2 系列发布说明¶
4.3.0¶
升级说明¶
内部后端模块已重命名,以明确表示它们是私有的
oslo_service.backend.common→oslo_service.backend._commonoslo_service.backend.threading→oslo_service.backend._threadingoslo_service.backend.eventlet→oslo_service.backend._eventlet
这些模块从未打算直接使用。此更改使它们更清楚是
oslo_service.backend的内部组件。项目应仅通过oslo_service.backend.__init__中提供的公共接口与后端系统交互 —特别是通过诸如get_component()、get_backend()和init_backend()等函数。如果您的项目曾直接导入任何这些模块,请更新导入以改用公共 API。
4.2.2¶
升级说明¶
oslo_service.wsgi模块已从弃用中恢复。它包含除了基于 eventlet 的Server类之外的许多实用程序。现在,只有Server类本身被弃用。
4.2.1¶
错误修复¶
threading后端现在接受ProcessLauncher中的wait_interval参数,以与 Neutron 等服务兼容。该参数仍用于eventlet后端,以在子进程监控循环期间减少 CPU 使用率,但在threading中没有效果。如果传递了该参数,则会记录一条警告。此外,现在支持对同一个ProcessLauncher实例多次调用launch_service(),内部使用单个ServiceManager。这使得 threading 后端与eventlet后端的行为完全兼容。
修复了在 threading 后端服务关闭期间发生的崩溃,该崩溃是由对
cotyledon.ServiceManager上不存在的内部方法_terminate()的错误调用引起的。关闭过程现在正确使用公共shutdown()方法,确保服务的优雅且可靠的终止。
4.2.0¶
新特性¶
向 oslo.service 添加了一个新的 threading 后端,使用标准的 Python 线程而不是 eventlet。这包括使用 cotyledon 的完整实现
Service、Launcher、ServiceLauncher 和 ProcessLauncher
使用 futurist.ThreadPoolExecutor 的 LoopingCall 变体(FixedIntervalLoopingCall、DynamicLoopingCall 等)
一个模仿 eventlet 行为的新 ThreadGroup 和 Thread 抽象
使用标准 Python 信号的本机 SignalHandler 实现
此后端提供了一个与标准线程兼容的替代方案,避免了猴子补丁,使其适用于 eventlet 有问题或不受欢迎的环境。
此外
ProcessLauncher 现在支持 no_fork=True 模式,允许服务在主进程中运行而无需 fork。这在 fork() 不安全时非常有用 — 例如,在多线程环境中或使用 Python 3.12+ 时,默认的多进程启动方法已更改为 spawn。
添加了一个新的 register_backend_default_hook() API。它允许用户在 init_backend() 未能尽早调用的情况下定义一个回退后端类型。这在导入顺序或初始化时序无法保证的环境中很有帮助。
示例
`python from oslo_service import backend backend.register_backend_default_hook(lambda: backend.BackendType.THREADING) `此挂钩仅在 init_backend() 尚未被调用时使用。
已知问题¶
当使用具有多个工作进程的 threading 后端(即带有 fork() 的 ProcessLauncher)时,在 fork 发生之前启动线程可能会因 os.fork() 在多线程进程中的行为方式而导致状态损坏。这是 Python 中的一个已知限制。
为避免此问题,您可以
确保在 oslo.service fork 工作进程之前没有启动任何线程。
使用 ProcessLauncher(no_fork=True) 完全禁用 fork。
显式管理线程生命周期 — 例如,在 fork 之前停止所有线程,如 Nova 当前所做的那样。
升级说明¶
尽管 Python 3.14 默认使用
spawn作为多进程启动方法,但 oslo.service 仍依赖fork作为创建工作进程的唯一支持方法。OpenStack 的许多部分都依赖于无法安全序列化(pickle)的对象(例如,argparse 解析器、线程锁、配置默认值中的 lambda),这使得spawn目前不切实际。从长远来看,进程扩展应由外部处理(例如,通过 Kubernetes 或 systemd),而不是由服务本身处理。