workerman 不支持直接调用 worker::stop() 停止单个 worker 进程,正确方式是通过发送 sigterm 信号或在 onworkerstart 中条件触发 exit() 实现优雅退出,并手动清理定时器、连接和资源。

停止单个 Worker 进程的正确方式
Workerman 不允许你在运行时主动调用某个 Worker 对象的 stop 方法。真正可行的操作是:向目标 Worker 进程发送 SIGTERM 信号,由 Master 进程捕获后决定是否回收该 Worker。但注意:这个操作不是开发者直接控制的,而是通过 Workerman 内部机制触发的。
如果你希望某个 Worker 主动退出(比如完成当前任务后不再接受新连接),推荐做法是在 onWorkerStart 中启动一个一次性定时器或条件判断,在满足退出条件时调用 exit() 或 posix_kill(getmypid(), SIGTERM),让该进程自行终止。Master 会感知到子进程退出并按配置决定是否拉起新进程(取决于 $worker->reloadable 和 count 设置)。
资源释放的关键点
当 Worker 进程退出时,以下资源需特别关注是否已释放:
-
定时器:使用
Timer::del($timerId)或Timer::clearAll()主动清理,否则可能残留未执行回调 -
socket 连接:所有客户端连接在进程退出前会自动触发
onClose回调,但需确保你在该回调中做了必要清理(如从全局连接池中移除) - 文件/数据库句柄:PHP 在进程退出时会自动关闭打开的文件和 PDO 连接,但若使用了长连接池(如 Swoole\Table 或自定义连接池),必须手动释放
-
内存引用:避免在
onWorkerStart中绑定闭包持有大对象,防止退出时内存无法及时回收
实用建议:模拟“可控退出”
虽然不能直接 stop 单个 Worker,但可以通过以下方式实现类似效果:
- 设置
$worker->name = 'my_task_worker',便于日志识别 - 在
onWorkerStart中注册一个检查标志位的定时器,例如每秒读取 Redis 或文件中的开关状态 - 一旦检测到“退出指令”,调用
Timer::clearAll()+foreach ($worker->connections as $conn) $conn->close()+exit(0) - 确保
onWorkerStop回调中无阻塞操作,仅做轻量级收尾(如记录日志、上报指标)











