要扛住1万并发,必须用swoole(≥4.8.0)+think-swoole(≥3.1.0)替代php-fpm,并在config/swoole.php中配置有效连接池;db::pool()是唯一启用入口,database.php中pool参数完全无效,所有数据库操作须显式链式调用池实例。

ThinkPHP6 本身不支持原生协程和连接池,要扛住 1 万并发,必须脱离 PHP-FPM,改用 Swoole(≥4.8.0)+ topthink/think-swoole(≥3.1.0)组合,并配合 PolarDB 或高配 MySQL 实例做连接层优化。光靠配置 database.php 里的 pool 参数毫无作用——那些字段在 TP8 及更早版本中完全被忽略。
必须启用 Swoole 协程环境
TP6 是同步阻塞框架,FPM 模式下每个请求独占一个 PHP 进程,1 万并发意味着至少 1 万条数据库连接,MySQL 很快报 Too many connections。只有 Swoole Worker 进程常驻内存、支持协程后,才能复用连接资源。
- 安装
topthink/think-swoole扩展,启动命令为php think swoole - 确认
config/swoole.php中已启用数据库池配置,config/database.php里的任何pool_size、max_connections字段全部无效 - 禁用所有基于文件的缓存(如
cache.type = file),防止多协程写冲突 - 反向代理(Nginx)需配置
proxy_http_version 1.1和proxy_set_header Connection '',避免连接复用异常
连接池参数要按 PolarDB/MySQL 实际容量反推
连接池不是越大越好。max_active 设为 200,不代表能撑 200 并发,而是指“最多允许 200 条空闲或活跃连接共存”。它必须 ≤ 数据库实例的 max_connections × 0.8,给系统预留空间。
- PolarDB 默认
max_connections=200(按量集群),建议池子设max_active=160、max_idle=20 -
wait_timeout=3000(3 秒):协程排队获取连接超时,太小会频繁抛PoolTimeoutException,太大拖垮接口响应 -
idle_timeout=300(5 分钟):空闲连接自动销毁,匹配 MySQL 的wait_timeout,防止MySQL server has gone away - 务必关闭
'persistent' => false和'break_reconnect' => false,PolarDB 不支持重连兜底
所有数据库操作必须显式走池子
Db::table()、Db::connect()、模型 find() 默认都走短连接,哪怕你配了池子也白搭。唯一有效入口是 Db::pool(),且必须链式调用到底。
- 正确写法:
Db::pool()->table('user')->where('id', 1)->find() - 事务也要池化:
Db::pool()->transaction(function () { ... }),普通Db::transaction()会绕过池子 - 多库场景下,先
Db::pool()->connect('log_db'),再链式操作;模型类需重写db()方法返回池化实例,或手动指定protected $connection = 'log_db' - 避免混用:
Db::pool()->connect('a')->cache()->select()中->cache()可能触发默认连接,建议拆成独立变量操作
监控与压测验证关键指标
上线前必须验证池子是否真实生效。仅看配置或日志不够,得查数据库端真实连接数和协程行为。
- MySQL 执行
show processlist,观察连接数是否稳定在max_active附近,而非随并发线性上涨 - 用
ab -n 10000 -c 1000或wrk -t12 -c400 -d30s压测,关注错误率(尤其是PoolTimeoutException)和 P99 延迟 - 在
DbPool类中加计数器(如静态$counter),统计各连接名的 get/release 频次,确认复用率 - 检查 Swoole 日志中是否有
SQLSTATE[HY000] [2002] Connection refused,这往往意味着池子没启、或数据库max_connections已打满
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











