1

我有一个用 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...”消息立即发送并立即接收,但不知何故(仅在这些随机时间段内)客户端未完全/正确读取。

4

0 回答 0