swoole::start() 启动后请求502,因thinkphp默认按单次请求设计而swoole常驻内存,导致container、config、db连接等状态残留;需禁用自动初始化,在onrequest中手动调用app::run()并重置单例,配置协程mysql连接池,合理设置worker_num、max_coroutine及task_worker_num。

为什么 Swoole::start() 启动后请求直接 502?
不是代码写错了,是 ThinkPHP 默认的 App 生命周期和 Swoole 的常驻内存模型根本冲突。Swoole 启动后不会每次请求都 reload 全局对象,而 ThinkPHP 的 Container、Config、数据库连接等默认按「单次 CLI/HTTP 请求」设计,复用时会残留状态或连接泄漏。
实操建议:
- 必须禁用 ThinkPHP 的自动初始化流程,改用
Swoole\Http\Server手动接管请求生命周期 - 所有全局单例(如
Db、Cache)需在onRequest回调里重新初始化或显式 reset,不能依赖thinkphp/start.php - 避免在
onWorkerStart中初始化任何带请求上下文的类(比如Request、Session),它们此时根本不存在
如何让 think-swoole 正确加载中间件和路由?
官方扩展 think-swoole 本身不接管路由解析,它只是把 Swoole 请求转成 ThinkPHP 能认的 Request 对象,但默认跳过了中间件链和模块调度逻辑。
实操建议:
- 务必在
onRequest回调中手动调用think\App::run(),而不是只做echo $response->getContent() - 确保
config/swoole.php中的enable_static_handler设为false,否则静态资源会绕过中间件(比如 JWT 鉴权中间件就失效) - 如果用了多应用模式,
app/multi_app.php必须在onWorkerStart里 require,不能靠自动加载——Swoole worker 不走传统入口文件
swoole_http_server 配置哪些参数直接影响并发上限?
不是开越多 worker_num 就越快。TP + Swoole 下真正的瓶颈常在 MySQL 连接池、Redis 连接复用、以及 PHP 内存回收机制上。
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
实操建议:
-
worker_num建议设为 CPU 核数 × 2~4,超过 32 很少带来收益,反而加剧进程间锁竞争 - 必须设置
max_coroutine(如3000),否则协程内发起的异步 DB 查询会被阻塞,TP 的Db::transaction()就会卡死 -
task_worker_num留 2~4 个足够,日志写入、邮件发送这类耗时操作才扔进去;别把 Redis 缓存更新也丢进 task,它本就是协程安全的 - 关闭
daemonize开发期调试,上线后必须开,否则systemctl无法管理进程状态
为什么 Db::connect() 在 Swoole 下频繁报 Too many connections?
ThinkPHP 默认的 PDO 连接不支持 Swoole 协程,每次 Db::table()->select() 都新建连接,且不会自动释放——连接被 worker 进程长期持有,很快打满 MySQL max_connections。
实操建议:
- 强制切换到协程 MySQL:安装
swoole/ext-mysql,配置database.php中的type为swoole_mysql,并启用pool配置项 - 禁用
debug模式,TP 的 SQL 日志记录器会在每个查询后 dumpdebug_backtrace(),协程环境下极易引发内存泄漏 - 不要在
onWorkerStart里调用Db::connect()做预热,协程连接池必须按请求动态分配
最麻烦的点其实是配置分散:Swoole 参数在 server.php,DB 连接池在 database.php,中间件开关又在 swoole.php,漏配一个就导致压测时连接数缓慢爬升,半夜报警才发现。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










