news 2026/10/15 23:08:52

Rsyslog 集中式日志转发实战:从协议选型到队列配置

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Rsyslog 集中式日志转发实战:从协议选型到队列配置

1. 为什么值得花时间搞懂 Rsyslog 的转发链路

日志这东西,平时没人搭理,一出事全公司都来找你。我做过好几个集中式日志平台的项目,踩过最大的坑不是存储不够、不是查询太慢,而是日志根本没送到。应用服务器上tail -f看得好好的,一到中心节点就缺了几段,排查半天发现是 rsyslog 的转发规则写错了,或者 UDP 丢包了没人发现。

Rsyslog 是 Linux 世界最主流的日志守护进程,几乎所有的发行版都默认装着它。它的核心能力就两件事:本地收集和网络转发。把几十上百台机器的日志汇聚到一台中心服务器上,做统一存储、检索、告警,这是运维里最基础也最刚需的一环。不管你后面接的是 Elasticsearch、Loki 还是自己写的分析脚本,日志能稳定、完整、低延迟地到达中心节点,是整个链路的地基。

这篇文章面向的是需要搭建集中式日志系统的运维和开发人员,不管你之前有没有接触过 rsyslog,跟着走一遍都能把服务端和客户端的配置跑通。我会把配置文件的每一段拆开讲清楚它在干什么、为什么这么写,再补充一些官方文档里不会告诉你的实操细节。整套方案基于 rsyslog 8.x 版本,这是目前主流发行版自带的版本,兼容性最好。

2. 整体架构设计与协议选型思路

2.1 集中式日志转发的三种典型拓扑

在动手写配置之前,先想清楚日志的流向。常见的拓扑有三种:

第一种是直连型,所有客户端直接把日志发给中心服务器。结构最简单,适合机器数量在几十台以内的场景。缺点是中心服务器是单点,一旦挂了所有日志都丢。

第二种是中继型,客户端先发给区域中继节点,中继节点再转发给中心。适合跨机房、跨网段的场景,可以减少跨网络的连接数,也能在中继节点做一层缓冲。

第三种是混合型,关键业务直连中心,普通业务走中继。这种最灵活,但配置管理复杂度也最高。

我这次以最实用的直连型为主线来展开,中继的配置会在后面单独提。你先把一条链路跑通,再考虑扩展。

2.2 UDP、TCP 还是 RELP:协议选型的核心权衡

这是整个方案里最重要的一个决策,直接决定了日志的可靠性和性能。很多人默认用 UDP,因为配置简单,但生产环境里我强烈建议至少用 TCP。

协议可靠性性能配置复杂度适用场景
UDP低,会丢包最高最低内网、日志量大且可容忍丢失
TCP中,有连接保障中中大多数生产场景
RELP高,应用层确认中低高审计日志、不可丢失场景

UDP 的问题在于它是无连接的,网络稍微拥塞或者接收端处理不过来,数据包就直接被丢弃,而且发送端完全不知道。我遇到过一台机器每秒产生上万条日志,用 UDP 转发到中心,高峰期丢了将近三成,事后查问题发现关键的那几条恰好丢了,非常被动。

TCP 解决了丢包问题,因为它有重传机制和流量控制。但 TCP 也有个坑:如果中心服务器重启,客户端在重连期间产生的日志可能会丢。这时候就需要 RELP(Reliable Event Logging Protocol),它在应用层做了确认和重传,能保证日志至少送达一次。代价是性能会下降,配置也更复杂。

我的建议是:普通业务日志用 TCP,审计类、合规类日志用 RELP。UDP 只在极端追求性能且能接受丢失的场景下用。

2.3 消息格式的选择:从 RFC3164 到 RFC5424

日志消息的格式也影响后续的解析。老式的 RFC3164 格式就是传统的 syslog 格式,时间戳精度只到秒,没有结构化字段。RFC5424 是 2009 年发布的新标准,支持毫秒级时间戳、结构化数据、UTF-8 编码。

