我有一个用 perl 编写的小型 Web 应用程序,在 apache 下运行 mod_perl。它所做的只是创建与服务器的套接字连接,并在发送请求之前等待 OK 消息。我们最多只有 10 个孩子。随机读取此 Ok 消息会失败。其他读取同时进行。我已经找到了
sudo strace -x -o traceout.log -f -tt -s 1024 -p 23735
正常读取有:
31317 14:27:18.043630 alarm(30) = 0
31317 14:27:18.043722 read(17, "OK nGSrv ready. $Revision: 1.59 $ Built: May 5 2017 11:17:19 - [1]\r\n", 4096) = 70
31317 14:27:18.043811 alarm(0) = 30
但失败有:
31198 14:26:34.350791 alarm(30) = 0
31198 14:26:34.350836 fstat64(16, {st_mode=S_IFSOCK|0777, st_size=0, ...}) = 0
31198 14:26:34.350934 read(16, "OK nGSrv ready. $Revision: 1.59 $ Built: May 5 2017 11:17:19 - [3]\r\n", 4096) = 70
31198 14:26:34.351014 read(16, <unfinished ...>
:
:
31198 14:26:39.345766 <... read resumed> "", 4096) = 0
31198 14:26:39.345829 alarm(0) = 25
5 秒警报/超时是另一端关闭连接,因为它没有收到请求。
有谁知道为什么失败有这个额外的 fstat64 和未完成的读取?
$server = IO::Socket::INET->new(Proto => "tcp",
PeerAddr => $ip,
PeerPort => $port,
Timeout => $timeout);
if( $server ) {
eval {
local $SIG{ALRM} = sub { die "alarm\n" }; # \n required!!!!
alarm $queuetimeout;
$greeting = <$server>;
alarm 0;
};
if($@) { # Something in the eval died
unless( $@ eq "alarm\n" ) {
# Unexpected Error
$greeting = 'ERROR'; # Force an ERROR response
} else {
# Timeout
$greeting = 'BUSY'; # Force a BUSY response
}
}
给出“额外” fstat64 和未完成读取的行是:-
$greeting = <$server>;
这工作正常,直到某些随机事件导致十分之一失败,在随机时间段内,然后它们停止。这会影响同一网络上的 6 个 Web 服务器,它们具有共同的挂载和共同的数据库。我们能找到的唯一区别是这个 fstat64。这 6 个 Web 服务器(apache、mod_perl)连接到同一网络上的其他 2 个服务器之一。我们已经对两台服务器进行了 tcpdump 处理,可以看到“OK nGSrv ready...”消息立即发送并立即接收,但不知何故(仅在这些随机时间段内)客户端未完全/正确读取。