Workerman搭建高并发TCP服务端的核心是避免事件循环阻塞,必须定义onConnect和onMessage回调、启用text协议或手动缓存切分消息、设置合理进程数并禁用同步操作。

用Workerman搭建能稳定承载数千并发连接的TCP服务端,核心不是堆配置参数,而是让每个连接生命周期内不卡住事件循环——一旦onMessage里出现sleep()、file_get_contents()或同步MySQL查询,整个进程就堵死,后续所有连接排队等待。
基础服务端骨架必须包含的三个回调
第一步:创建Worker实例并监听端口,协议地址写成tcp://0.0.0.0:2345,不能漏掉tcp://前缀,否则启动失败。
第二步:必须定义onConnect回调,哪怕只写echo "connected\n";——【没有onConnect,部分Workerman版本会静默拒绝后续通信】。
第三步:在onMessage中必须调用$connection->send()或至少用strlen($data)读完数据,否则连接可能被心跳机制强制关闭。
第四步:运行Worker::runAll(),此时服务端才真正开始监听。
解决粘包与消息边界识别
Workerman默认不拆包,onMessage收到的数据可能是半条、整条或多条拼接在一起。text协议仅靠换行符分隔,但客户端平台差异大:Windows发\r\n,Linux发\n。
方法一:启用内置text协议(简单但有局限)
在Worker初始化后加一行:Worker::$protocol = 'text';,此时框架会在收到\n时触发onMessage,但要求客户端每条消息末尾严格带\n,否则消息永远不触发。
方法二:手动缓存+按行切分(推荐)
给每个连接绑定缓冲区:$connection->buffer = '';;在onMessage中执行:$connection->buffer .= $data;,再用$lines = explode("\n", $connection->buffer);切分;把最后一段不带\n的内容留回$connection->buffer = array_pop($lines);;遍历$lines逐条处理。
注意:用trim($line, "\r\n")统一清理行首尾,避免Windows客户端带来的\r干扰解析。
提升并发能力的关键配置
Worker默认单进程,CPU空转也撑不过几百连接。必须显式设置进程数:$worker->count = 4;——建议从CPU核心数起步,比如4核机器设为4,压测后再微调。
启动时务必加-d参数:php start.php start -d,否则信号处理异常会导致子进程无法回收,跑一段时间后连接数卡死。
别盲目调高$worker->count到16甚至32——【超过CPU核心数×2反而增加上下文切换开销,实测性能下降】。
避免常见阻塞陷阱
onMessage里禁止出现任何同步阻塞操作:file_get_contents()、sleep()、mysqli_query()(未用异步驱动)、curl_exec()(未设超时或未用CurlMulti)。
如果必须查数据库,用异步MySQL扩展(如amphp/mysql)或改用连接池方案;临时调试可加set_time_limit(0);但上线前必须移除。
发送响应时记得补换行符:$connection->send("OK\n");,text协议下不加\n,telnet客户端收不到回显——因为多数终端默认行缓冲,没遇到换行就不刷新显示。











