← [ BACK_TO_NOTES ]

Python 服务优雅关闭

收到停机信号后停止接入,按预算排空或取消并等待在途任务,再释放依赖;区分协作退出与强制终止。

#concept #growing #dev #python #python

[!info] related notes

Python 服务优雅关闭

这个概念为什么出现

容器/编排发送 SIGTERM 后若直接杀进程,会打断请求与事务。优雅关闭协议:

  1. 停止接新流量
  2. 等待进行中完成(有超时)
  3. 关闭连接与刷日志

[!abstract] 一句话理解 停止接入后,按预算排空或请求取消,等待任务退出,再关闭依赖。超时策略与事务/消息协议决定剩余工作的处理,优雅关闭本身不保证没有半完成操作。

最小可运行示例

场景:工作循环响应停止标志

# graceful_flag_demo.py
# 业务意图:用 Event 模拟关闭开关。
# 教学点:协作式退出;真实服务接 signal。

from threading import Event


def worker_loop(stop: Event, max_steps: int = 3) -> int:
    steps = 0
    while not stop.is_set() and steps < max_steps:
        steps += 1
    return steps


def main() -> None:
    stop = Event()
    stop.set()  # 模拟收到关闭
    print("steps:", worker_loop(stop))


if __name__ == "__main__":
    main()

建议运行:

python graceful_flag_demo.py

期望输出:

steps: 0

结合场景再看三个关注点

  1. 此例只验证预设停止标志使循环不开始,没有注册信号、启动线程、排空队列或等待退出。检查后信号仍可能到达,不能保证标志一变就不再执行一步。
  2. Event.set() 只改标志,不中断阻塞调用,也不 join 线程;后台任务需有唤醒路径并显式等待。真实循环可用 Event.wait(timeout) 响应停止,避免忙轮询。
  3. DB 事务与消息确认语义要对齐。

核心概念与准确模型

  • SIGTERM/SIGINT
  • load balancer 摘流
  • asyncio.create_task 不会自动建立随创建者取消的任务树;TaskGroup 管理其登记任务,独立任务需显式取消并 await。
  • 正常退出和协作取消用 finally/上下文清理;SIGKILL、os._exit 或强制终止不能保证运行清理代码。

边界情况与反直觉行为

  1. Python 信号处理器在主解释器主线程执行,注册也受主线程限制;它不能作为任意工作线程的中断机制。
  2. 阻塞 SDK、长时间 C 调用可能推迟取消/信号响应;等待超时只表示停止等待,不会自动杀掉线程。
  3. 双重信号

常见误区

[!warning] 常见误区:只注册 signal 不排空 错误理解:打印 bye 即优雅。
正确模型:停止接流 + 等待 + 关依赖。

工程实践

  • readiness 与 liveness 分离
  • 关闭超时可配置
  • 演练 kill 场景

本节总结

优雅关闭是服务契约。信号只是扳机,排空才是内容。

自测题

  1. 优雅关闭三步?
  2. 为何需要超时?
参考答案
  1. 停新流量,按策略排空或取消并等待,再关资源;应给整个过程分配有限预算。
  2. 防止卡死任务永远不退出。

延伸阅读与资料来源

资料类型支撑内容
signal文档信号
创建于 2026/7/15 更新于 2026/10/17
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本