必须绕过thinkphp命令封装陷阱,用最小化引导启动workerman常驻进程;确认版本为4.0.10,删除不兼容的topthink/think-worker,手动创建start_gateway.php独立启动。

要在 ThinkPHP 项目中稳定运行 Workerman 4.0.10 并支持长连接、WebSocket 或 MQTT 等实时能力,必须绕过框架命令封装陷阱,用最小化引导方式启动常驻进程,否则会因 exit 被屏蔽、容器复用、连接泄漏导致服务秒退或内存暴涨。
确认 Workerman 版本与依赖兼容性
执行 composer show workerman/workerman,确保输出版本为 4.0.10。若显示 3.x 或 5.x,请强制指定:composer require workerman/workerman:^4.0.10。ThinkPHP 6.0–6.3 与 Workerman 4.0.10 兼容,但 不能混用 topthink/think-worker 4.x(仅适配 TP8),否则 Worker::runAll() 会被 Symfony Console 的 exit 拦截而静默失败。
删除已安装的 think-worker:composer remove topthink/think-worker。它在 TP6 中不是必需项,反而引入生命周期冲突。
手动创建独立启动脚本
在项目根目录新建 start_gateway.php,内容如下:
<?php use GatewayWorkerGateway;use GatewayWorkerBusinessWorker;use GatewayWorkerRegister;use WorkermanWorker;require_once __DIR__ . '/vendor/autoload.php';// ⚠️ 关键:不加载 public/index.php,避免触发 HTTP 环境检测// 设置 gateway 进程监听地址和端口$gateway = new Gateway('websocket://0.0.0.0:7272');$gateway->count = 4;$gateway->lanIp = '127.0.0.1';$gateway->startPort = 2900;$gateway->onConnect = function($connection) { echo "New connection
"; };// BusinessWorker 处理业务逻辑,需继承自 ThinkPHP 应用实例$worker = new BusinessWorker();$worker->count = 4;$worker->eventHandler = 'app\server\BusinessEventHandler';// Register 服务必须启动,否则 Gateway 无法注册节点$register = new Register('text://0.0.0.0:1236'); Worker::runAll();
这个脚本只加载 autoloader 和必要类,完全脱离 ThinkPHP 命令生命周期。任何在全局作用域初始化 DB、Redis 或读取 config 的行为都必须移到 onWorkerStart 回调里,否则子进程会重复建连。
编写 BusinessEventHandler 业务处理器
在 app/server/BusinessEventHandler.php 中定义:
<?php namespace appserver;use thinkApp;use thinkacadeDb;use WorkermanConnectionTcpConnection;class BusinessEventHandler{ protected $app; public function __construct() { // 在构造函数中不初始化 App!必须延迟到 onWorkerStart } public function onWorkerStart($businessWorker) { // ✅ 此处才是安全初始化位置 $this->app = new App(__DIR__ . '/../../'); // 预热模型、重置数据库连接池 Db::connect()->reconnect(); } public function onMessage($client_id, $data) { // 使用 $this->app 调用控制器或模型,例如: // return $this->app->invoke(['app\controller\Chat', 'handle'], [$client_id, $data]); }}
注意:不能直接 new App() 在构造函数里——Workerman fork 子进程时会复制当前对象状态,导致所有子进程共享同一 Db 连接句柄。必须在 onWorkerStart 中重建实例。
启动与调试服务
第一步:赋予执行权限(Linux/macOS):chmod +x start_gateway.php。
第二步:前台启动测试:php start_gateway.php。观察终端是否输出 Workerman[xxx] start in DEBUG mode 及三个进程状态 OK。
第三步:验证 WebSocket 连接:telnet 127.0.0.1 7272 或用浏览器访问 ws://127.0.0.1:7272,成功建立连接即表示 Gateway 已就绪。
第四步:生产环境守护启动:php start_gateway.php start -d。此时 必须设置 Worker::$user = 'www-data'(Linux)或对应 Web 服务用户,否则 reload 或 stop 会因权限不足失败。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











