日志采集架构:Agent、Logstash、Fluentd、Filebeat

日志采集是整个存储链路的“水源”。水源脏了、断了,后面存再多也没用。我见过不少团队上来就搭 Elasticsearch 集群,日志格式、采集方式一概不管,最后排错排到崩溃。嗯,这一章我们就聊聊怎么选采集器,怎么搭架构。

说白了,采集层要解决两件事:一是把日志从千奇百怪的地方捞出来,二是保证不丢、不重、不乱序。市面上主流方案就那么几个——Agent、Logstash、Fluentd、Filebeat。我一个个说。

4.1 采集器的职责与定位

先理清角色。采集器不是存数据的,它是“搬运工”。我的习惯是把采集器分成两类:

  • 轻量级转发器:只负责读文件、发数据。典型代表是 Filebeat、Fluent Bit。
  • 重量级处理管道:能解析、过滤、转换、路由。典型代表是 Logstash、Fluentd。

为什么区分这个?因为资源消耗差很多。你在每台业务机器上跑 Logstash?JVM 堆 1GB 起,跑 1000 台就是 1TB 内存,老板会找你谈心的。所以我的推荐很明确:采集端用轻量级工具,集中处理用重量级工具。

4.2 四大采集器深度对比

特性 Filebeat Fluentd Logstash 传统 Agent
开发语言 Go Ruby + C Java (JRuby) 因实现而异
资源占用 极低 (~10MB) 中等 (~50MB) 较高 (~256MB+) 不定(通常较高)
数据可靠性 内置背压 + ACK Buffer 插件保证 持久化队列 需自行实现
过滤能力 弱(基本字段处理) 强(插件生态丰富) 极强(丰富 Filter) 弱到中
吞吐性能 极高(10万 EPS+) 高(数万 EPS) 中(受 JVM GC 影响) 因实现而异
典型场景 边缘采集、容器环境 统一日志平台、Ruby/云原生 集中处理、复杂解析 遗留系统集成

我的建议:生产环境标配是 Filebeat + Logstash。Filebeat 塞到每台服务器上,Logstash 做集中过滤。这套组合我在好几个项目里都用过,上万台机器也没出过问题。

4.3 架构模式:分层与聚合

采集架构不是一条直线。我画个框架图帮你理解典型的架构分层:

日志采集分层架构 边缘层 (Edge Layer) Filebeat / Fluent Bit 每台业务机上部署,只负责收集 + 发送,不做复杂处理 聚合层 (Aggregation Layer) Logstash / Fluentd 集中接收,完成过滤、解析、格式统一、转发 存储/消费层 (Storage Layer) Elasticsearch / Kafka / HDFS / S3 最终目的地,按策略分温/冷区存储 关键原则:边缘轻量化,集中富处理,避免每台机器上跑重量级进程

你会看到三层结构。边缘层跑 Filebeat,聚合层跑 Logstash,存储层接 Elasticsearch 或 Kafka。每一层只干自己的事,出了问题排查也简单。

我来说说各层的细节。

4.4 边缘采集:Filebeat 实战

Filebeat 是我最常用的边缘采集器。Go 写的,单进程几 MB 内存,CPU 占用基本忽略不计。为什么?因为它内部用了一种叫“harvester”的机制,只读增量内容,不是全量扫文件。

给你看一份我项目里的配置:

filebeat.inputs:
- type: log
  enabled: true
  paths:
    - /var/log/app/*.log
    - /data/logs/*.json
  fields:
    env: production
    service: order-api

filebeat.config.modules:
  path: ${path.config}/modules.d/*.yml
  reload.enabled: true
  reload.period: 10s

output.logstash:
  hosts: ["logstash01:5044", "logstash02:5044"]
  loadbalance: true
  ssl.enabled: true
  ssl.certificate_authorities: ["/etc/filebeat/ca.crt"]

我曾经踩过的坑:Filebeat 默认的 harvester_limit 是 0(无限制)。有一次我们在一个目录下监控了 5000+ 日志文件,Filebeat 直接开了 5000 个文件句柄,系统 ulimit 被捅穿了。后来我强制设置 harvester_limit: 100,配合 close_inactive: 5m,问题才解决。

Filebeat 只有三个核心概念:

  • Input:定义读什么、从哪读、怎么读。
  • Harvester:负责具体读取每个日志文件的协程。
  • Output:数据发往哪里,支持 Logstash、Kafka、ES 等。

对了,Filebeat 还有一个“模块”系统。比如你想采集 Nginx 日志,直接 filebeat modules enable nginx 就自动配置好解析规则。这个特性很适合快速上线。

4.5 集中处理:Logstash 与 Fluentd 对比

到了聚合层,我们需要能“折腾”日志的工具。Logstash 和 Fluentd 是两大主力。我两个都深度用过,说说感受。

Logstash 优势在生态:输入插件 50+,过滤插件 60+,输出插件 70+。你想到的格式它基本都能解析。缺点是吃内存,JVM 的垃圾回收(GC)在大流量下会抖动。

Fluentd 优势在性能:Ruby 写的内核,但底层 C 插件效率很高。内存占用稳定,GC 影响小。插件数量略少,但对于 90% 的场景够用了。

我个人的选择标准:

  • 团队熟悉 Java 栈?用 Logstash,排查 JVM 问题有经验。
  • 追求极致资源?用 Fluentd,或者 Fluent Bit(轻量版)。
  • 需要复杂分析(grok、geoip、kv)?Logstash 更顺手。

一个真实案例:某金融项目要求每秒 5 万条日志实时入库。一开始用单机 Logstash,发现 GC 停顿导致偶发 3-5 秒延迟。后来改成 Logstash + 持久化队列(queue.type: persisted),并把 worker 数调到 CPU 核心数的 2 倍,延迟稳定在 200ms 以内。这个调节参数我做了很多次实验才找到最佳值。

4.6 采集架构的几个关键参数

无论用哪种采集器,下面这几个参数你一定要调:

参数 推荐值 为什么重要
harvester_limit 100 - 200 防止文件句柄撑爆 ulimit
close_inactive 5m - 10m 自动关闭不活跃文件,减少资源
pipeline.workers CPU 核数 × 2 Logstash/Fluentd 并行处理调优
queue.type persisted (生产环境) 防止进程重启导致数据丢失
flush_interval 1s - 5s 批量写入,减少网络 IO 次数
retry_limit 5 - 10 重试策略,避免死循环

最后一点,关于数据的可靠性。我的原则是:边缘层尽量不存,聚合层必须排队。Filebeat 可以配置 registrty 文件记录读取偏移,Logstash 用持久化队列。两层保障下来,99.99% 的场景不会丢数据。