SSL+tomcat8下 websocket报出java.io.IOException: Broken pipe问题

本文记录了一次在服务器上部署应用时遇到的Tomcat管道爆裂异常问题,该问题表现为客户端主动断开连接时出现IOException。通过排查日志及代码,最终在Apache官方论坛找到解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

错误日志信息

客户端主动关闭连接!
服务端主动关闭连接清除通道缓存开始....
2018-08-22 16:31:32.810  INFO 20725 --- [nio-8848-exec-5] com.faybd.core.socket.Cache              : 有Socket(WebSocket)连接断开,当前连接数:0
2018-08-22 16:31:32.932  INFO 20725 --- [nio-8848-exec-5] o.a.t.w.s.WsRemoteEndpointImplServer     : Failed to close the ServletOutputStream connection cleanly

java.io.IOException: Broken pipe
        at sun.nio.ch.FileDispatcherImpl.write0(Native Method)
        at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:47)
        at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93)
        at sun.nio.ch.IOUtil.write(IOUtil.java:51)
        at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:471)
        at org.apache.tomcat.util.net.SecureNioChannel.flush(SecureNioChannel.java:140)
        at org.apache.tomcat.util.net.SecureNioChannel.close(SecureNioChannel.java:399)
        at org.apache.tomcat.util.net.SecureNioChannel.close(SecureNioChannel.java:413)
        at org.apache.coyote.http11.upgrade.NioServletOutputStream.doClose(NioServletOutputStream.java:138)
        at org.apache.coyote.http11.upgrade.AbstractServletOutputStream.close(AbstractServletOutputStream.java:140)
        at org.apache.tomcat.websocket.server.WsRemoteEndpointImplServer.doClose(WsRemoteEndpointImplServer.java:142)
        at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.close(WsRemoteEndpointImplBase.java:638)
        at org.apache.tomcat.websocket.WsSession.onClose(WsSession.java:526)
        at org.apache.tomcat.websocket.WsFrameBase.processDataControl(WsFrameBase.java:342)
        at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:284)
        at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:130)
        at org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:60)
        at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler$WsReadListener.onDataAvailable(WsHttpUpgradeHandler.java:183)
        at org.apache.coyote.http11.upgrade.AbstractServletInputStream.onDataAvailable(AbstractServletInputStream.java:198)
        at org.apache.coyote.http11.upgrade.AbstractProcessor.upgradeDispatch(AbstractProcessor.java:96)
        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:669)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:748)

 

当我在本地运行没有发现这个问题,上服务器后才存在这个问题,根据操作及日志是在客户端主动关闭连接时发生的一个管道爆裂异常。 但日志上面的信息定位不到具体的问题。code了所有可疑代码都没排查到问题的所在。最后在apache网站找到了跟我遇到同样问题的老兄

http://mail-archives.apache.org/mod_mbox/tomcat-dev/201602.mbox/%3C152f32d902c.1153d042c48123.1931297950055756927@eatmeals.ca%3E

算是tomcat8的一个坑吧

### Java WebSocket 中 `java.io.IOException: Broken pipe` 的解决方案 在 Java WebSocket 应用程序中遇到 `java.io.IOException: Broken pipe` 错误通常是由于客户端与服务器之间的连接中断引起的。以下是可能的原因以及对应的解决方案: #### 1. **网络不稳定或超时** 如果客户端和服务器之间存在长时间的无数据传输状态,可能会触发防火墙或其他中间设备关闭连接。可以通过设置心跳机制来保持连接活跃。 ```java // 设置心跳消息发送间隔时间(单位:毫秒) session.getBasicRemote().sendText("{\"type\":\"heartbeat\"}"); ``` 通过定期向对方发送心跳包可以有效防止因超时而导致的断开[^1]。 #### 2. **客户端主动断开连接** 当客户端突然退出或者强制终止应用程序时,可能导致未完成的数据写入操作失败并抛出此异常。为了减少影响,在编写代码逻辑时应捕获此类异常并优雅地处理它们。 ```java try { session.getBasicRemote().sendText(message); } catch (IOException e) { System.err.println("Failed to send message due to IOException."); } ``` 这样即使发生管道破裂也不会导致整个应用崩溃[^2]。 #### 3. **服务端负载过高** 正如提到过的那样,当 Tomcat 或其他容器承受过多并发请求超过其配置容量时会拒绝部分新来的链接尝试从而引发类似的错误提示信息。“Broken Pipe”在这种情况下表示试图往已经被关闭的方向继续写入内容所致的结果。因此优化性能参数比如调整最大线程数(maxThreads),最小空闲线程(minSpareThreads)等都是必要的措施之一;另外还可以考虑升级硬件设施以满足更高的访问量需求[^2]。 #### 4. **不匹配版本间兼容性问题** 确保所使用的库文件与其依赖项均处于相同的主要发行版系列之内非常重要。不同版本间的细微差异有时会造成意想不到的行为表现形式即所谓的“broken pipe”。查阅官方文档确认当前项目里涉及到的所有组件是否都遵循一致的标准规范是非常关键的一个环节。 --- ### 示例代码片段展示如何实现简单的WebSocket通信及异常捕捉 下面给出一段基础示例用于演示基本功能的同时也包含了对于可能出现的各种状况下的应对策略: ```java @ServerEndpoint("/websocket") public class MyWebSocket { @OnOpen public void onOpen(Session session){ System.out.println("Connected ... "+session.getId()); } @OnMessage public String onMessage(String message, Session session){ try{ // Simulate some processing delay. Thread.sleep(50L); if(!session.isOpen()){ throw new RuntimeException("Session closed unexpectedly"); } return "Received '"+message+"'"; }catch(Exception ex){ return "Error occurred while handling your request."; } } @OnError public void onError(Throwable error){ System.err.println("Error happened:"+error.getMessage()); } @OnClose public void onClose(){ System.out.println("Closed!"); } } ``` 以上例子展示了标准的生命周期方法定义方式,并且加入了简单的延迟模拟实际业务场景中的耗时过程。同时针对潜在的风险做了初步防护设计——检查会话状态并在必要时候提前返回友好型反馈给调用方知道出现了什么情况而不是让原始堆栈轨迹暴露出去。 ---
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值