PHP用while(true)实现SSE时其他功能被冻结无法并行运行如何解决
问题根因
- 会话锁阻塞:PHP默认开启会话后会独占会话文件锁,同一个客户端发起的所有请求都需要等前一个请求释放锁后才能执行,你的SSE接口一直持有会话锁不释放,自然会卡住同客户端的其他请求。
- 进程资源占满:如果用php-fpm部署,每个SSE长连接会占用一个fpm进程持续运行,当可用fpm进程被占满后,新的请求只能排队等待,也会出现冻结现象。
解决方案
- 优先处理会话锁问题
如果你的SSE接口不需要在循环中读写会话数据,在进入while循环前主动释放会话锁即可解决90%的同客户端请求阻塞问题,修改后的代码如下:
// 进入循环前主动释放会话锁,不影响后续逻辑执行 session_write_close(); while (true) { echo $this->event->fill(); ob_flush(); flush(); if (connection_aborted()) { return; } sleep($interval); }
- 优化部署配置
- 调大php-fpm的最大进程数,预留足够进程处理普通业务请求,避免SSE长连接占满所有资源。
- 生产环境推荐使用Swoole、Workerman这类异步常驻框架承载SSE服务,这类框架是事件驱动模式,单进程即可处理数千个并发长连接,不会阻塞其他业务接口运行。
- 服务隔离
如果SSE使用量较大,可以单独拆分SSE服务独立部署,和普通业务接口使用不同的端口/域名,完全避免互相影响。
内容的提问来源于stack exchange,提问作者h h
相关产品推荐
相关产品推荐

