Become a sponsor

说明
优雅关闭确保应用在收到终止信号时,能够完成正在处理的请求、关闭数据库连接、停止定时任务调度器后再退出,避免请求中断和资源泄漏。
收到 SIGINT / SIGTERM 信号
│
├─ 停止接收新请求
├─ 关闭定时任务调度器(shutdown_scheduler)
├─ 停止 IOLoop 事件循环
└─ 进程退出# src/bootstrap.py
import signal
import tornado.httpserver
import tornado.ioloop
def main():
app = create_app()
http_server = tornado.httpserver.HTTPServer(app)
http_server.listen(options.port)
# 启动定时任务调度器
from modules.job.scheduler import init_scheduler
init_scheduler()
ioloop = tornado.ioloop.IOLoop.current()
# ============================================================
# 优雅关闭回调
# ============================================================
def _shutdown():
"""收到退出信号时关闭调度器并停止事件循环。"""
logger.info("收到退出信号,正在优雅关闭...")
from modules.job.scheduler import shutdown_scheduler
shutdown_scheduler()
ioloop.stop()
# ============================================================
# 注册信号处理(优雅关闭)
# ============================================================
for sig in (signal.SIGINT, signal.SIGTERM):
try:
signal.signal(sig, lambda s, f: ioloop.add_callback_from_signal(_shutdown))
except (ValueError, AttributeError, OSError):
pass
ioloop.start()| 信号 | 触发方式 | 说明 |
|---|---|---|
SIGINT | Ctrl+C | 终端中断信号 |
SIGTERM | kill <pid> | 进程终止信号(Docker/Supervisor 默认发送) |
Windows 兼容
Windows 下 SIGTERM 可能不完全支持,SIGINT(Ctrl+C)是主要的关闭方式。代码中使用 try/except 包裹信号注册,避免 Windows 下的兼容性问题。
shutdown_scheduler() 停止 APScheduler,等待正在执行的任务完成ioloop.stop() 停止事件循环,进程自然退出Docker 发送 SIGTERM 等待 30 秒后发送 SIGKILL:
# Dockerfile
STOPSIGNAL SIGTERM# docker-compose.yml
services:
app:
stop_grace_period: 30s[program:djangoadmin]
command=poetry run python app.py --port=8041
stopsignal=TERM
stopwaitsecs=30优雅关闭方案具备以下特点:
1. 信号驱动:SIGINT / SIGTERM 触发关闭流程
2. 调度器先停:先关闭定时任务,避免任务执行到一半
3. IOLoop 停止:事件循环停止后进程自然退出
4. DB 会话兜底:BaseHandler.on_finish 确保会话释放
5. 容器友好:Docker / Supervisor 默认发送 SIGTERM