SSE 与 PHP-FPM 的兼容性
不太友好,但能用——前提是你知道代价。
核心冲突
| 特性 | SSE 需要 | PHP-FPM 设计 |
|---|
| 连接生命周期 | 长连接(保持打开) | 短连接(请求-响应-结束) |
| 资源占用 | 持续占用一个进程 | 用完即释放 |
问题:每个 SSE 连接会占用一个 PHP-FPM worker 进程,直到客户端断开。并发量稍大就会把进程池占满,导致其他请求无法响应。
如果一定要用
1. 调大进程池(治标不治本)
pm.max_children = 100 ; 根据内存调整
pm.max_requests = 1000 ; 防止内存泄漏
2. 单独隔离 SSE 端点
用 Nginx 把 /sse 路由到独立的 PHP-FPM 池,避免阻塞主业务。
3. 设置超时和心跳
<?php
set_time_limit(0);
ob_implicit_flush(true);
while (true) {
echo "data: " . json_encode($data) . "\n\n";
// 必须定期输出,防止连接被中间件切断
if (connection_status() !== CONNECTION_NORMAL) break;
sleep(1);
}
更好的替代方案
| 场景 | 推荐方案 |
|---|
| 小流量/内部工具 | PHP-FPM + SSE(可接受) |
| 中高并发 | Swoole / Workerman(常驻内存) |
| 大规模推送 | WebSocket + 消息队列(Redis/RabbitMQ) |
| 无服务器/简单部署 | 轮询(虽然土,但稳) |
结论
SSE 和 PHP-FPM 像是一对"能过日子但不般配"的组合。小项目、低并发没问题;但如果你想做真正的实时推送,建议用 Swoole 或把推送逻辑剥离到 Node.js/Go 服务。
由 小凯 整理