You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apache+SSE+PHP环境下SSE正常但其他请求长期Pending问题求助

解决SSE导致其他请求Pending的问题

兄弟,这个坑我之前踩过!核心原因是SSE的长连接特性和PHP/Apache的会话锁、进程管理机制冲突了,给你几个针对性的解决思路:

1. 立刻释放PHP会话锁(最关键!)

PHP的Session默认是文件存储,而且请求期间会加独占锁——如果你的SSE请求开启了Session(比如要获取用户登录状态),那其他所有需要Session的请求都会被死死堵住,直到SSE连接断开。

解决办法很简单:在SSE控制器里,拿到需要的Session数据后,马上调用session_write_close()释放锁:

session_start();
// 只在这里获取你需要的Session数据,比如用户ID
$user_id = $_SESSION['user_id'] ?? 0;
// 立刻关闭Session,释放锁!
session_write_close();

// 接下来才是SSE的响应头和推送逻辑
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Connection: keep-alive');

while (true) {
    // 推送消息的逻辑
    echo "data: " . json_encode(['msg' => '新消息']) . "\n\n";
    // 强制输出缓冲区内容
    ob_flush();
    flush();
    // 避免太频繁推送,适当休眠
    sleep(1);
    // 检查客户端是否断开连接,及时退出循环
    if (connection_aborted()) {
        break;
    }
}

2. 调整Apache MPM配置(针对Prefork模式)

如果你的Apache用的是Prefork MPM(默认模式),每个HTTP连接会占用一个独立进程,SSE的长连接会一直占着这个进程不释放——当进程池被耗尽时,新的请求就只能处于Pending状态。

你之前改了没效果可能是参数没到位,试试这些调整:

  • 把MaxRequestWorkers(旧版本叫MaxClients)调大,比如根据服务器配置设为200-500;
  • 如果服务器支持,直接换成Event MPM(异步处理模式),它能高效处理大量长连接,不会像Prefork那样被SSE拖垮;
  • KeepAliveTimeout不要设太长(比如5秒),但这个对SSE本身影响不大,重点还是进程数和Session锁。

3. 确保输出缓冲彻底关闭

PHP的输出缓冲会把推送的内容攒着不发,导致SSE连接一直挂着,也可能间接加重进程占用。确保:

  • 在php.ini里把output_buffering设为Off;
  • 在SSE代码开头加上ob_end_flush()关闭默认缓冲,每次推送后必须调用ob_flush()和flush()强制输出。

4. 进阶方案:用Nginx反向代理或专门的SSE服务

Apache+PHP的组合天生不擅长处理大量长连接,如果你的聊天场景用户量较大,建议:

  • 用Nginx做反向代理,让Nginx处理SSE的长连接,PHP只负责生成推送数据;
  • 或者直接用Node.js/Go这类更适合长连接的语言来单独处理SSE服务,PHP作为后端接口提供数据。

内容的提问来源于stack exchange,提问作者Sergey Shirnin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 10:30:32