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

PHP Server-Sent Events导致其他请求阻塞问题求助

SSE连接导致其他请求阻塞的问题排查与解决

问题描述

我在PHP服务器上实现了一个简单的SSE端点,在Angular应用中通过Azure Event Source订阅它,以此在请求中发送自定义请求头。连接本身可正常工作,也能收到流数据,但一旦建立SSE连接,其他所有请求都会被阻塞,处于“Pending”状态,直到关闭SSE端点的连接。我已尝试使用session_write_close();但无济于事,希望找到不影响其他请求的解决方案。

PHP服务端实现

public function newSSEEvent()
{
    session_write_close();
    header("Content-Type: text/event-stream");
    header("Cache-Control: no-store");
    $counter = rand(1, 10);
    while (true) {
           echo "event: Date\n";
           $curDate = date(DATE_ISO8601);
           echo 'data: {"time": "' . $curDate . '"}';
           echo "\n\n";
 
        $counter--;
        if (!$counter) {
            echo "event: Ping\n";
            echo 'data: Last Ping' . $curDate . "\n\n";
            $counter = rand(1, 10);
        }
        ob_flush();
        flush();
        sleep(1);
    }
}

Angular客户端实现

async getEvent(url) {
    await fetchEventSource(
      url,
      {
        method: "GET",
        headers: {
          // 自定义请求头
        },
        onmessage(ev) {
          console.log(ev);
        },
      }
    );
}

解决方案建议

1. 确保Session完全关闭

虽然调用了session_write_close(),但要确认它在任何可能触发Session启动的代码之后执行,且后续代码不再操作Session。如果使用框架(如Laravel),框架可能自动启动Session,需将session_write_close()放在输出响应头之前,确保Session锁被释放。

2. 强制清理输出缓冲区

部分服务器配置会强制开启output_buffering,导致ob_flush()和flush()无法及时输出内容。可在代码开头添加:

ob_end_clean(); // 关闭并清空所有层级的输出缓冲区

也可在php.ini中设置output_buffering = Off(需服务器权限)。

3. 优化服务端循环逻辑

PHP同步阻塞式循环会占用单个进程/线程,在Apache prefork模式下,进程数有限时会导致其他请求排队:

  • 加入客户端断开检测,避免无效进程占用:
    if (connection_aborted()) {
        break;
    }
    
  • 改用PHP-FPM动态进程管理,确保有足够空闲进程处理其他请求;
  • 长期方案:使用Swoole/Workerman等异步框架实现SSE,从根源解决阻塞问题。

4. 规避浏览器并发限制

浏览器对同一域名的并发请求数有限(通常为6个),SSE连接会占用一个名额。可:

  • 将SSE请求放在独立子域名下,绕过同一域名的并发限制;
  • 客户端避免用await阻塞主线程(当前代码的await仅影响函数本身,不影响其他请求,主要问题仍在服务端)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 10:46:18