PHP实现Server-Sent Events无法逐次推送数据的解决办法
SSE推送延迟问题的解决方法
你遇到的问题核心是输出缓冲机制导致内容没有实时推送——不管是PHP本身还是Web服务器(Apache/Nginx)的缓冲,都会把你的输出暂时存起来,直到缓冲区满或者脚本结束才一次性发送给客户端。下面是具体的解决步骤和修正后的代码:
你的原始代码
客户端JS代码
const eventSource = new EventSource("http://localhost/sse_test.php"); eventSource.onmessage = function( event ) { console.log( event.data ) ; };
服务端PHP代码
header('Content-Type: text/event-stream'); header('Cache-Control: no-cache'); while ( true ) { echo 'data:'; $messages = time(); $messages = json_encode( $messages ); echo $messages; echo $a; // 这里$a未初始化,还会破坏SSE格式 echo "\n\n"; $a++; flush(); sleep(5); }
问题排查与修复
关闭PHP的输出缓冲
PHP默认开启输出缓冲,仅用flush()无法直接把内容推给客户端,需要先手动关闭:- 在脚本开头添加
ob_end_flush();:关闭当前的输出缓冲池 - 添加
ob_implicit_flush(true);:让后续的echo操作自动触发刷新,无需每次手动调用flush()
- 在脚本开头添加
修复代码中的错误
- 删掉多余的
echo $a;:这行会触发PHP Notice错误($a未初始化),还会破坏SSE的消息格式,导致客户端无法正确解析 - 若不需要$a变量,直接删掉所有相关代码即可
- 删掉多余的
禁用Web服务器的缓冲
- Apache环境:确保关闭
mod_deflate(Gzip压缩),或者在PHP脚本中添加header('Content-Encoding: none');强制禁用压缩,避免压缩功能缓冲输出 - Nginx环境:在对应接口的location配置中添加
proxy_buffering off;,禁用Nginx的代理缓冲
- Apache环境:确保关闭
修正后的PHP代码
<?php header('Content-Type: text/event-stream'); header('Cache-Control: no-cache'); header('Content-Encoding: none'); // 禁用压缩,避免服务器缓冲 // 关闭PHP输出缓冲 ob_end_flush(); ob_implicit_flush(true); while (true) { // 构造符合SSE规范的消息 echo 'data: ' . json_encode(time()) . "\n\n"; sleep(5); } ?>
这样修改后,客户端就能每5秒收到一次时间戳,无需放弃SSE改用HTTP轮询。
内容的提问来源于stack exchange,提问作者Quentin Régnier
相关产品推荐
相关产品推荐