如果你的日志后面要进 Elasticsearch 做结构化分析,建议在客户端就配置成 RFC5424 格式,这样时间戳精度更高,字段也更规范。配置上就是在模板里指定RSYSLOG_SyslogProtocol23Format。不过要注意,有些老旧的接收端可能不认这个格式,需要先确认对端兼容性。

3. 服务端配置:把中心节点搭起来

3.1 基础环境准备与模块加载

服务端我用的是一台 4 核 8G 的虚拟机,系统是主流的 Linux 发行版。先确认 rsyslog 版本:

rsyslogd -v

输出里能看到版本号,8.x 以上都支持本文的配置。如果版本太老,建议先升级,因为老版本在 TCP 并发和队列管理上有不少已知问题。

服务端的配置文件在/etc/rsyslog.conf,但更好的做法是在/etc/rsyslog.d/目录下新建独立的配置文件,比如10-server.conf。这样升级系统时不会覆盖你的配置,也方便管理。

首先要加载必要的模块。rsyslog 是模块化设计的,不用的功能不加载,减少资源占用:

# 加载 TCP 和 UDP 输入模块 module(load="imtcp") module(load="imudp") # 加载 RELP 输入模块(如果要用 RELP) module(load="imrelp")

imtcp和imudp分别对应 TCP 和 UDP 的接收。这里有个细节:模块加载是全局的,但监听端口是在 input 里指定的,两者要配合。

3.2 监听端口与接收规则配置

加载模块后,要告诉 rsyslog 在哪个端口监听:

# TCP 监听 514 端口 input(type="imtcp" port="514") # UDP 监听 514 端口 input(type="imudp" port="514") # RELP 监听 2514 端口 input(type="imrelp" port="2514")

514 是 syslog 的标准端口,但它是特权端口(小于 1024),需要 root 权限才能绑定。rsyslog 默认以 root 启动,所以没问题。如果你不想用标准端口,改成 1514 之类的也可以,客户端对应改一下就行。

注意:如果服务器开了防火墙,记得放行对应端口。TCP 和 UDP 要分别放行,很多人只放了 TCP 忘了 UDP,结果用 UDP 的客户端一直连不上。

接收规则决定了日志收到后怎么处理。最简单的做法是按来源 IP 分目录存储:

# 按客户端 IP 分目录存储 template(name="RemoteLogs" type="string" string="/var/log/remote/%FROMHOST-IP%/%$YEAR%-%$MONTH%-%$DAY%.log") # 应用模板 if $fromhost-ip != '127.0.0.1' then { action(type="omfile" dynaFile="RemoteLogs") stop }

这段配置的意思是:如果日志不是本机产生的,就按来源 IP 和日期存到/var/log/remote/下,然后停止后续处理。stop很关键,不加的话日志会继续往下走,可能被重复写入本地日志文件。

%FROMHOST-IP%是 rsyslog 的属性变量,代表发送方的 IP。类似的常用变量还有%HOSTNAME%(主机名)、%syslogtag%(标签)、%msg%(消息内容)。这些变量在模板里可以直接引用。

3.3 磁盘存储策略与目录规划

存储目录的规划直接影响后续的检索效率。我见过有人把所有日志堆在一个文件里,几天下來文件几十个 G,grep一次要几分钟。合理的做法是按维度分目录:

# 按主机名和日期分层 template(name="StructuredLogs" type="string" string="/var/log/remote/%HOSTNAME%/%$YEAR%/%$MONTH%/%$DAY%.log")

这样每个主机每天一个文件,检索时先定位主机再定位日期,速度快很多。缺点是文件数量多,如果机器有几百台,一年下来文件数量很可观。这时候可以考虑用dynaFile配合omfile的压缩功能,或者直接接入 Elasticsearch 做索引。

磁盘空间也要提前规划。假设 100 台机器,每台每天产生 500MB 日志,一天就是 50GB,保留 30 天需要 1.5TB。这个量级用本地磁盘扛不住,要么做定期清理,要么直接写远程存储。rsyslog 支持输出到多种后端,包括数据库、消息队列、对象存储等,后面会提到。

