PHP处理高并发AI请求不能只靠fpm.max_children,因其无法区分普通API与耗时AI请求,易导致全部worker被占满而引发503;需Nginx限流+PHP层排队(Redis BRPOP+Lua原子操作)+前端友好响应(202+X-Queue-Position)。

PHP 处理高并发 AI 请求时,为什么不能只靠 fpm.max_children?
因为 AI 接口(比如调用本地 LLM 或转发到 OpenAI)通常响应慢、资源占用高,fpm.max_children 只控制 PHP-FPM 进程数,无法区分「普通 API」和「耗时 AI 请求」;一旦大量请求涌入,会挤占全部 worker,导致其他接口也卡死,甚至触发 503。
真正要做的,是应用层限流 + 请求排队,把压力挡在进入 PHP 执行前的环节。
- 优先用 Nginx 做第一道限流(轻量、高效),例如
limit_req针对/api/ai/chat路径 - PHP 层需配合做第二道控制:识别重复会话、拒绝超长队列、设置 per-user 请求 TTL
- 别依赖
sleep()或usleep()模拟排队——它会占满 FPM worker,等于没限流
用 Redis 实现公平排队,关键在 LPUSH + BRPOP 组合
不推荐用数据库存队列(写入慢、锁竞争高),Redis 的 list 结构天然适合 FIFO 场景。但直接 LPUSH + RPOP 有竞态:多个 worker 同时 RPOP 可能取到同一条任务。
必须用阻塞式弹出:BRPOP queue:ai:pending 30,30 秒超时避免无限等待;同时用 Lua 脚本保证「入队 + 计数 + TTL 设置」原子性:
eval "redis.call('LPUSH', KEYS[1], ARGV[1]); redis.call('INCR', KEYS[2]); redis.call('EXPIRE', KEYS[2], 3600); return 1" 2 queue:ai:pending counter:ai:active user_123_task_xyz
-
counter:ai:active用于实时统计当前处理中请求数,供限流逻辑读取(如 >5 就返回 429) - 每个用户任务加唯一 ID(如
md5(session_id . time())),避免重复提交被合并 - worker 进程需设置
set_time_limit(600),防止因等待超时被 FPM 杀掉
当用户请求被排队时,如何避免前端不断重试?
返回 202 Accepted 并附带 Location: /api/ai/status?task_id=xxx 是标准做法,但很多前端会忽略这个语义,继续轮询或刷新页面。
更稳妥的方式是:在响应头里加 X-RateLimit-Remaining: 3 和 X-Queue-Position: 2,让前端明确知道自己排第几、还能发几个请求。
- 用 Redis
ZCARD+ZRANK算位置(把 task_id 存进有序集合,score 为 UNIX 时间戳) - 前端拿到
X-Queue-Position: 2后,可每 3 秒查一次状态,而不是每秒发请求 - 如果用户关掉页面,后端需在
BRPOP超时后自动清理该 task_id 对应的元数据,否则队列会积压
LLM 流式响应(SSE)下,PHP 如何不卡住整个连接?
AI 返回文本流时,若用传统 echo + flush(),在 Nginx + PHP-FPM 默认配置下大概率失败:Nginx 缓冲未关闭、FPM buffer_output 开启、浏览器接收不及时都会导致卡死。
- 必须在响应前输出完整 SSE 头:
header('Content-Type: text/event-stream');+header('Cache-Control: no-cache');+header('X-Accel-Buffering: no'); - 禁用 PHP 输出缓冲:
if (function_exists('fastcgi_finish_request')) fastcgi_finish_request();不行,得用ob_end_flush(); ob_flush(); flush();三层清空 - 每次输出 chunk 后加
usleep(10000)(10ms),避免过快触发 Nginx 的proxy_buffering自动启用
真正难的是超时控制——用户中途断开,PHP 进程不会立刻感知。得在每次 echo 前检查 connection_aborted(),并结合 ignore_user_abort(false) 配合使用。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











