java.net.SocketException: Broken pipe

测试环境没有报错,生产环境每天都有几条这样的报错,网上查了好多资料,翻译成中文大概意思是 Broken pipe(“管道破裂”

错误原因说明:

1)broken pipe的字面意思是“管道破裂”。broken pip的原因是该管道的读端被关闭。

2)broken pipe经常发生socket关闭之后(或者其他的描述符关闭之后)的write操作中。

3)发生broken pipe错误时,进程收到SIGPIPE信号,默认动作是进程终止。

4)broken pipe最直接的意思是:写入端出现的时候,另一端却休息或退出了,因此造成没有及时取走管道中的数据,从而系统异常退出

网上分析原因很多如下
1、报文过大:处理的报文过大,导致客户的端无法解析报文。 

2、文件过大:处理时间过长,由于执行时间较长或频率较高,程序或服务器出发超时直接结束进程。

3、重复提交:处理时间过长导致当客户端重复发送请求,而上次请求尚未完成,下次请求会close上次请求。

4、数据库配置问题:mysql配置文件忘记配置wait_timeout参数,导致数据库连接顺序关闭(RS、PS、CONN)。

5、另外就是:Java虚拟机内存太小或者使用低版本的JVM,出发垃圾回收。

结合项目本身分析:

我的应该是在第二和第三条导致的,client端用户在杀死进程时,接口的TCP请求尚未完成(未完成的原因是处理时间长)。
导致server端write数据时,收到SIGPIPE信号,抛出Broken pipe异常。

说白了就是我请求写入的数据量比较大,处理时间比较长,在测试环境单机测试的情况下,不会有问题。但生产环境数据请求量上来以后,当前一次请求还未处理完,后一个请求就把前一个请求给close掉了,导致write数据时,收到sigpipe(信号污染),抛出出了Broken pipe。

java.net.SocketException: Broken pipe
    at java.net.SocketOutputStream.socketWrite0(Native Method)
    at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:109)
    at java.net.SocketOutputStream.write(SocketOutputStream.java:153)
    at org.apache.http.impl.io.SessionOutputBufferImpl.streamWrite(SessionOutputBufferImpl.java:124)
    at org.apache.http.impl.io.SessionOutputBufferImpl.write(SessionOutputBufferImpl.java:160)
    at org.apache.http.impl.io.ContentLengthOutputStream.write(ContentLengthOutputStream.java:113)
    at org.apache.http.entity.ByteArrayEntity.writeTo(ByteArrayEntity.java:112)
    at org.apache.http.impl.DefaultBHttpClientConnection.sendRequestEntity(DefaultBHttpClientConnection.java:156)
    at org.apache.http.impl.conn.CPoolProxy.sendRequestEntity(CPoolProxy.java:152)
    at org.apache.http.protocol.HttpRequestExecutor.doSendRequest(HttpRequestExecutor.java:238)
    at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:123)
    at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:272)
    at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186)
    at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
    at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
    at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56)
 

解决办法:

我的场景是把身份证照片转成base64数据传输的,压缩前大概两百五十多k。

期初不怎么怀疑因为传输内容过大造成的,但试着对base64数据做了下压缩,在观察线上日志,发现问题确实没有了。

因为上传图片识别,牵扯到客户端和服务端的交互,虽然问题解决了,但我还是怀疑服务端连接设置也存在问题,一次数据传输200多k就造成报错,未免有点儿太过经不起考验,后续有新的发现,还会更新。

参考资料:

https://blog.csdn.net/shenshao_8/article/details/81049456

https://blog.csdn.net/ooppookid/article/details/54891771

https://www.cnblogs.com/cthon/p/9139553.html

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java管道流是一种特殊的I/O流,它允许两个线程之间进行单向通信。一个线程可以将数据写入管道流,另一个线程可以从管道流中读取数据。Java管道流通过一个管道输入流和一个管道输出流来实现。 以下是Java管道流的基本操作: 1. 创建管道:使用Pipe类的静态方法open()创建管道,该方法返回一个Pipe对象,其中包含管道输入流和管道输出流。 ``` Pipe pipe = Pipe.open(); ``` 2. 获取管道输入流和输出流:使用Pipe对象的方法获取管道输入流和输出流。 ``` Pipe.SourceChannel sourceChannel = pipe.source(); Pipe.SinkChannel sinkChannel = pipe.sink(); ``` 3. 向管道输出流中写入数据:使用管道输出流的write()方法向管道中写入数据。 ``` sinkChannel.write(ByteBuffer.wrap("Hello, World!".getBytes())); ``` 4. 从管道输入流中读取数据:使用管道输入流的read()方法从管道中读取数据。 ``` ByteBuffer buffer = ByteBuffer.allocate(1024); sourceChannel.read(buffer); ``` 完整的Java管道流示例: ``` import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.Pipe; public class PipeExample { public static void main(String[] args) throws IOException { // 创建管道 Pipe pipe = Pipe.open(); // 获取管道输入流和输出流 Pipe.SourceChannel sourceChannel = pipe.source(); Pipe.SinkChannel sinkChannel = pipe.sink(); // 向管道输出流中写入数据 sinkChannel.write(ByteBuffer.wrap("Hello, World!".getBytes())); // 从管道输入流中读取数据 ByteBuffer buffer = ByteBuffer.allocate(1024); sourceChannel.read(buffer); System.out.println(new String(buffer.array()).trim()); } } ``` 运行结果: ``` Hello, World! ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值