IIS下Server Sent Events无法实时推送问题求助
IIS下ASP.NET MVC 4.7.2 Server-Sent Events推送丢失问题解决
我有一个基于ASP.NET Framework 4.7.2的MVC Web应用,用Server Sent Events(JavaScript的EventSource)实现服务器向客户端推送数据,明确不使用SignalR。在IIS Express上功能完全正常,但部署到IIS 10.0.22621.1554(Win11)后,仅约半数推送能到达浏览器,无固定规律,怀疑是IIS的缓存或缓冲机制导致。
当前代码
服务端C#控制器代码
[HttpGet] public void Connect() { Response.ContentType = "text/event-stream"; Response.CacheControl = "no-cache"; Response.AddHeader("connection", "keep-alive"); Response.Expires = -1; Response.Buffer = false; Response.BufferOutput = false; Response.Write("data: initialized\n\n"); Response.Flush(); var clientDisconnectedToken = Response.ClientDisconnectedToken; var client = ServerEventsHandler.Connect(currentUser); var cancelled = false; while (!cancelled && !clientDisconnectedToken.IsCancellationRequested) { var data = client.WaitForData(clientDisconnectedToken, out cancelled); if (!cancelled && !clientDisconnectedToken.IsCancellationRequested && data != null && data.Length > 0) { foreach (var item in data) { Response.Write($"data: {item.Data}\n\n"); Response.Flush(); } } } ServerEventsHandler.Disconnect(client); Response.Close(); }
客户端JavaScript代码
const url = "/ServerEvents/Connect"; const connection = new EventSource(url, { withCredentials: true }); connection.addEventListener("message", (e) => { // do stuff ... }, false);
已尝试无效的操作
在web.config中禁用text/event-stream的动态压缩:
<httpCompression> <dynamicTypes> <add mimeType="text/event-stream" enabled="false" /> </dynamicTypes> </httpCompression>
解决方案
1. 强化服务端响应头,彻底禁用缓冲
在服务端Connect方法开头,添加更严格的缓存和缓冲禁用头部:
Response.AddHeader("X-Accel-Buffering", "no"); // 禁用反向代理/中间件缓冲 Response.AddHeader("Cache-Control", "no-cache, no-store, must-revalidate"); Response.AddHeader("Pragma", "no-cache"); Response.Expires = 0; // 覆盖原有的-1设置,确保过期时间为0
这些头部能强制IIS和任何中间件不缓冲SSE响应,保证数据实时推送。
2. 调整IIS应用程序池配置
打开IIS管理器,找到对应应用的应用程序池,进入高级设置:
- 把队列长度设为1000以上,避免长连接被队列拒绝
- 关闭快速失败保护(启用设为False),防止应用池因长时间连接被误回收
- 设置**闲置超时(分钟)**为0,禁用闲置超时,保持长连接存活
3. 彻底禁用SSE内容的动态压缩
仅web.config的局部设置可能无效,需要确保服务器级和应用级都禁用:
在web.config的<system.webServer>节点下添加完整配置:
<system.webServer> <urlCompression doDynamicCompression="false" /> <httpCompression> <dynamicTypes> <remove mimeType="text/event-stream" /> <add mimeType="text/event-stream" enabled="false" /> </dynamicTypes> </httpCompression> </system.webServer>
如果需要保留其他动态内容压缩,可只保留<remove>和<add>节点,把doDynamicCompression设为True。
4. 添加心跳包防止连接空闲缓冲
IIS会对长时间无数据的连接进行缓冲,添加定期心跳包能保持连接活跃:
修改服务端循环逻辑,加入心跳超时处理:
while (!cancelled && !clientDisconnectedToken.IsCancellationRequested) { var timeoutTask = Task.Delay(30000); // 每30秒发一次心跳 var dataTask = Task.Run(() => client.WaitForData(clientDisconnectedToken, out cancelled)); var completedTask = Task.WhenAny(timeoutTask, dataTask); if (completedTask == timeoutTask) { // 发送SSE注释作为心跳,不会触发客户端message事件 Response.Write(": heartbeat\n\n"); Response.Flush(); } else { var data = dataTask.Result; if (!cancelled && !clientDisconnectedToken.IsCancellationRequested && data != null && data.Length > 0) { foreach (var item in data) { Response.Write($"data: {item.Data}\n\n"); Response.Flush(); } } } }
内容的提问来源于stack exchange,提问作者mrsubwoof
相关产品推荐
相关产品推荐

