Unix域套接字发生Broken Pipe的原因是什么?

6
我有一个服务器应用程序,它接收请求并将其转发到Unix域套接字。在合理使用时,这可以完美运行,但当我使用几千个请求进行负载测试时,会出现“Broken Pipe”错误。
我正在使用Java 7和junixsocket发送请求。我有许多并发请求,但我有一个20个工作线程的线程池,它正在写入Unix域套接字,因此不存在太多并发打开连接的问题。
对于每个请求,我都会打开、发送和关闭与Unix域套接字的连接。
什么原因会导致Unix域套接字出现“Broken Pipe”?
更新:
如果需要,放置代码示例:
byte[] mydata = new byte[1024];
//fill the data with bytes ...

AFUNIXSocketAddress socketAddress = new AFUNIXSocketAddress(new File("/tmp/my.sock"));
Socket socket = AFUNIXSocket.connectTo(socketAddress);
OutputStream out = new BufferedOutputStream(socket.getOutputStream());
InputStream in = new BufferedInputStream(socket.getInputStream()));

out.write(mydata);
out.flush();  //The Broken Pipe occurs here, but only after a few thousand times

//read the response back...

out.close();
in.close();
socket.close();

我有一个由20个工作者组成的线程池,他们正在同时进行上述操作(因此最多有20个并发连接到同一个Unix域套接字),每个连接都会打开、发送和关闭。这对于10,000个请求的负载测试表现良好,但当我增加几千个请求时,突然出现了这个错误,所以我想知道它是否来自某些操作系统限制。
请注意,这是Unix域套接字,而不是网络TCP套接字。

请查看(什么导致了Broken Pipe错误)[https://dev59.com/0G455IYBdhLWcg3wAvXQ]。 - Shehzad
@jbx 我也从一个AFUNIXSocket客户端中看到了这种行为。你最终找到了根本原因吗? - tjdett
@tjdett 对我来说有点太长了,不过我记得我增加了文件限制,比如打开文件和打开套接字的数量。 - jbx
2个回答

5
“Broken pipe”指的是您向已被另一端关闭的连接写入数据。由于缓冲,它会被异步地检测到。这基本上意味着您的应用程序协议存在错误。

1
谢谢,但这是Unix域套接字,它不是一个普通的TCP套接字,在这里破管道通常是由网络问题或服务器以非优雅的方式关闭连接引起的。 - jbx
是的,但为什么会发生在Unix域套接字上?它本质上是操作系统上的本地文件句柄。没有其他一方正在关闭任何东西,这都是本地的。 - jbx
3
正如AA所说,第一步是走出否认的状态。你遇到了“broken pipe”(断开管道)错误。这种情况只会在对等方关闭其套接字时出现,其他情况不会发生。因此,对等方正在关闭其套接字。至于为什么,那是另一个问题。 - user207421
@BrianVandenberg 你还有什么其他的想法? - user207421
哇,不知怎么的这个帖子在9年后又被挖出来了。在我的情况下,是由于达到了操作系统的限制(这就是为什么它会在负载条件下发生)。增加最大文件句柄和somaxconn等参数可以解决这个问题。 - jbx
显示剩余9条评论

0

来自Linux程序员手册(Mac上的套接字手册也有类似的语言):

实现SOCK_STREAM的通信协议确保数据不会丢失或重复。如果一条数据无法在合理的时间内成功传输到具有缓冲区空间的对等协议,则认为连接已死亡。当在套接字上启用SO_KEEPALIVE时,协议以特定于协议的方式检查另一端是否仍然存活。如果进程在损坏的流上发送或接收数据,则会引发SIGPIPE信号;这会导致未处理该信号的简单进程退出。

换句话说,如果数据在流套接字中被卡住了太长时间,就会出现SIGPIPE错误。如果您无法跟上负载测试,那么出现这种情况是合理的。


这是一篇非常老的帖子,但是...如果你读了我的问题,我明确说过它不是TCP套接字,而是UNIX域套接字,因此完全是本地进程间通信。 - jbx
@jbx 抱歉,我意识到我的术语不正确。UDP/datagram 不应该是这次对话的一部分,而我应该说“流套接字”而不是 TCP。我倾向于使用后者,因为 UNIX 流套接字在插入其地址后与 TCP 套接字完全相同,由于您使用相同的系统调用和监听/连接动态,因此您可以在它们上运行 TCP 协议,例如 HTTP。然而,我的大多数回答仍然站得住脚,因为它取自没有提到 TCP 的文档 - 错误完全是我的。 - TheHans255
在我的情况下,没有数据被卡住。我想如果我没记错的话(因为已经过去9年了),问题是我达到了系统默认的最大连接和文件限制。我增加了像fs.file-maxnet.core.somaxconn这样的东西,问题就解决了。 - jbx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接