案发现场
问题:
org.springframework.web.context.request.async.AsyncRequestNotUsableException: ServletOutputStream failed to write: Broken pipe
org.springframework.web.context.request.async.AsyncRequestNotUsableException: ServletOutputStream failed to write: Broken pipeat org.springframework.web.context.request.async.StandardServletAsyncWebRequest$LifecycleHttpServletResponse.handleIOExceptionquest.java:343) ~[spring-web-6.1.15.jar!/:6.1.15]at org.springframework.web.context.request.async.StandardServletAsyncWebRequest$LifecycleServletOutputStream.write(StandardSer01) ~[spring-web-6.1.15.jar!/:6.1.15]at java.base/java.io.OutputStream.write(OutputStream.java:127) ~[na:na]at org.springframework.util.StreamUtils.copy(StreamUtils.java:117) ~[spring-core-6.1.15.jar!/:6.1.15]at org.springframework.http.converter.ByteArrayHttpMessageConverter.writeInternal(ByteArrayHttpMessageConverter.java:67) ~[spr5]at org.springframework.http.converter.ByteArrayHttpMessageConverter.writeInternal(ByteArrayHttpMessageConverter.java:38) ~[spr5]at org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:235) ~[spring-web-6at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbodProcessor.java:300) ~[spring-webmvc-6.1.15.jar!/:6.1.15]at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseB2) ~[spring-webmvc-6.1.15.jar!/:6.1.15]at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueH[spring-web-6.1.15.jar!/:6.1.15]at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerwebmvc-6.1.15.jar!/:6.1.15]at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandleg-webmvc-6.1.15.jar!/:6.1.15]at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapmvc-6.1.15.jar!/:6.1.15]at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spri.15]
从你提供的错误日志来看,问题的核心是 AsyncRequestNotUsableException
和 Broken pipe
。以下是问题的原因和解决方法:
问题原因
-
Broken pipe 错误:这个错误通常发生在客户端与服务器之间的连接被意外中断时。例如,客户端可能在服务器尝试写入响应之前关闭了连接。
-
AsyncRequestNotUsableException:当尝试在一个已经完成或失败的异步请求中继续操作时,会抛出此异常。
解决方法
-
检查客户端行为:
-
确保客户端在请求过程中不会主动关闭连接。例如,客户端可能在获取响应之前就关闭了连接,导致服务器端抛出
Broken pipe
。 -
如果客户端是浏览器,检查是否有脚本或插件可能导致连接中断。
-
-
优化服务器端逻辑:
-
在写入响应之前,检查客户端连接是否仍然可用。可以使用
HttpServletResponse.isCommitted()
方法来判断响应是否已经提交。 -
如果检测到连接已中断,可以捕获
IOException
并记录日志,而不是抛出异常。
-
-
调整超时设置:
-
如果服务器端的异步处理时间较长,可以适当增加超时时间。例如,设置
AsyncContext.setTimeout()
。 -
对于 Tomcat 服务器,可以在
server.xml
中调整connectionTimeout
和asyncTimeout
。
-
-
捕获并处理异常:
-
在代码中捕获
AsyncRequestNotUsableException
和IOException
,并进行适当的处理。例如:
-
try {// 写入响应逻辑
} catch (IOException e) {// 处理 Broken pipe 异常log.warn("Client disconnected before response was sent", e);
} catch (AsyncRequestNotUsableException e) {// 处理异步请求不可用异常log.warn("Async request is not usable", e);
}
检查网络问题:
-
如果问题频繁出现,可能是网络不稳定导致的。检查服务器和客户端之间的网络连接,确保没有中间设备(如防火墙、代理服务器)干扰