发布于2026-07-07 阅读(0)
扫一扫,手机访问
先说一个核心原则:UserProcess 必须通过 addProcess() 注册到 Swoole Server 中,否则它就成了“黑户”进程——既无法被自动重启,也收不到优雅关闭信号,更别提信号监听了。更严重的是,子进程退出后没人回收,僵尸进程就这么诞生了。而一旦正确注册,Swoole Manager 会自动处理 SIGCHLD,异步回收子进程,干干净净。

关键一步:必须用 addProcess() 方法注册,绝对不能用 new SwooleProcess 之后直接调 start()。否则进程脱离主服务生命周期,自动重启、优雅关闭、信号监听一概失效。
常见错误写法长这样:
$p = new SwooleProcess(function($proc) { while(true) { sleep(1); }});$p->start(); // ❌ 错误:未纳入 Server 管理
正确姿势其实很简单:
on('Start') 或 on('WorkerStart') 回调中调用 $server->addProcess($process)。$process 必须是 SwooleProcess 实例,且它的回调函数不能阻塞主事件循环——比如别用无超时的 sleep()。tick() 或 after() 来实现非阻塞定时逻辑,而不是死循环。根源很简单:父进程(Swoole Manager)没有主动回收子进程的退出状态。当 UserProcess 自己 exit() 或异常终止,而主服务没监听 SIGCHLD,僵尸就留下了。
解决方法不是手动 wait()——那个会阻塞,正确的做法是利用 Swoole 内置机制:
addProcess() 添加,Swoole Manager 就会自动注册 SIGCHLD 处理器,异步回收子进程。addProcess();再检查子进程退出前是否用了 posix_kill($pid, SIGTERM) 这类非标准退出方式。ps aux | grep 'Z' 或 cat /proc/$pid/status | grep State。两者都干异步的活,但定位和资源模型完全不同:
task_worker_num 控制数量,只负责执行 $server->task() 投递的任务,共享 Server 配置和连接池。$server->task() 很可能失败(因为 $server 实例在子进程中不可用),正确做法是用管道或消息队列通信。大多数 server->set() 参数并不作用于 UserProcess,但以下三个例外值得注意:
max_request:只控制 Worker/TaskWorker 的重启,UserProcess 不受它限制——这也是它适合长任务的原因。daemonize:设为 true 时,UserProcess 随主服务一起转入后台;设为 false 则所有进程都在前台输出,方便调试。reload_async:热更新时默认不重启 UserProcess——它需要自己实现配置热加载,比如监听文件变更再重载业务类。真正影响 UserProcess 行为的是你传给 SwooleProcess 构造函数的参数:$redirect_stdin_stdout 和 $pipe_type 决定了它能不能读写主服务的标准流、是否创建 IPC 管道。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8