6

我有一个服务器应用程序,它接收请求并在 Unix 域套接字上转发它们。这在合理的使用情况下非常有效,但是当我对几千个请求进行一些负载测试时,我收到了 Broken Pipe 错误。

我正在使用带有junixsocket的 Java 7来发送请求。我有很多并发请求,但我有一个由 20 个工作人员组成的线程池,它们正在写入 unix 域套接字,因此不存在并发打开连接过多的问题。

对于每个请求,我打开、发送和关闭与 Unix 域套接字的连接。

可能导致 Unix 域套接字上的管道损坏的原因是什么?

更新:

如果需要,放置代码示例:

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 套接字。

4

2 回答 2

4

'Broken pipe' 表示您已写入已被另一端关闭的连接。由于缓冲,它的检测有些异步。这基本上意味着您的应用程序协议中有错误。

于 2012-04-15T22:39:19.707 回答
0

来自Linux Programmer's Manual(Mac 上的 socket 手册页中也有类似的语言):

实现 SOCK_STREAM 的通信协议确保数据不会丢失或重复。如果对等协议有缓冲空间的一段数据在合理的时间内不能成功传输,则认为该连接已死。当在套接字上启用 SO_KEEPALIVE 时,协议以特定于协议的方式检查另一端是否还活着。如果进程在中断的流上发送或接收,则会引发 SIGPIPE 信号;这会导致不处理信号的幼稚进程退出。

换句话说,如果数据在流套接字中停留的时间过长,您最终会得到一个 SIGPIPE。如果您无法跟上负载测试,那么您最终会遇到这种情况是合理的。

于 2021-09-14T17:21:51.233 回答