AberSheeran
Aber Sheeran

WSGI 项目的 Lifespan

起笔自
所属文集: 程序杂记
共计 906 个字符
落笔于

经过大概几年的使用,我深深感受到 Python 的 asyncio 生态还是跟闹着玩的一样,于是打算 CURD 业务部分还是迁回同步比较好,使用 gevent 包装,性能也并不弱。

而 ASGI 迁回 WSGI,面临最大的问题就是如何把 ASGI Lifespan 在 WSGI 项目里实现了。WSGI 协议的设计里并没有给出对应的功能,于是只能在 WSGI Server 和 WSGI Framework 里想办法了。大致来说,有如下两种实现。

  • 模块加载时,执行启动时需要执行的代码,并且记录状态,避免重复执行。
  • 使用服务器程序提供的接口,由服务器程序保证执行。

第一种就是 Django 启动项目时一次性执行代码的实现,Django App ready,但这玩意对我来说没有任何意义。因为我用的是 hintapi

于是只能用第二种办法。而我查了几种常见的 WSGI Server,发现只有 Gunicorn 支持纯 Python 的 Server Hook。之所以强调纯 Python,是因为 uWSGI 支持 C 写的 Hooks

Gunicorn 提供了许多接口,覆盖了整个 Service 的各个生命周期。一般 CURD 项目会用到的 Hook 就是 post_worker_init,其参数由启动时指定的 worker-class 决定,默认的 sync 函数签名如下。

# gunicorn.conf.py
from gunicorn.workers.sync import SyncWorker as Worker


def post_worker_init(worker: Worker) -> None:
    pass

时隔两年之后,我自己写了一个 WSGI Server——Zī Bái。兹白提供了三个 hook 函数,通过这些 hook 就能解决 Lifespan 的问题。

  • before_serve 在服务启动前被调用
  • before_graceful_exit 在服务收到优雅退出的信号后、执行退出代码前执行
  • before_died 在服务被彻底关闭前执行
如果你觉得本文值得,不妨赏杯茶
Type hint 在定义数据模型时的应用
URL Query Parameters