Webman数据库连接本质是每个Worker进程复用一个PDO连接,非传统中心化连接池;需配置惰性重连、对齐mysql.wait_timeout/webman.tcp_keepalive_time/php.pdo.timeout三处超时参数,并避免事务未提交导致连接泄漏。

Webman 本身不提供内置数据库连接池,所谓“连接池”实际是每个 Worker 进程复用一个 PDO 连接;超时断开报错的根因通常不是连接池缺失,而是网络抖动 + 连接未重试 + 超时参数未对齐。
Webman 的数据库连接本质是进程级单连接复用
Webman 基于 Workerman,Worker 进程常驻内存,onWorkerStart 中初始化的 PDO 实例会一直存活并被后续所有请求复用。这不是传统中心化连接池(如 HikariCP),而是一种轻量、无协调开销的“伪池”——每个进程只持有一个连接,靠进程隔离实现并发安全。
这意味着:
- 连接数 = Worker 进程数 × 1,不会自动扩容,也不会自动回收空闲连接
- 一旦该连接因网络中断、MySQL
wait_timeout触发断开,后续请求就会直接抛出PDOException:SQLSTATE[HY000] [2006] MySQL server has gone away -
config/database.php中设置PDO::ATTR_TIMEOUT只控制单次 SQL 执行超时,不控制连接建立或保活
阿里云 RDS 网络环境下必须配心跳 + 惰性重连
内网直连 MySQL 可能正常,但 Webman 服务连阿里云 RDS 时,中间经过 SLB、NAT 网关等,TCP 连接容易被静默中断(尤其空闲 >30s)。仅靠 PDO::ATTR_TIMEOUT 无法解决。
正确做法是在模型基类中实现惰性重试逻辑,且必须在 try/catch 中捕获具体错误码:
Webman 2.2.0版本强化了 TCP/UDP 服务支持,优化路由组管理,并增强异步任务处理能力。结合协程与连接池技术,Webman 能轻松应对高并发场景,适用于网站、接口服务、即时通讯、物联网及游戏开发,兼具高性能、灵活扩展与稳定可靠,是多场景 PHP 服务开发的理想选择。
- 错误码
2006(server has gone away)和2013(lost connection)需触发重连 - 重连前先
$pdo->getAttribute(PDO::ATTR_CONNECTION_STATUS)判断是否已断开,避免无效重连 - 重试次数建议 ≤3,延迟从 50ms 起步递增,防止雪崩
- 不要在
onWorkerStart中做心跳SELECT 1—— 它无法覆盖所有断开场景,反而增加无谓负载
示例关键判断逻辑:
if ($e->getCode() == '2006' || $e->getCode() == '2013') {
$this->reconnect();
return $this->retryQuery($sql, $bindings, $times - 1);
}
Webman + 阿里云 RDS 必须对齐三处超时参数
连接超时是链路行为,必须端到端协同。以下三个值必须满足: mysql.wait_timeout ≥ webman.tcp_keepalive_time ≥ php.pdo.timeout。
- 查 RDS 当前
wait_timeout:SHOW VARIABLES LIKE 'wait_timeout';(阿里云默认 300 秒) - Linux 内核侧设
net.ipv4.tcp_keepalive_time=600(单位秒),避免 NAT 网关主动踢掉空闲连接 - PHP 层
PDO::ATTR_TIMEOUT设为 3~5 秒,不能设为 0(无限等待)或 >10 秒(拖垮整个 Worker) - 注意:Webman 的
config/app.php中max_request若设得太小(如 100),会导致 Worker 频繁重启,连接反复重建,放大问题
连接池爆满?先别急着加连接数
如果监控发现 Threads_connected 接近 max_connections,大概率不是连接不够,而是连接泄漏或阻塞。执行以下诊断:
- 查当前活跃连接:
SHOW PROCESSLIST;,重点关注Command = 'Sleep'且Time > 60的连接 ID - 确认这些 Sleep 连接是否对应 Webman 的 Worker 进程(看
User和Host) - 若大量 Sleep 连接长期存在,说明业务代码中某处
beginTransaction()后没commit()或rollback(),或异常未被捕获导致事务卡住 - 临时止血可用:
KILL,但根治要修复事务边界或加; DB::transaction()包裹
真正需要“连接池”的场景极少:只有当单个 Worker 处理高并发短任务(如每秒数百查询),且数据库 max_connections 远高于 Worker 数时,才值得引入 swoole/mysql 或 spiral/database 等协程连接池方案。对绝大多数 Webman 项目,进程级单连接 + 正确重试 + 参数对齐,已足够稳定。










