hyperf多数据库连接超时参数需分池独立配置:wait_timeout按业务特征设2.0~8.0秒,connect_timeout依网络距离调至3.0~5.0秒,max_idle_time严格小于服务端断连阈值30秒以上,并协同heartbeat与min_connections联动调优。

Hyperf 多数据库连接超时参数配置不能简单套用单库逻辑,必须按连接池独立管理、业务特征差异、服务端限制三者联动调整。核心不是“设多少”,而是“怎么配才不冲突、不泄漏、不假超时”。
多数据库连接的 wait_timeout 必须分池设置
每个数据库连接池(如 default、log_db、report_db)都有独立的 wait_timeout,它只控制该池内协程等待空闲连接的最长时间。若多个业务共用同一池但负载差异大(比如日志写入高频短耗时,报表查询低频长耗时),就会互相干扰:报表慢查询拖住日志协程排队,导致日志侧频繁报 WaitTimeoutException。
- 日志类连接池(高频写入):
wait_timeout设为 2.0~3.0 秒,快速失败,避免阻塞上游 - 报表/分析类连接池(低频长耗时):
wait_timeout设为 5.0~8.0 秒,预留执行缓冲 - 切勿全局统一设值,尤其避免把
wait_timeout设成 10 秒以上——会掩盖连接池真实容量不足
connect_timeout 要按网络距离差异化调低connect_timeout 是建立新连接的超时,不是复用连接的等待时间。对跨机房或云厂商内网延迟较高的数据库(如阿里云 RDS 与应用不在同可用区),默认 10.0 秒容易在抖动时卡住协程。
- 同机房/同 VPC:建议 5.0 秒
- 跨可用区/跨地域:建议 3.0 秒,配合重试策略(如
retry_seconds => [1, 2, 4]) - 若日志中频繁出现
Connection timeout且ss -s | grep ESTAB显示连接数远低于max_connections,大概率是connect_timeout过长导致协程堆积
max_idle_time 必须严格小于对应数据库的 wait_timeout
MySQL 和 PostgreSQL 的服务端空闲断连机制不同,但原则一致:客户端连接池的 max_idle_time 必须比服务端主动断连阈值小至少 30 秒,否则连接取出时必然失效。
- MySQL:查
SHOW VARIABLES LIKE 'wait_timeout';,设max_idle_time = wait_timeout - 30(如服务端是 28800 秒,客户端设 28770;常见线上值为 60,客户端设 30) - PostgreSQL:没有
wait_timeout,实际生效的是tcp_keepalives_idle(默认 7200 秒),但更关键的是idle_in_transaction_session_timeout(防事务卡死)。此时max_idle_time应 ≤ 300 秒,并配合监控state = 'idle in transaction'的连接 - 多库场景下,每个池的
max_idle_time都要单独校验,不能复用同一数值
心跳与空闲检查必须按池启用且协同heartbeat 参数在 Hyperf 中默认不生效,真正起作用的是后台 IdleConnectionChecker 线程,它依赖 max_idle_time 和 heartbeat 协同工作:
-
heartbeat必须 ≤max_idle_time,推荐设为max_idle_time / 2(如max_idle_time=30,则heartbeat=15) -
min_connections别设 0,尤其多库场景下冷启延迟更敏感;各池建议 ≥ 2(日志池可设 5,报表池可设 2) - 若某库驱动不支持
PING(如旧版 pgsql 扩展),改用'checker' => 'SELECT 1',但注意该语句不能在事务中执行,需确保连接处于 idle 状态
连接泄漏风险在多库下更隐蔽
一个库的 pipeline 或 transaction 泄漏,不会影响其他池,但会让本池 max_connections 快速耗尽。排查重点:
- 对每个数据库连接池单独执行
SELECT count(*) FROM sys_stat_activity;(PostgreSQL)或SHOW PROCESSLIST;(MySQL),看连接是否长期滞留 - 检查所有使用
$db->connection('xxx')->transaction(...)或$redis->pipeline()的地方,务必加finally { $db->reconnect(); }或显式释放 - 异步队列消费进程必须使用独立 Redis/DB 连接池(如
queue池),避免和 HTTP 请求共用,否则高并发时队列会抢光连接











