关注perl IO :: Socket丢失UDP数据包

时间:2017-04-28 03:05:11

标签: perl sockets udp

我有一个小的UDP perl服务,它接收syslog数据,用它来解决它,然后通过它(通过UDP)将它发送回同样在localhost上运行的syslog服务器。它工作得很好,但我担心它可能会丢失syslog事件,所以测试它

基本上我推了100"这是一个测试$ NUM ++"消息输入,有时100会出现 - 但一旦99出现(通过运行perl脚本的主机上运行的tcpdump来衡量)。这是在我们的生产系统上,它处理500-1500 syslog msg / sec。像往常一样,当它只有测试流量时,它可以很好地工作,但在负载下我不确定。

tcpdump显示了超过eth0的100个事件,但是tcpdump显示99超过了lo。所以也许有人从来没有把它变成了'rcvSock'或者也许有人迷失了通过' $ sndSock'

基本上perl代码如下所示。然而,"#fiddling" bit确实涉及DNS查找的一些暂停,所以有一些" read-> block-> write"继续我不认为"听"在UDP下受支持,所以我无法确定perl脚本是否阻止下一次接收,而它正在进行" fiddling"?

任何人都可以了解损失可能发生的位置以及如何通过它吗?

$rcvSock = IO::Socket::INET->new(
     LocalAddr => $hn,
     LocalPort => $rcvPort,
     Timeout => $timeout,
     Proto    => 'udp'
);

$sndSock = IO::Socket::INET->new(
     PeerAddr => $syslogSrv,
     PeerPort =>$syslogPort,
     Timeout  => $timeout,
     Proto    => 'udp',
     Blocking => 0
);

while (1) {
    $now=time;
    $rcvSock->recv($input,2560);
    $remote_addr=$rcvSock->peerhost();
    #fiddling occurs
    $sndSock->send("$input");
}

2 个答案:

答案 0 :(得分:0)

谢谢你SO_RCVBUF的伎俩。

正在发生的事情是我每秒推送(比方说)1000个系统日志记录/数据包,但DNS查询我暂停处理1秒/记录。所以这意味着在处理完一条记录之后,现在有999条记录需要处理。在1998年之后的两秒钟。这看起来并不好......

操作系统可以根据SO_RCVBUF对这些数据包进行排队,默认情况下(在Redhat上)为212992字节。因此,假设每个syslog记录平均有400个字节,那么在内核开始丢弃新数据包之前,最多可排队约530个记录。所以我可以将SO_RCVBUF 10提高100倍,但它不会解决那个大停顿的根本问题。然而,实际上我在谈论峰值速率:有时候记录/秒下降,并且许多系统日志记录不需要DNS查找(即我跳过它们)。同样通过缓存那些DNS查找,我可以最大限度地减少完成它们的时间,因此1000 /秒可能是101 /秒涉及DNS,而这反过来可能是99%可缓存,导致只有2-5 /需要DNS查找的秒 - 在该级别,健康的缓存将帮助您解决峰值负载问题

我不是程序员,因此使用输入队列,异步DNS查找等正确执行此操作是我无法做到的。但我确实知道iptables ...所以我打算在不同的端口上运行其中的几个,并使用iptables循环传递传入的数据包到它们上面,给它们提供异步功能而不需要编写一行代码。这应解决我需要担心的负载水平: - )

谢谢!

答案 1 :(得分:-1)

尝试增加SO_RCVBUF

IO::Socket::INET->setsockopt(SOL_SOCKET, SO_RCVBUF, ...)

sar对于网络统计调查非常有帮助。

  

idgmerr / s每秒可以接收的UDP数据报数   除了缺乏申请以外的原因,不得交付   目的端口[udpInErrors]。

$ sar -n UDP 5

08:18:12 AM    idgm/s    odgm/s  noport/s idgmerr/s
08:18:15 AM    121.33    121.33      7.67      0.00