workerman4 默认支持 sigint 和 sigterm 优雅关闭:停止新连接、等待旧连接超时(默认10秒)后退出;需确保主进程常驻、不忽略 sigterm、清理逻辑放 onworkerstop 且避免阻塞。

Workerman4 默认会监听 SIGINT(Ctrl+C)和 SIGTERM 信号,并在收到时触发优雅关闭流程——但仅监听 SIGINT 是不够的,生产环境必须同时处理 SIGTERM。
这是因为 SIGINT 主要用于本地开发调试(比如你手动按 Ctrl+C),而真实部署中(如 Docker、systemd、K8s)系统或编排工具发的是 SIGTERM。如果 Workerman4 没注册 SIGTERM,进程会被直接 kill -9 强制终止,导致连接中断、数据丢失、资源未释放等问题。
✅ Workerman4 默认已支持 SIGINT + SIGTERM
从 Workerman4 v4.1.0 起,核心已内置对两个信号的监听:
- 收到
SIGINT或SIGTERM后,自动调用Worker::stop(); -
Worker::stop()会:- 停止接受新连接(关闭 listener);
- 等待已有连接自然断开或超时(默认 10 秒);
- 最终退出所有 worker 进程。
你无需手动写 pcntl_signal(),除非你要定制清理逻辑。
⚠️ 但要注意这些关键点
不要屏蔽或忽略
SIGTERM
避免在代码里调用pcntl_signal(SIGTERM, SIG_IGN),否则优雅关闭失效。确保主进程是常驻的(非一次性脚本)
Workerman 的信号监听依赖于长期运行的主循环(Worker::runAll())。如果你在 CLI 中执行后立即退出(比如没调用runAll或提前exit),信号根本收不到。-
自定义清理逻辑要放在
onWorkerStop回调中Worker::$onWorkerStop = function ($worker) { echo "Worker stopping...\n"; // 关闭数据库连接、释放文件句柄、保存状态等 \PDO::getConnection()->close(); @unlink('/tmp/workerman.pid'); }; 避免在
onWorkerStop里做阻塞操作
比如同步 HTTP 请求、大文件写入、无超时的 Redisbrpop—— 它们会拖慢退出,甚至卡死整个 shutdown 流程。建议改用异步方式或设短超时。
? 手动补充监听(仅当需要扩展行为)
如果你需要捕获其他信号(如 SIGHUP 重载配置),可显式添加:
pcntl_signal(SIGTERM, function ($sig) {
echo "Received SIGTERM, initiating graceful shutdown\n";
Worker::stop();
});
pcntl_signal(SIGINT, function ($sig) {
echo "Received SIGINT, initiating graceful shutdown\n";
Worker::stop();
});
pcntl_signal_dispatch(); // 必须调用,否则信号不触发
注意:
pcntl_signal_dispatch()需在事件循环中定期调用(Workerman 内部已自动处理,一般不用手动加)。
? 验证是否真正优雅关闭
启动服务后,在另一个终端执行:
kill -TERM $(cat workerman.pid) # 推荐,模拟生产环境 # 或 kill -INT $(cat workerman.pid) # 等效于 Ctrl+C
观察日志是否有类似输出:
Worker stopping... All connections closed. Worker exited.
同时检查连接是否真正“自然结束”:用 netstat -an | grep :your_port 确认没有 ESTABLISHED 连接残留;客户端不应收到 Connection reset 或 502/503。
不复杂但容易忽略。