4. 客户端配置:让日志可靠地发出去

4.1 转发规则的编写与匹配

客户端的配置核心是匹配规则加转发动作。匹配规则决定哪些日志要转发,转发动作决定发到哪里、用什么协议。

最简单的全量转发:

# 加载 TCP 输出模块 module(load="omfwd") # 所有日志转发到中心服务器 *.* action(type="omfwd" target="192.168.1.100" port="514" protocol="tcp")

*.*表示所有设施(facility)和所有优先级(priority)的日志。设施包括 auth、cron、daemon、kern、mail 等,优先级从 debug 到 emerg 共 8 级。实际使用中很少全量转发,通常会有选择:

# 只转发 info 及以上级别的日志,排除 debug *.info;*.!debug action(type="omfwd" ...) # 只转发特定设施的日志 auth,authpriv.* action(type="omfwd" ...)

*.!debug里的感叹号表示排除,这个语法容易记混,多写几次就熟了。

4.2 队列机制:应对网络抖动和中心节点重启

这是客户端配置里最容易被忽略、但最重要的部分。默认情况下,如果中心服务器不可达,rsyslog 会直接丢弃日志。加上队列配置后,日志会先缓存在本地,等网络恢复再发。

action(type="omfwd" target="192.168.1.100" port="514" protocol="tcp" queue.type="LinkedList" queue.size="10000" queue.filename="fwd_queue" queue.saveOnShutdown="on" queue.maxdiskspace="1g" action.resumeRetryCount="-1" action.resumeInterval="30")

逐项解释一下:

  • queue.type="LinkedList":使用内存队列,性能最好。如果对可靠性要求极高,可以改成Disk,但性能会下降。
  • queue.size="10000":内存队列最多缓存 10000 条消息。
  • queue.filename="fwd_queue":磁盘队列的文件名前缀,配合queue.type="Disk"或内存队列溢出时使用。
  • queue.saveOnShutdown="on":关机时把队列内容存盘,重启后继续发送。
  • queue.maxdiskspace="1g":磁盘队列最大占用 1GB。
  • action.resumeRetryCount="-1":无限重试,-1 表示不限制。
  • action.resumeInterval="30":重试间隔 30 秒。

这套配置下来,即使中心服务器宕机几个小时,客户端也能把日志缓存在本地,恢复后自动补发。我实测过断网 2 小时、积压几十万条日志的场景,恢复后几分钟内全部补发完成,没有丢失。

提示:queue.size不要设得太大,内存队列占用的是进程内存,设成 100 万条可能直接把 rsyslog 进程撑爆。一般 10000 到 50000 之间比较稳妥,超出的部分会溢出到磁盘队列。

4.3 多目标转发与条件路由

有时候日志需要同时发给多个目标,比如一份发给中心日志服务器,一份发给本地的分析程序。rsyslog 支持一个规则匹配多个动作:

*.info action(type="omfwd" target="192.168.1.100" port="514" protocol="tcp") *.info action(type="omfwd" target="192.168.1.101" port="514" protocol="tcp")

两条 action 会依次执行,日志发往两个目标。如果只想在特定条件下转发,可以用 if 判断:

if $programname == 'nginx' then { action(type="omfwd" target="192.168.1.100" port="514" protocol="tcp") }

$programname是产生日志的程序名,nginx 的访问日志和错误日志都会带上这个标签。按程序名路由是实践中最常用的方式,因为不同程序的日志价值和处理方式差异很大。

5. 完整实操流程与验证方法

5.1 服务端从零到可用的完整步骤

我把服务端的搭建过程整理成可复制的步骤:

第一步,确认 rsyslog 已安装并运行:

systemctl status rsyslog

如果没有安装,用包管理器装上。主流发行版都自带,一般不用额外装。

第二步,创建服务端配置文件/etc/rsyslog.d/10-server.conf,内容如下:

