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

Spring SSE应用Firefox接收首条数据后连接被关闭求助

Spring SSE连接在Firefox接收首条数据后断开的排查方案

我太懂这种卡了两周找不到突破口的感觉了!咱们来一步步拆解这个问题——你遇到的EofException本质是浏览器主动断开了连接,而Firefox在收到第一条数据就断,大概率是SSE协议规范没满足或者响应头/配置有问题,下面是几个你可以立刻排查的方向:

1. 先确认SSE响应头是否完全合规

SSE对响应头有严格要求,少一个都可能导致浏览器直接断开:

  • 必须设置 Content-Type: text/event-stream,且不能带字符编码以外的额外参数
  • 必须禁用缓存:Cache-Control: no-cache 或者 Cache-Control: no-store
  • 绝对不能设置 Content-Length(SSE是流式传输,固定长度会让浏览器认为数据已传输完成)
  • 建议补充设置 Connection: keep-alive

你可以打开浏览器的Network面板,查看这条SSE请求的响应头,核对有没有不符合的地方。虽然Spring的SseEmitter默认会处理这些规则,但如果你手动修改过头信息,可能不小心破坏了规范。

2. 检查第一条数据的格式是否符合SSE规范

这是最容易踩坑的点!SSE的每条消息必须遵循固定格式:

data: 你的内容\n\n

哪怕你要发送JSON数据,也得用data:前缀包裹,比如:

data: {"id":1,"content":"hello"}\n\n

你现在调用的E1.send(value,MediaType.APPLICATION_JSON);存在一个隐藏问题:Spring的SseEmitter.send(Object, MediaType)会用消息转换器把对象转成JSON,但不会自动加上SSE要求的data:前缀和换行符!这就导致Firefox收到的是纯JSON,不是合法的SSE消息,直接判定连接异常断开了。

解决方法有两种:

  • 手动把JSON包装成SSE格式字符串再发送:
    String sseMessage = "data: " + objectMapper.writeValueAsString(value) + "\n\n";
    E1.send(sseMessage, MediaType.TEXT_PLAIN);
    
  • 用Spring提供的SseEventBuilder构建消息,它会自动处理格式:
    SseEventBuilder event = SseEmitter.event()
            .data(value, MediaType.APPLICATION_JSON);
    E1.send(event);
    

3. 排查Jetty的连接超时配置

如果头和格式都没问题,那可能是Jetty的idle超时设置太短。默认情况下Jetty的idle超时可能是30秒,如果第一条数据发送后没有后续心跳消息,Firefox可能会主动断开连接。你可以在Spring Boot配置里加长超时时间:

server.jetty.idle-timeout=300000 # 设为5分钟

同时建议定期发送心跳消息(比如每隔15秒发一条空的data: \n\n),保持连接活跃。

4. 排除Firefox本身的干扰

  • 试试用隐私模式打开页面,排除浏览器插件拦截长连接的可能
  • 检查about:config里的网络设置:
    • network.http.keep-alive.timeout:确保设得足够长(比如600秒)
    • network.http.connection-timeout:不要设得太短

附:你提供的报错日志

org.eclipse.jetty.io.EofException 
at org.eclipse.jetty.io.ChannelEndPoint.flush(ChannelEndPoint.java:292) 
at org.eclipse.jetty.io.WriteFlusher.flush(WriteFlusher.java:429) 
at org.eclipse.jetty.io.WriteFlusher.write(WriteFlusher.java:322) 
at org.eclipse.jetty.io.AbstractEndPoint.write(AbstractEndPoint.java:372) 
at org.eclipse.jetty.server.HttpConnection$SendCallback.process(HttpConnection.java:750) 
at org.eclipse.jetty.util.IteratingCallback.processing(IteratingCallback.java:241) 
at org.eclipse.jetty.util.IteratingCallback.iterate(IteratingCallback.java:224) 
Caused by: java.io.IOException: An established connection was aborted by the software in your host machine 
at sun.nio.ch.SocketDispatcher.writev0(Native Method) 
at sun.nio.ch.SocketDispatcher.writev(SocketDispatcher.java:55) 
at sun.nio.ch.IOUtil.write(IOUtil.java:148) 
at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:503) 
at org.eclipse.jetty.io.ChannelEndPoint.flush(ChannelEndPoint.java:272) 
... 29 more

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:26:03