使用EventSource时客户端JS被阻塞的问题求助
问题分析与解决建议
你的问题核心是SSE(Server-Sent Events)长连接阻塞了同域名下的其他AJAX请求,根源在于PHP端的SSE脚本没有正确实现分块传输编码,导致浏览器的并发连接槽位被长期占用,无法处理其他请求。以下是具体解决步骤:
1. 修正PHP SSE脚本的核心逻辑
必须确保SSE脚本正确发送响应头、定期输出心跳包并强制刷新缓冲区,让浏览器知道连接处于活跃状态但不会占用请求槽位。
修改newmessage2.php代码如下:
<?php // 设置SSE必备响应头 header('Content-Type: text/event-stream'); header('Cache-Control: no-cache'); header('Connection: keep-alive'); header('X-Accel-Buffering: no'); // 禁用Nginx等代理的缓冲,确保实时输出 // 关闭PHP输出缓冲,确保数据立即发送 if (ob_get_level() > 0) { ob_end_flush(); } flush(); // 循环监听新消息,同时定期发送心跳 while (true) { // 业务逻辑:检查是否有新的呼叫消息 $newCall = getNewCallData(); // 替换为你的实际查询逻辑 if ($newCall) { // 发送NewCall事件 echo "event: NewCall\n"; echo "data: " . json_encode($newCall) . "\n\n"; flush(); } // 发送心跳包(浏览器会自动忽略以":"开头的注释行) echo ": ping\n\n"; flush(); // 休眠5秒,避免CPU占用过高 sleep(5); } // 示例业务函数:模拟获取新呼叫数据 function getNewCallData() { // 这里替换为你的实际逻辑,比如查询数据库/缓存 return rand(0, 10) > 7 ? ['id' => uniqid(), 'content' => '新呼叫通知'] : null; }
2. 客户端代码补充(可选但建议)
原JS代码无需大改,可添加错误监听确保SSE连接异常时自动重连:
var sourceCallUpdater = new EventSource("./js/newmessage2.php"); sourceCallUpdater.addEventListener('NewCall', (e) => { // 处理新消息的逻辑 const callData = JSON.parse(e.data); console.log('收到新呼叫:', callData); // 这里写更新页面的代码 }); // 监听SSE连接错误,确保异常时自动重连 sourceCallUpdater.addEventListener('error', (e) => { if (e.readyState === EventSource.CLOSED) { console.log('SSE连接断开,浏览器将自动重连'); } else { console.error('SSE连接出错:', e); } });
3. 关键原理说明
浏览器对同一域名的HTTP/1.1并发连接数默认限制为6个,若SSE脚本未正确分块输出,连接会一直处于"pending"状态,占用1个连接槽位。当你调用GotoPage发起AJAX请求时,会被排队等待槽位释放,直到SSE连接发送数据或断开。
通过定期发送心跳包并强制刷新缓冲区,浏览器会确认连接活跃但不会阻塞其他请求,同时避免连接因超时被断开。
内容的提问来源于stack exchange,提问作者Robert Goth
相关产品推荐
相关产品推荐