module(load="imtcp") module(load="imudp") input(type="imtcp" port="514") input(type="imudp" port="514") template(name="RemoteLogs" type="string" string="/var/log/remote/%FROMHOST-IP%/%$YEAR%-%$MONTH%-%$DAY%.log") if $fromhost-ip != '127.0.0.1' then { action(type="omfile" dynaFile="RemoteLogs") stop }

第三步,创建存储目录并设置权限:

mkdir -p /var/log/remote chown syslog:adm /var/log/remote

不同发行版 rsyslog 的运行用户不同,有的是syslog,有的是root。用ps aux | grep rsyslog确认一下,把目录权限给对应用户。

第四步,检查配置语法:

rsyslogd -N1

这个命令会解析配置文件并报告错误,不实际启动服务。配置有语法问题时它会明确指出哪一行出错,非常实用。每次改完配置都应该跑一遍。

第五步,重启服务:

systemctl restart rsyslog

第六步,确认端口在监听:

ss -tlnp | grep 514 ss -ulnp | grep 514

分别检查 TCP 和 UDP 的监听状态。

5.2 客户端配置与连通性测试

客户端的配置步骤类似:

第一步,创建/etc/rsyslog.d/20-client.conf:

module(load="omfwd") *.* action(type="omfwd" target="192.168.1.100" port="514" protocol="tcp" queue.type="LinkedList" queue.size="10000" queue.filename="fwd_queue" queue.saveOnShutdown="on" action.resumeRetryCount="-1" action.resumeInterval="30")

第二步,检查语法并重启:

rsyslogd -N1 systemctl restart rsyslog

第三步,手动产生一条日志测试:

logger "test message from client"

logger是产生 syslog 消息的标准工具,几乎所有 Linux 都有。执行后到服务端的/var/log/remote/下找对应 IP 的目录,看日志有没有到。

如果没到,先检查网络连通性:

telnet 192.168.1.100 514

TCP 能连上说明网络和端口没问题,问题出在配置上。UDP 没法用 telnet 测,可以用nc:

echo "test" | nc -u 192.168.1.100 514

5.3 用 tcpdump 抓包定位转发问题

配置都对但日志就是不到,这时候抓包是最直接的排查手段。在服务端执行:

tcpdump -i any -nn port 514 -A

-A参数会把包内容以 ASCII 形式打印出来,能直接看到日志文本。然后在客户端执行logger命令,观察服务端有没有抓到包。

如果抓到了包但日志没落盘,说明是服务端的处理规则有问题,重点检查模板和 action 配置。如果没抓到包,说明是客户端没发出来或者网络不通,重点检查客户端的转发规则和防火墙。

这个排查思路我用了很多次,基本能在几分钟内定位问题所在。抓包看到的内容还能确认消息格式是否符合预期,比如时间戳格式、主机名字段是否正确。

6. 常见问题与排查技巧实录

6.1 日志重复、丢失、乱序的根因分析

日志重复是最常见的问题之一。原因通常是配置了多个匹配规则,同一条日志被多个 action 处理。比如既配了*.*全量转发,又配了*.info的转发,info 级别的日志就会发两次。解决办法是理清规则优先级,用stop及时终止后续处理。

日志丢失的原因就多了。UDP 丢包是最常见的,换成 TCP 基本能解决。队列配置不当也会丢,比如queue.size太小、没配磁盘队列,网络一抖动队列就溢出。还有一种隐蔽的情况是服务端的imtcp有并发连接数限制,客户端多了之后新连接被拒绝,日志自然就丢了。可以在服务端配置里加input(type="imtcp" port="514" maxsessions="500")提高上限。

日志乱序在 UDP 下很常见,因为 UDP 不保证顺序。TCP 下一般不会乱序,但如果用了多线程处理或者多个队列,也可能出现。对顺序敏感的场景,建议在消息里带上客户端的时间戳和序列号,接收端按序列号排序。

6.2 性能瓶颈的识别与调优

当日志量上来后,rsyslog 可能成为瓶颈。判断方法很简单,看 CPU 和磁盘 IO:

