rsyslog 转发日志丢数据主因是默认 udp 无确认机制,需改 tcp(@@)并配磁盘队列;journald 日志进不了集中系统因 forwardtosyslog 未启用或 syslog-ng/ rsyslog 未正确加载 journal 源;filebeat 解析 nginx 日志需 dissect 精确匹配格式;logstash filter 性能低多因 grok 过载、未设 worker 数或缺失 geoip 缓存。

为什么 rsyslog 转发日志到 syslog-ng 会丢数据?
rsyslog 默认用 UDP 转发,没确认机制,网络抖动或目标忙时直接丢包。生产环境必须切 TCP,并配缓冲队列。
- 启用 TCP:在
rsyslog.conf中改<em>.</em> @@192.168.1.100:514(两个 @ 表示 TCP) - 开启磁盘队列防崩:
$ActionQueueType Disk+$ActionQueueFileName rsyslog_queue - 限制队列大小避免占满磁盘:
$ActionQueueMaxDiskSpace 1g -
syslog-ng端要监听 TCP:source s_network { network(ip(0.0.0.0) port(514) transport(tcp)); };
常见错误是只改了 rsyslog 的协议,但 syslog-ng 还卡在 UDP 模式,收不到任何东西。
journalctl 日志进不了集中系统?查这三处
systemd-journald 默认不转发日志给 rsyslog 或 syslog-ng,得手动打通。
- 确认
/etc/systemd/journald.conf中ForwardToSyslog=yes已开启(注意不是yes小写,大写会无效) - 检查
syslog-ng是否加载了systemd-journal源:source s_journald { systemd-journal(); }; - 若用
rsyslog,需装rsyslog-gnutls和rsyslog-mmjsonparse插件,否则 JSON 格式日志解析失败,字段全丢
典型现象是 journalctl -u nginx 能看到日志,但 Kibana 里查不到 —— 很可能只是 journald 和 syslog 层没连通。
用 filebeat 收集 Nginx access.log 时字段全空?
filebeat 默认按行读日志,但 Nginx access log 是空格分隔的结构化文本,不配 dissect 或 grok 解析器,message 字段就是一整行字符串,status、response_time 全不存在。
- 在
filebeat.yml的processors下加 dissect:</li><li>dissect: tokenizer: "%{clientip} - %{ident} %{auth} [%{timestamp}] \"%{method} %{url} %{protocol}\" %{status} %{size} \"%{referrer}\" \"%{useragent}\"" - 时间戳要转成 @timestamp:
- convert_timezone: {field: timestamp, from: "UTC", to: "UTC"} - 注意 Nginx 日志格式是否含额外字段(如
request_time),tokenizer 必须严格对齐,少一个%{...}就整条解析失败,字段全空
别信网上抄来的通用 grok pattern,Nginx 配置里 log_format 改过一行,pattern 就得重调。
Logstash filter 性能卡在 500 events/sec?先看这个配置
logstash 吞吐瓶颈常出在 filter 阶段,尤其用 grok 匹配复杂正则时,CPU 占满也跑不满。
- 把
grok放在if [type] == "nginx"条件块里,避免对所有日志都执行 - 关闭
break_on_match => false(默认 true),匹配成功就停,别硬扫完全部 pattern - 用
dissect替代grok:只要日志格式固定,dissect性能高 5–10 倍,且无回溯风险 -
geoip查询必须加cache_size => 1000,否则每次请求都查库,IO 直接拖垮
最常被忽略的是:Logstash 启动时没加 -w 4(worker 数),默认只用 1 个线程,再怎么优化 filter 也白搭。










