workerman需手动实现http长连接:设$connection->closeconnection = false、响应头加connection: keep-alive、配置$connection->maxlifetime,并启用tcp层keep-alive参数,三者缺一不可。

Workerman 本身不直接处理 HTTP 层的 Keep-Alive 头或连接复用逻辑——它作为底层 PHP 网络框架,更关注 TCP 连接生命周期和应用层心跳。当你用 Workerman 实现 HTTP 服务(如自定义 HTTP Worker),需手动控制连接保持行为,而非依赖 Nginx 或 Apache 那类 Web 服务器的 keepalive_timeout 配置。
HTTP 连接保持的核心控制点
Workerman 的 HTTP 长连接靠两件事协同实现:一是禁用自动关闭空闲连接,二是合理设置连接最大存活时间。
-
关闭自动断连:默认情况下,Workerman 的 HTTP Worker 在收到请求后会主动关闭连接。要保持长连接,必须显式设置
$connection->closeConnection = false;,并在响应头中加入Connection: keep-alive -
设置连接最大生命周期:通过
$connection->maxLifetime = 300;(单位秒)限制单个连接最长存活时间,防止内存泄漏或僵尸连接累积 -
响应头必须明确声明:在
onMessage中返回响应时,需手动写入标准 HTTP 头,例如:HTTP/1.1 200 OK\r\nConnection: keep-alive\r\nKeep-Alive: timeout=60, max=100\r\nContent-Length: 12\r\n\r\nHello World
超时参数不是由 Workerman 自动解析的
像 Keep-Alive: timeout=60 这样的响应头,只是告诉客户端“建议你在这个时间内复用该连接”,Workerman 不会读取或执行这个值。真正的超时控制仍由以下机制承担:
- 客户端行为:浏览器或 HttpClient 会按自己的策略决定是否复用、何时关闭连接(如 Chrome 默认复用 5 分钟)
-
Workerman 主动清理:通过定时器扫描
$worker->connections,对超过maxLifetime或长时间无数据的连接调用$connection->close() -
TCP 层保活(关键!):即使 HTTP 层保持连接,NAT/防火墙仍可能在 60–300 秒内静默回收空闲连接。必须在
onConnect中启用并调优系统级 TCP Keep-Alive:
示例配置(Linux 环境):
$connection->onConnect = function($connection) {
$socket = $connection->getSocket();
if ($socket && is_resource($socket)) {
// 启用 TCP Keep-Alive
socket_set_option($socket, SOL_SOCKET, SO_KEEPALIVE, 1);
// 首次探测前空闲时间(秒)
socket_set_option($socket, IPPROTO_TCP, TCP_KEEPIDLE, 45);
// 探测间隔(秒)
socket_set_option($socket, IPPROTO_TCP, TCP_KEEPINTVL, 15);
// 最大失败探测次数
socket_set_option($socket, IPPROTO_TCP, TCP_KEEPCNT, 3);
}
};
与 Nginx 反向代理共存时的注意事项
若 Workerman 前面挂了 Nginx,HTTP Keep-Alive 行为实际由 Nginx 控制,Workerman 只负责与 Nginx 的后端通信:
- Nginx 到客户端的连接由
keepalive_timeout和keepalive_requests控制 - Nginx 到 Workerman 的 upstream 连接需开启 HTTP/1.1 并配置
keepalive指令,例如:
upstream workerman_backend {
server 127.0.0.1:8080;
keepalive 32;
}
server {
location / {
proxy_pass http://workerman_backend;
proxy_http_version 1.1;
proxy_set_header Connection '';
}
}
此时 Workerman 收到的是 Nginx 转发的单次 HTTP 请求,不会感知客户端是否开启了 Keep-Alive,也不需要自己维护 HTTP 层连接复用逻辑。
小结:真正起作用的三个层级
别只盯着 HTTP 头里的 Keep-Alive 字样。维持可靠长连接,必须分层落实:
-
应用层心跳:客户端每 30 秒发
{"type":"ping"},服务端回{"type":"pong"}并更新活跃时间戳 -
TCP 层保活:用
socket_set_option设置TCP_KEEPIDLE/TCP_KEEPINTVL/TCP_KEEPCNT,穿透 NAT -
Workerman 连接管理:设
maxLifetime+ 定时清理 +closeConnection = false+ 手动响应头
三者缺一不可。只配 HTTP 头,连接会在 2 分钟后被路由器悄悄切断;只开 TCP Keep-Alive,HTTP 层可能已因超时关闭连接;只设 maxLifetime 不做心跳,无法及时发现假死连接。











