如何使用ThinkPHP高效实现长连接请求处理?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1014个文字,预计阅读时间需要5分钟。
ThinkPHP 本身不支持真正意义上的长连接请求,所有长连接都需脱离 PHP-FPM 模式,改用 Swoole 或 Workerman 等常驻进程方案;在标准 Web 部署下,仅能依赖伪长轮询模拟。
为什么不能在控制器里用 sleep() 挂起请求
PHP-FPM 是同步阻塞模型,每个请求独占一个 worker 进程。写 sleep(5) 或 while (!Redis::get($key)) { usleep(100000); } 会导致该 worker 被锁死,无法处理新请求。压测时很快出现超时、502、FPM 进程耗尽。
- 即使加了
set_time_limit(0),也只延长脚本执行时间,不解决进程阻塞本质 - Nginx 默认
proxy_read_timeout是 60 秒,超时后主动断开,客户端收不到响应 - MySQL 连接可能因 wait_timeout 中断,触发
PDOException: MySQL server has gone away
扫码登录这类场景该用伪长轮询而非真长连接
客户端每 1–2 秒发一次 GET 请求,服务端查 Redis,有结果立刻返回,无结果快速返回空 JSON(如 {"code": 0, "msg": "waiting"}),不挂起、不阻塞。
本文共计1014个文字,预计阅读时间需要5分钟。
ThinkPHP 本身不支持真正意义上的长连接请求,所有长连接都需脱离 PHP-FPM 模式,改用 Swoole 或 Workerman 等常驻进程方案;在标准 Web 部署下,仅能依赖伪长轮询模拟。
为什么不能在控制器里用 sleep() 挂起请求
PHP-FPM 是同步阻塞模型,每个请求独占一个 worker 进程。写 sleep(5) 或 while (!Redis::get($key)) { usleep(100000); } 会导致该 worker 被锁死,无法处理新请求。压测时很快出现超时、502、FPM 进程耗尽。
- 即使加了
set_time_limit(0),也只延长脚本执行时间,不解决进程阻塞本质 - Nginx 默认
proxy_read_timeout是 60 秒,超时后主动断开,客户端收不到响应 - MySQL 连接可能因 wait_timeout 中断,触发
PDOException: MySQL server has gone away
扫码登录这类场景该用伪长轮询而非真长连接
客户端每 1–2 秒发一次 GET 请求,服务端查 Redis,有结果立刻返回,无结果快速返回空 JSON(如 {"code": 0, "msg": "waiting"}),不挂起、不阻塞。