top -p $(pgrep rsyslogd) iostat -x 1

如果 rsyslog 进程 CPU 占用持续很高,通常是模板处理或者正则匹配太复杂。优化方向是简化模板,避免在每条日志上做昂贵的字符串操作。如果磁盘 IO 是瓶颈,说明写入速度跟不上,可以考虑用内存队列缓冲,或者把日志先写到 tmpfs 再异步落盘。

还有一个容易忽略的点是日志文件的数量。如果按主机名和日期分目录,文件数量会很多,文件系统的 inode 和目录查找都会成为瓶颈。这种情况下建议用omfile的asyncWriting模式,或者直接接入支持批量写入的后端。

6.3 高频踩坑速查表

现象可能原因排查方法解决方案
日志完全不到防火墙拦截telnet 测端口放行 TCP/UDP 端口
日志时有时无UDP 丢包tcpdump 抓包对比改用 TCP
日志重复多条规则匹配检查配置文件加 stop 终止
中心重启后日志缺失无队列缓冲检查 queue 配置加磁盘队列
日志时间戳不对时区不一致对比两端时间统一时区配置
磁盘写满无清理策略df -h 查看配 logrotate 或远程存储

这张表里的每一条我都在实际项目中遇到过,尤其是时区问题,跨机房部署时特别容易踩。客户端和服务端时区不一致,日志时间戳对不上,排查问题时能把人逼疯。统一用 UTC 时间是最稳妥的做法。

7. 进阶玩法:从转发到结构化处理

7.1 用模板定制日志格式

默认的 syslog 格式信息量有限,通过模板可以定制输出格式。比如输出成 JSON,方便后续程序解析:

template(name="JsonFormat" type="string" string="{\"time\":\"%timereported:::date-rfc3339%\",\"host\":\"%HOSTNAME%\",\"program\":\"%programname%\",\"message\":\"%msg%\"}\n")

%timereported:::date-rfc3339%里的:::date-rfc3339是属性选项,把时间格式化成 RFC3339 标准。类似的选项还有date-rfc3164、date-mysql等。JSON 格式的日志直接喂给 Elasticsearch 或者 Loki,省去了大量解析工作。

7.2 接入消息队列做削峰填谷

日志量特别大的时候,rsyslog 直接写文件可能扛不住。这时候可以在中间加一层消息队列,rsyslog 只负责把日志发到队列,后面的消费和存储由专门的程序处理:

module(load="omkafka") action(type="omkafka" broker="192.168.1.200:9092" topic="syslog" confParam=["compression.codec=gzip"])

omkafka是 Kafka 输出模块,需要单独安装。类似的还有omrabbitmq、omelasticsearch等。这种架构的好处是解耦,rsyslog 不用关心下游怎么处理,队列本身也能缓冲流量高峰。

7.3 日志轮转与长期归档策略

日志不能无限增长,必须配轮转。rsyslog 本身不负责轮转,靠系统的 logrotate:

