博主介绍:✌全网粉丝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 异常解决
一、报错内容
以下是报错内容详情:
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 omitted
Caused 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;
@RestController
public 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
)监控异步请求的生命周期,定位客户端断开的具体原因。
好了,今天分享到这里。希望你喜欢这次的探索之旅!不要忘记 “点赞” 和 “关注” 哦,我们下次见!🎈
本文完结!
祝各位大佬和小伙伴身体健康,万事如意,发财暴富,扫下方二维码与我一起交流!!!
转载自CSDN-专业IT技术社区
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_44299027/article/details/147067308