【异常解决】org.springframework.web.context.request.async.AsyncRequestNotUsableException: ServletOutputStr
博主介绍:✌全网粉丝22W+,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌
技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物联网、机器学习等设计与开发。
感兴趣的可以先关注收藏起来,在工作中、生活上等遇到相关问题都可以给我留言咨询,希望帮助更多的人。
org.springframework.web.context.request.async.AsyncRequestNotUsableException: ServletOutputStream failed to flush: java.io.IOException: Broken pipe 异常解决
- 一、报错内容
- 二、原因分析
-
- 2.1 直接原因
- 2.2 触发场景
- 2.3 Spring 异步机制
- 三、解决方案
-
- 3.1 捕获异常并忽略(推荐)
- 3.2 设置超时时间
- 3.3 检查响应是否可写
- 3.4 调整服务器配置
- 四、根本问题排查
- 五、总结
一、报错内容
以下是报错内容详情:
org.springframework.web.context.request.async.AsyncRequestNotUsableException: ServletOutputStream failed to flush: java.io.IOException: Broken pipe at org.springframework.web.context.request.async.StandardServletAsyncWebRequest$LifecycleHttpServletResponse.handleIOException(StandardServletAsyncWebRequest.java:320) at org.springframework.web.context.request.async.StandardServletAsyncWebRequest$LifecycleServletOutputStream.flush(StandardServletAsyncWebRequest.java:392) at java.base/java.io.FilterOutputStream.flush(FilterOutputStream.java:153) at com.fasterxml.jackson.core.json.UTF8JsonGenerator.flush(UTF8JsonGenerator.java:1200) at com.fasterxml.jackson.databind.ObjectWriter.writeValue(ObjectWriter.java:1063) at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:483) at org.springframework.http.converter.AbstractGenericHttpMessageConverter.write(AbstractGenericHttpMessageConverter.java:114) at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:297) at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:192) at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:78) at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:136) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:926) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:831) at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903) at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:195) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344) at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:389) at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:904) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1741) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1190) at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63) at java.base/java.lang.Thread.run(Thread.java:842)Caused by: org.apache.catalina.connector.ClientAbortException: java.io.IOException: Broken pipe at org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:303) at org.apache.catalina.connector.OutputBuffer.flush(OutputBuffer.java:265) at org.apache.catalina.connector.CoyoteOutputStream.flush(CoyoteOutputStream.java:136) at org.springframework.web.context.request.async.StandardServletAsyncWebRequest$LifecycleServletOutputStream.flush(StandardServletAsyncWebRequest.java:389) ... 52 common frames omittedCaused by: java.io.IOException: Broken pipe at java.base/sun.nio.ch.FileDispatcherImpl.write0(Native Method) at java.base/sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:62) at java.base/sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:132) at java.base/sun.nio.ch.IOUtil.write(IOUtil.java:97) at java.base/sun.nio.ch.IOUtil.write(IOUtil.java:53) at java.base/sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:532) at org.apache.tomcat.util.net.NioChannel.write(NioChannel.java:122) at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.doWrite(NioEndpoint.java:1378) at org.apache.tomcat.util.net.SocketWrapperBase.doWrite(SocketWrapperBase.java:764) at org.apache.tomcat.util.net.SocketWrapperBase.flushBlocking(SocketWrapperBase.java:728) at org.apache.tomcat.util.net.SocketWrapperBase.flush(SocketWrapperBase.java:712) at org.apache.coyote.http11.Http11OutputBuffer$SocketOutputBuffer.flush(Http11OutputBuffer.java:559) at org.apache.coyote.http11.filters.ChunkedOutputFilter.flush(ChunkedOutputFilter.java:157) at org.apache.coyote.http11.Http11OutputBuffer.flush(Http11OutputBuffer.java:216) at org.apache.coyote.http11.Http11Processor.flush(Http11Processor.java:1244) at org.apache.coyote.AbstractProcessor.action(AbstractProcessor.java:400) at org.apache.coyote.Response.action(Response.java:208) at org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:299) ... 55 common frames omitted
这个错误 org.springframework.web.context.request.async.AsyncRequestNotUsableException: ServletOutputStream failed to flush: java.io.IOException: Broken pipe
通常发生在 Spring Web 异步请求处理 过程中,客户端(如浏览器、移动端或 API 调用方)在服务器尚未完成响应时提前关闭了连接(如刷新页面、取消请求或网络中断),导致服务器尝试写入数据时发现连接已断开(Broken pipe
)。
二、原因分析
2.1 直接原因
客户端主动断开连接(TCP RST 包),但服务器仍在尝试通过 ServletOutputStream
写入数据。
2.2 触发场景
-
长轮询(
Long Polling
)或SSE(Server-Sent Events)
请求被客户端取消。 -
前端页面跳转或用户手动刷新。
-
网络不稳定(如移动端切换网络)。
-
服务器响应超时,客户端主动超时断开。
2.3 Spring 异步机制
当使用 @Async、DeferredResult 或 Callable
时,Spring 会在独立线程中处理请求。如果客户端断开,服务器线程可能仍在执行,最终尝试刷新响应时抛出此异常。
三、解决方案
3.1 捕获异常并忽略(推荐)
如果是非关键业务(如日志、通知推送),可以直接捕获异常并忽略:
import org.springframework.web.context.request.async.AsyncRequestNotUsableException;@RestControllerpublic class AsyncController { @GetMapping(\"/async-data\") public DeferredResult<String> getAsyncData() { DeferredResult<String> deferredResult = new DeferredResult<>(); new Thread(() -> { try { // 模拟耗时操作 Thread.sleep(3000); deferredResult.setResult(\"Data loaded!\"); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } catch (AsyncRequestNotUsableException e) { // 客户端已断开,忽略异常 System.out.println(\"Client disconnected: \" + e.getMessage()); } }).start(); return deferredResult; }}
3.2 设置超时时间
为 DeferredResult 设置超时,避免长时间占用资源:
@GetMapping(\"/async-data\")public DeferredResult<String> getAsyncData() { DeferredResult<String> deferredResult = new DeferredResult<>(5000L); // 5秒超时 deferredResult.onTimeout(() -> { System.out.println(\"Request timeout\"); }); deferredResult.onError((Throwable t) -> { if (t instanceof AsyncRequestNotUsableException) { System.out.println(\"Client disconnected\"); } }); // 异步处理逻辑... return deferredResult;}
3.3 检查响应是否可写
在写入响应前检查连接状态:
if (!deferredResult.isSetOrExpired()) { deferredResult.setResult(\"Data\");} else { System.out.println(\"Response already closed\");}
3.4 调整服务器配置
- Tomcat:在 application.properties 中调整连接超时:
server.tomcat.connection-timeout=5000 # 5秒
- Undertow:禁用异步请求的 Broken pipe 日志:
server.undertow.no-request-timeout=5000
四、根本问题排查
- 客户端行为:
检查前端代码是否意外取消请求(如 axios 的 CancelToken)。
确认网络稳定性(特别是移动端)。
- 服务器性能:
如果服务器处理过慢,优化异步任务逻辑(如数据库查询、外部 API 调用)。
使用熔断机制(如 Hystrix 或 Resilience4j)避免长时间阻塞。
- 日志监控:
记录完整的异常堆栈,分析断开时的上下文:
catch (AsyncRequestNotUsableException e) { log.error(\"Client disconnected during async processing\", e);}
五、总结
如果问题持续,建议结合 APM 工具(如 SkyWalking、New Relic
)监控异步请求的生命周期,定位客户端断开的具体原因。
好了,今天分享到这里。希望你喜欢这次的探索之旅!不要忘记 “点赞” 和 “关注” 哦,我们下次见!🎈
本文完结!
祝各位大佬和小伙伴身体健康,万事如意,发财暴富,扫下方二维码与我一起交流!!!