/var/log/remote/*/*.log { daily rotate 30 compress delaycompress missingok notifempty create 0640 syslog adm }

这段配置表示每天轮转一次,保留 30 天,压缩旧文件。delaycompress表示延迟一天再压缩,避免正在写入的文件被压缩导致问题。create指定新文件的权限和属主,要和 rsyslog 的运行用户匹配。

长期归档的话,可以考虑把轮转后的日志同步到对象存储。用rclone或者awscli之类的工具,配合 cron 定时执行。归档时建议按年月打包,减少小文件数量,检索时也方便定位。

8. 我踩过的几个印象深刻的坑

说几个配置文档里不会写、但实际部署时大概率会遇到的坑。

第一个是主机名解析。rsyslog 默认会用%HOSTNAME%作为日志里的主机标识,但如果客户端的/etc/hosts配置有问题,或者 DNS 解析慢,rsyslog 在启动时会卡住等解析。表现是服务启动特别慢,日志延迟很高。解决办法是在客户端配置里加global(net.enableDNS="off"),直接用 IP 标识,不做反向解析。

第二个是SELinux。在某些开启了 SELinux 的系统上,rsyslog 绑定 514 端口或者写/var/log/remote/会被拒绝,日志里能看到 AVC 拒绝记录。要么调整 SELinux 策略,要么临时设为 permissive 模式测试。生产环境建议正确配置策略,不要直接关掉。

第三个是配置文件的加载顺序。/etc/rsyslog.d/下的文件是按文件名排序加载的,10-server.conf会在20-client.conf之前加载。如果两个文件里有冲突的规则,后面的会覆盖前面的。命名时用数字前缀就是为了控制顺序,这个习惯要养成。

第四个是队列文件残留。如果 rsyslog 异常退出,磁盘队列文件可能残留,下次启动时会尝试恢复。如果队列文件损坏,rsyslog 可能启动失败。这时候需要手动清理队列文件目录,通常在/var/spool/rsyslog/下。清理前确认没有重要日志积压,否则会丢数据。

这套配置我在多个项目里用过,从几十台机器的小集群到上千台的大集群都跑得通。核心就是三点:协议选 TCP 保可靠,队列配磁盘防丢失,模板分目录利检索。把这三点做到位,日志转发这条链路基本不会出大问题。后面要扩展的话,往上加消息队列、加结构化解析、加告警规则,都是在这个稳定地基上做加法。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 23:07:44

TensorFlow工程化实战:从开发调试到生产部署全链路指南

1. 项目概述:这不是一个“框架”,而是一套可落地的工程化神经网络实践体系很多人第一次听说tensorflow,脑子里浮现的是“谷歌开源的深度学习框架”“写AI要用的库”“学生做课程设计的标配”。但在我带过几十个从零起步的项目、参与过多个工业…

作者头像 李华
网站建设 2026/10/15 23:02:58

Cocos Creator 3D无动画换装系统:节点查找、资源加载与材质绑定实战

1. 换装系统的整体设计思路角色换装这件事,听起来像是美术和策划的活儿,但真正落地到引擎里,它就是一个纯粹的工程问题:如何在不重建整个角色的前提下,动态替换模型上某一部分的外观。麒麟子在笔记里明确标注了“无动画…

作者头像 李华
网站建设 2026/10/15 23:02:39

告别复制粘贴:8个最值得上手的MCP服务器

说到“告别复制粘贴”,我脑子里立刻出现几个典型画面:终端里一整屏报错,你一段段复制进对话框;网页文档太长,你把全文选中粘贴过去再求“总结”;数据库查询结果几百行,你整理成表格后再发给 AI …

作者头像 李华
网站建设 2026/10/15 23:00:12

AI日报制作全流程:从信息筛选到结构化压缩的工程实践

1. 一份AI日报的诞生逻辑每天早上八点前把一份AI日报推到订阅者面前,这件事我已经连续做了两年多。很多人以为这就是"把昨天的新闻复制粘贴一遍",但真正操作过的人知道,一份能让人愿意每天花三分钟读完的日报,背后是一整…

作者头像 李华
网站建设 2026/10/15 22:59:22

深度学习复习指南:从张量到部署的核心基础与实战要点

1. 为什么“复习”深度学习比“学”深度学习更让人头疼如果你问一个刚入门深度学习的人最怕什么,十有八九会告诉你“公式推不动”或者“代码跑不通”。但如果你问一个已经做过几个项目、调过几轮模型的人最怕什么,答案往往出人意料——怕被问到最基础的概…

作者头像 李华
网站建设 2026/10/15 22:59:17

降AI率工具测评:开源免费方案与改稿实战全解析

做内容运营这两年,我几乎每天都要和“AI味”打交道。AI起草确实快,但稿子交上去之前,至少得花半小时把那些“总而言之”“值得一提的是”“不难发现”改成正常人说的话。最近陆续有人问我“降AI率工具到底有没有用”,我就把市面上…

作者头像 李华