Broken Pipe
Broken Pipe发生的原因
当某个进程试图往一个已收到RST的SOCKET连接写数据,就会出现Broken Pipe。
(由于TCP协议层已经处于RST状态了,因此不会将数据发出,而是发一个SIGPIPE信号给应用层,SIGPIPE信号的缺省处理动作是终止程序。)
那么确定什么时候TCP会发送RST报文段,就可以确定Broken Pipe发生的具体原因。
之前已经分析了TCP RST报文产生的几种情景了。
原因分析
broken pipe出现的前提条件是进程试图往一个已经在RST状态的TCP连接写入数据。
那么这个写入数据,到底应该怎么理解呢?到底是进程试图往本地SendQ发送缓存区写入数据还是TCP协议试图将SendQ的数据发送到对端的RecvQ呢?按照字面意思应该是前者。
之前我们已经分析了几种会出现RST报文的情况。
结合我们出现该异常的接口分析。我们发现我们出错的接口,返回的数据,最小的8K多,最大的超过128K。查阅了几天的异常日志,都没有发现一个报出broken pipe异常错误的接口的返回数据小于8K。
根据RST报文产生的情况,我们可以做出如下推断,当Client端与我们的服务器建立了TCP链接之后。当TCP协议将服务端SendQ队列里的内容发送到对端(Client)的ReceQ队列中后,Client关闭了进程,此时ReceQ 读取缓存区还有数据未被读取(不管ReceQ的数据Client端有没有读取过,也不管TCP将多少服务端的数据发到了ReceQ,总之,就是在关闭的时候,还有数据存在于读取缓存区中),这时候关闭socket,会导致端Client端产生一个RST重置报文。
这时候服务端的数据还没有写完,会继续写入,当再次写入的时候,TCP协议已经是RST状态的了,这个时候,就会发生broken pipe。
上面的推论能够解释broken pipe发生的一整个流程。
那我们来查看下linux服务器的默认SendQ大小与我们接口返回的数据大小的对比,就能够是否确实是这些接口的数据写入都需要多次写入缓存区。
那么如何查看linux默认的SendQ缓冲区大小呢。linux给我们提供了相应的命令
ubuntu@VM-104-50-ubuntu:/data/iyourcar$ cat /proc/sys/net/ipv4/tcp_wmem
4096 16384 4194304最小 默认 最大
我们发现,默认写缓存区大小是16k,可是我们的接口返回的数据最小的是8k多呀,这个接口返回的数据是可以一次写入缓存区的呀。咋回事呀,怎么这样也会broken呢。如果服务端一次性写入16k数据到写缓存区,那么是不可能出现broken pipe的呀。那只能证明我们的程序并不是一次性写入16k的数据给缓存区,这个大小肯定是要比8k多要小的。那我们就来求证一下,用一个会报出异常的接口在出现异常的地方进行debug,主要debug写入数据的流程。
使用的内置容器是Tomcat
OutputBuffer#appendByteArray
public static final int DEFAULT_BUFFER_SIZE = 8 * 1024;public OutputBuffer() {this(DEFAULT_BUFFER_SIZE);}private void appendByteArray(byte src[], int off, int len) throws IOException {if (len == 0) {return;}int limit = bb.capacity();//我们发现,每一次写入的字节数bb.capacity()大小,而默认的capacity大小就是8*1024,也就是8kwhile (len >= limit) {realWriteBytes(ByteBuffer.wrap(src, off, limit));len = len - limit;off = off + limit;}if (len > 0) {transfer(src, off, len, bb);}}
我们发现,实际上,tomcat帮我们向socket写入数据的时候,是每8k写入一次SendQ(但是真正TCP发送数据,可能是分很多块去发送到对端的ReceQ的)
后来我们将内置web容器换成了undertow,发现依旧会发生这种情况,应该默认也是一次写入8k吧,具体还没有debug。
所以当使用的容器是tomcat的时候,只要接口返回数据的大小大于8k,就可能会出现broken pipe。
Broken Pipe相关推荐
- TNS-12518 Linux Error:32:Broken pipe
最近一周,有一台ORACLE数据库服务器的监听服务在凌晨2点过几分的时间点突然崩溃,以前从没有出现过此类情况,但是最近一周出现了两次这种情况,检查时发现了如下一些信息: $ lsnrctl servi ...
- JedisConnectionException: java.net.SocketException: Broken pipe
问题:redis一台,内存15g,32个现成共同操作redis!数据量160w,报出:JedisConnectionException: java.net.SocketException: Broke ...
- linux ssh 报错 Write failed: Broken pipe 解决方法
目录 原理 方法1:通过客户端配置 方法2:服务器端配置 方法3:临时SSH命令配置 总结 在使用SSH连接远程服务器的时候,如果长时间不操作,再次进入 Terminal 时就会有卡死一段时间没有响应 ...
- 服务器可以ping通,Write failed: Broken pipe
服务器可以ping通,ping无丢包,延迟很低,但是ssh连接的时候需要等一会然后显示admin@admin:~$ ssh 10.10.25.21 admin@10.10.25.21's passwo ...
- vm显示打不开 /dev/vmmon:Broken pipe
这个主要是vm打开时系统拒绝他说没有vmmon这个文件 因为是broken pipe.所以应该是通道性的问题 也就是vm给本机发送文件,本机未收到相应的信息.或是相反.所以先考虑到系统阻止访问到问题 ...
- java.io.IOException: Broken pipe 的异常处理
断开的管道 java.io.IOException: Broken pipe 解决方法 一.Broken pipe产生原因分析 1.当访问某个服务突然服务器挂了,就会产生Broken pipe; 2. ...
- 调用 usb_control_msg 返回错误值 -32, Broken pipe, 对 hidraw write时 返回错误值 -32, Broken pipe
-------------------Step 1--------------------- 如题,使用 libusb 对 hid 类设备进行控制传输的时候,有时会遇到此错误,但是实际上传输是成功的, ...
- 断开的管道 java.io.IOException: Broken pipe 解决方法
断开的管道 java.io.IOException: Broken pipe 解决方法 一.Broken pipe产生原因分析 1.当访问某个服务突然服务器挂了,就会产生Broken pipe; 2. ...
- gdb调试时,Program received signal SIGPIPE, Broken pipe.
今天在gdb调试时,发现总是出现Program received signal SIGPIPE, Broken pipe,搜索了网上的资料,发现是在调试时,接收到了SIGPIPE这个signal信号导 ...
- java.net.SocketException: Broken pipe问题解决
2019独角兽企业重金招聘Python工程师标准>>> javax.servlet.ServletException: ClientAbortException: java.net ...
最新文章
- win10 创建python虚拟环境
- 《IBM-PC汇编语言程序设计》(第2版)【沈美明 温冬婵】——第七章——自编解析与答案
- android 一个有漂亮动画效果的Dialog
- linux中yum与rpm区别
- DevOps的前世今生
- 阿里P8大佬亲自讲解!朝阳java培训
- .net 反编译_向.net/Unity 程序员推荐一个十分因吹斯听的网站:sharplab.io
- 不是我的错,也不是Atlas的!
- 动态链接库的隐式动态链接和显示动态链接
- Anders Hejlsberg谈C#、Java和C++中的泛型
- 自治系统中单个路由表的构造
- 上海工程技术大学c语言商店存货管理系统,商店存货管理系统课程设计.doc
- mysql如果索引为uid间隙锁_MySQL-浅析间隙锁
- 点云最小二乘法拟合空间直线
- 三种古典密码的认识(置换密码,代换密码和轮换密码)
- python处理grd格式文件_python基础
- Thinkpad笔记本键盘拆卸
- MoCo 动量对比学习——一种维护超大负样本训练的框架
- 如何通过 WhatsApp 开展营销活动?
- Android蓝牙开发系列文章-蓝牙mesh(一)