必须绕过php-fpm,以常驻进程方式启动websocket服务;需安装workerman 4.0.10、启用pcntl与posix扩展、用websocket://协议监听端口、配合gatewayworker实现业务分离,并通过redis、pdo连接池及nginx反向代理升级为生产级架构。

要在Linux服务器上用Workerman 4.0.10搭建可扩展的在线客服系统,必须绕过PHP-FPM传统模式,直接以常驻进程方式启动WebSocket服务,否则无法维持长连接、消息会延迟堆积甚至丢失。
安装Workerman并验证环境
执行composer require workerman/workerman:4.0.10安装指定版本,注意不要省略版本号,否则可能拉取到不兼容的5.x开发分支。
确认PHP版本不低于8.0:php -v;检查pcntl与posix扩展是否启用:php -m | grep -E "pcntl|posix"。若无输出,需编辑php.ini取消;extension=pcntl和;extension=posix前的分号,并重启PHP CLI环境。
【未启用pcntl扩展将导致Worker::runAll()直接报错退出,且错误提示极不直观】
编写最小可用WebSocket服务
在项目根目录新建chat_server.php,内容如下:
```php
use Workerman\Worker;
require_once __DIR__ . '/vendor/autoload.php';
$ws_worker = new Worker('websocket://0.0.0.0:8000');
$ws_worker->count = 2;
$ws_worker->onMessage = function ($connection, $data) {
$connection->send('收到:' . $data);
};
Worker::runAll();
```
关键点:协议必须写成websocket://而非http://或tcp://;$ws_worker->count = 2设为2个子进程,既利用双核又避免调试时日志刷屏。
启动、调试与进程管理
第一步:赋予执行权限 → 第二步:运行php chat_server.php start -d(-d表示守护进程模式) → 第三步:用netstat -tuln | grep :8000确认端口已监听。
若启动失败,立即执行php chat_server.php status查看进程状态;若显示“not running”,说明配置有硬性错误,此时不要反复start,先检查start.php路径是否与vendor同级、autoload.php是否存在。
日常调试建议去掉-d参数,用php chat_server.php start前台运行,错误堆栈实时可见。修改代码后必须先php chat_server.php stop再重新start,Workerman不支持热重载。
接入GatewayWorker实现业务分离
方法一:用Composer安装扩展 → 执行composer require workerman/gatewayclient和composer require workerman/gateway-worker。
方法二:手动部署GatewayWorker结构 → 在项目中创建Applications/YourApp/Events.php,定义onConnect、onMessage、onClose三个回调函数,其中onMessage里调用GatewayClient::sendToUid()向指定客服ID推送消息。
注意:GatewayWorker要求额外启动start_gateway.php和start_businessworker.php两个入口文件,且必须保证它们在同一服务器或局域网内低延迟互通。
升级至生产级架构的关键改造
① 将onMessage中的业务逻辑全部抽离为独立Service类,例如App\Services\MessageFilterService,利用PHP 8.5的|>管道操作符链式清洗敏感词、识别链接、转义HTML。
② 在onConnect中为每个连接生成唯一$client_id,并存入Redis哈希表hset online_users $client_id $ip:$port,设置30秒过期,用于心跳检测与强制下线。
③ 修改start_businessworker.php,将$worker->count设为CPU核心数×2,但单机不超过16,防止内存溢出;同时添加onWorkerStart回调,初始化PDO连接池并预加载常用配置。
④ 部署Nginx反向代理WebSocket流量,配置proxy_http_version 1.1和proxy_set_header Upgrade $http_upgrade,否则浏览器建立连接时返回400错误。











