2025.2 系列发布说明

4.3.0

升级说明

  • 内部后端模块已重命名,以明确表示它们是私有的

    • oslo_service.backend.commonoslo_service.backend._common

    • oslo_service.backend.threadingoslo_service.backend._threading

    • oslo_service.backend.eventletoslo_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 的完整实现

    • ServiceLauncherServiceLauncherProcessLauncher

    • 使用 futurist.ThreadPoolExecutorLoopingCall 变体(FixedIntervalLoopingCallDynamicLoopingCall 等)

    • 一个模仿 eventlet 行为的新 ThreadGroupThread 抽象

    • 使用标准 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 中的一个已知限制。

    请参阅:https://gibizer.github.io/posts/Eventlet-Removal-The-First-Threading-Bug/#threads–osfork–confused-threadpools

    为避免此问题,您可以

    • 确保在 oslo.service fork 工作进程之前没有启动任何线程。

    • 使用 ProcessLauncher(no_fork=True) 完全禁用 fork。

    • 显式管理线程生命周期 — 例如,在 fork 之前停止所有线程,如 Nova 当前所做的那样。

升级说明

  • 尽管 Python 3.14 默认使用 spawn 作为多进程启动方法,但 oslo.service 仍依赖 fork 作为创建工作进程的唯一支持方法。OpenStack 的许多部分都依赖于无法安全序列化(pickle)的对象(例如,argparse 解析器、线程锁、配置默认值中的 lambda),这使得 spawn 目前不切实际。

    从长远来看,进程扩展应由外部处理(例如,通过 Kubernetes 或 systemd),而不是由服务本身处理。