通过rsyslogd(8)进行异步日志记录和增加写缓冲区

在一个运行在虚拟容器(VMware)上且缺乏本地存储的高流量网站上,我们成功地通过从直接记录到日志文件(位于远程网络存储上)切换到rsyslogd来显著提高吞吐量(每秒请求数)。
基本上,我们从同步日志记录切换到了异步日志记录。Web服务器工作进程使用syslog(3)将数据写入内存缓冲区,而rsyslogd(8)以并行和自己的速度将数据发送到实际文件中,因此进程在记录日志时不会被IO阻塞。
到目前为止一切顺利。问题是,偶尔会出现rsyslogd无法写入的情况(例如短暂/持续的网络中断),导致输入缓冲区迅速填满。
我的问题是:
  • 客户端在使用syslog(3)rsyslogd写入时是否会被阻塞?
  • 有没有办法查看rsyslogd的统计信息,例如缓冲区的大小/填充情况?
  • 有没有办法增加rsyslogd的输入缓冲区大小?

2你解决过这个问题吗?如果是的话,我很有兴趣阅读你的答案。 - djeikyb
1@djeikyb:抱歉,不行。我看到有人对这个问题表示了兴趣(投票),但还没有人回答。看起来这需要深入源代码的研究。 - arielf
1你没有说你使用哪个网络服务器。也许你根本不应该使用syslog。例如,Apache是使用syslog来记录日志,还是直接写入日志文件?将日志记录到数据库中也是另一种可能性。 - user41313
2个回答

对于你的第一个问题的答案是:

是的,任何对syslog()的调用都是阻塞的。也许只有很短的时间,但它仍然涉及文件描述符的同步调用。有关更多详细信息,请参见man 3 syslog

除非您的服务器使用异步架构和原语,否则总会存在一些锁定。这可以通过使用单独的线程进行日志记录来缓解,但无法消除。至于另外两个问题,我不太清楚,但检查rsyslogd源代码(以及syslog()函数族的源代码)是唯一的了解方法。

更一般地说,如果您通过UDP:514“网络syslog协议”将日志记录移动到外部服务器,则几乎可以将创建锁的可能性降至零。 但在高负载期间可能会丢失一些日志,这是一个缺点

首先,在“起始”服务器上,您需要确保所有日志记录都通过syslog进行。例如,在Apache2中,您需要指定:

ErrorLog "syslog:daemon"

请参考适当的手册获取其他服务器信息。如果您无法确保此操作,请记住,记录文件系统可能会创建
其次,在原始rsyslogd配置中,您可以要求将所选择的设施(例如此示例中的“守护程序”)的所有syslog流量定向到一个或多个外部syslog服务器。在rsyslog配置文件中,您可以指定:
daemon.* @192.168.128.1
daemon.* @192.168.254.1

同时将日志的两份副本发送到两个不同的服务器。

第三,在目标服务器上启用通过UDP:514接收syslog消息。这在(目标)rsyslogd配置文件中,默认情况下是禁用的(只需删除前面的#号即可):

$ModLoad imudp
$UDPServerRun 514

第四,可选但强烈推荐的是,我还会启用高分辨率时间戳。
$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat

此选项通常默认禁用(天哪,为什么?)。

据我记得,rsyslog中主消息队列的默认模式是固定大小数组。它有一个限制,大约为10k个元素。尝试将其更改为链表队列,应该能更好地处理您偶尔出现的消息突发情况。
是的,有FixedArray和LinkedList队列。

试着做出改变...你能再明确一些吗?看了/etc/rsyslog.conf文件:我没有看到与你提到的队列类型有关的内容。这需要进行代码更改吗?在哪里和如何可以进行配置?谢谢! - arielf