Webman自定义进程是解决定时任务阻塞等核心问题的必要手段,必须在config/process.php中配置,每个进程需指定handler类并实现onWorkerStart方法,非监听型进程不设listen,耗时任务须独立进程隔离以避免阻塞HTTP Worker。

Webman 的自定义进程不是“可选插件”,而是解决定时任务阻塞、长连接保活、后台异步处理等真实问题的必要手段。不配置自定义进程,所有定时任务默认挤在同一个 Worker 进程里跑,sleep(30) 一下,后面所有 Crontab 都得排队等——这不是延迟,是调度瘫痪。
自定义进程必须写在 config/process.php 里
Webman 只认这个文件定义的进程,start.php 或控制器里 new 出来的 Worker 实例不会被主进程管理,也无法热重载或平滑重启。
-
process.php返回的是一个关联数组,键名是进程标识(如'task'、'websocket'),值是该进程的配置项 - 每个进程必须指定
'handler',指向一个类,且该类需实现onWorkerStart()方法(否则启动报错Call to undefined method onWorkerStart) - 不写
'listen'表示非监听型进程(比如纯定时任务),写了则作为独立服务端口启动(如'websocket://0.0.0.0:8888') -
'count'默认为1;设为2就会 fork 出两个完全独立的进程,各自运行自己的onWorkerStart,互不干扰
定时任务别再塞进 HTTP Worker 里
HTTP Worker 是为响应用户请求设计的,它的事件循环要优先保障低延迟、高吞吐。把耗时任务(如导出报表、同步第三方数据)丢进去,等于让所有用户请求为它让路。
- 新建
app/process/ReportTask.php,在里面注册Crontab,而不是在app/process/Task.php或中间件里 - 在
process.php中单独配一个'report_task'进程,'count' => 1即可,避免重复触发 - 如果某任务失败后需重试,不要用
sleep()循环重试——它会阻塞整个进程;改用Timer::add()延迟执行,或投递到消息队列 - 注意:多个自定义进程间不共享内存,
static变量或全局变量无法跨进程通信,要用Redis、UnixSocket或数据库做状态同步
监听型进程要显式关闭默认 HTTP 服务
当你新增一个 'my_api' => ['listen' => 'http://0.0.0.0:8686'] 进程时,Webman 默认的 HTTP Worker(由 start.php 启动的那个)依然在跑,端口冲突或路由混乱几乎是必然的。
立即学习“PHP免费学习笔记(深入)”;
- 先去
config/server.php把'listen'改为空字符串:'listen' => '',彻底禁用默认 HTTP 服务 - 确保新进程的
'listen'地址不与其他进程冲突,例如不能两个都监听http://0.0.0.0:8787 - Windows 下必须用
php windows.php start启动才能加载监听型自定义进程,Linux/macOS 用php start.php start - 若启用
'reusePort' => true,需确认 PHP 版本 ≥ 7.4 且内核支持SO_REUSEPORT,否则启动时报错Address already in use
真正难的不是写几个 onWorkerStart,而是想清楚哪个逻辑该放在哪个进程里——比如日志聚合适合单进程串行写,而实时推送必须多进程分摊连接压力。进程划分一旦定下,后续扩缩容、监控埋点、故障隔离就全绑在这上面了。



















