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

Spring Framework 6.0.23升级至6.1.0后出现ServletOutputStream写入失败问题

Spring 6.1升级后JBoss EAP 8中ServletOutputStream提前关闭(UT010029)问题分析

问题场景

项目基于JBoss EAP 8,将Spring Framework从6.0.23升级至6.1.0后,控制器出现UT010029: Stream is closed异常,日志显示根源为org.springframework.web.context.request.async.AsyncRequestNotUsableException,最终指向io.undertow.servlet.spec.ServletOutputStreamImpl写入时流已关闭。

为复现问题编写测试接口:

@RequestMapping(value = "/xxx/xxx", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
@ResponseBody
public String xxx(HttpServletRequest request, HttpServletResponse response, @RequestBody String jsonText)
        throws Throwable {
    // 模拟长时间业务处理
    Thread.sleep(100000);
    // ... 业务逻辑
    return jsonTextRslt;
}

测试结果对比:

  • Spring 6.0版本:等待100秒后正常返回200 OK;
  • Spring 6.1版本:请求处理到90秒时流被关闭,100秒后触发写入失败异常。

原因分析

  1. Undertow默认超时设置:JBoss EAP 8中Undertow子系统的read-timeout默认值为90秒,该参数原本控制服务器读取客户端请求数据的超时,但在Spring 6.1的逻辑下,请求处理阶段的时长也会触发该检测——当服务器处理请求的时间超过90秒,Undertow会主动关闭连接流。
  2. Spring 6.1的逻辑调整:Spring Framework 6.1对请求生命周期管理做了优化,新增了对容器连接状态的严格检测。当Undertow因超时关闭流后,Spring会立即识别到请求已不可用,抛出AsyncRequestNotUsableException;而Spring 6.0版本未实现该级别的检测,即使流已关闭,仍会尝试写入响应,最终侥幸完成返回(实际这是潜在的不稳定因素)。

解决方案合理性验证

通过修改JBoss的domain.xml或standalone.xml中Undertow子系统的http-listener,添加read-timeout="120000"(120秒)的方案是合理且符合规范的:

  • 该配置直接覆盖Undertow的默认超时,确保业务最长处理时间(100秒)在超时范围内,避免流被提前关闭;
  • 配置需根据实际业务场景调整:若存在更长时间的处理逻辑,需同步延长read-timeout值,但不建议设置过长,避免闲置连接占用服务器资源;
  • 此方案本质是让容器的超时策略适配业务需求,而非修改Spring核心逻辑,属于容器层面的标准配置调整,无侵入性且易于维护。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 19:03:19