3. 日志采集与传输:Filebeat、Logstash 与 Kafka 的实战配合

日志系统,说白了就是运维的「眼睛」。你想想看,线上出了故障,没有日志,你连问题在哪都不知道。我做了这么多年运维,最怕的就是半夜被叫起来,然后发现日志没采上来——那感觉,真叫一个绝望。

今天咱们聊聊日志采集与传输的铁三角:Filebeat、Logstash 和 Kafka。这三兄弟各司其职,配合好了,你的日志系统稳如老狗;配合不好,那就是灾难现场。

核心一句话:Filebeat 负责「采」,Logstash 负责「洗」,Kafka 负责「存和传」。各干各的活,别让它们串了。

日志采集与传输核心架构 应用服务器 (日志源) Filebeat 轻量采集器 Kafka 消息队列 Logstash 过滤/传输 采集日志文件 发送到 Kafka 缓冲/削峰 过滤后写入 ES 数据流方向:日志文件 → Filebeat → Kafka → Logstash → Elasticsearch 解耦、削峰、高可用,缺一不可

3.1 Filebeat:轻量级日志采集器

先说说 Filebeat。这玩意儿,我愿称之为「日志采集界的瑞士军刀」。为什么?因为它轻啊!

我记得有一次,客户那边服务器配置低得可怜,2核4G的机器上跑着十几个 Java 应用。想装 Logstash 采集日志?内存直接爆了。后来换成 Filebeat,内存占用才几十兆,稳得很。

Filebeat 的核心优势:

  • 资源占用极低:Go 语言编写,内存常驻 20-50MB
  • 断点续传:记录读取位置,重启后不会重复采集
  • 背压机制:下游处理不过来时,自动降速
  • 多输出支持:直接输出到 Elasticsearch、Logstash、Kafka

我的习惯:生产环境我一般把 Filebeat 直接输出到 Kafka,而不是 Logstash。原因很简单——解耦。Filebeat 只管采,Kafka 只管存,Logstash 只管洗。谁挂了都不影响谁。

来看一个典型的 Filebeat 配置:

# filebeat.yml
filebeat.inputs:
- type: log
  enabled: true
  paths:
    - /var/log/app/*.log
  fields:
    app_name: myapp
    env: production

output.kafka:
  hosts: ["kafka1:9092", "kafka2:9092"]
  topic: "app-logs"
  partition.round_robin:
    reachable_only: true
  required_acks: 1
  compression: gzip

这里有个坑,我踩过。你看 required_acks: 1 这个参数,意思是只要 Kafka leader 确认就算成功。如果设成 all,性能会下降不少。但如果你对数据完整性要求极高,那就得用 all。嗯,看场景取舍吧。

3.2 Logstash:日志过滤与传输

Logstash 是 ELK 栈里的「老大哥」。功能强大,但也是个「内存吃货」。我见过有人把 Logstash 当采集器用,结果 8G 内存的机器跑几天就 OOM 了。千万别这么干!

Logstash 的核心价值在于数据清洗和转换。你想想看,原始日志长什么样?乱七八糟的。有 JSON 格式的,有纯文本的,有带时间戳的,有不带的。Logstash 就是要把这些「脏数据」洗成统一格式。

Logstash 的三大核心组件:

组件 作用 实战建议
Input 数据输入 从 Kafka 读取,别直接从文件读
Filter 数据过滤 grok 解析、date 时间处理、mutate 字段修改
Output 数据输出 写入 Elasticsearch,注意索引模板

我曾经接手过一个项目,日志里时间戳格式五花八门。有的用 2024-01-15T10:30:00Z,有的用 2024/01/15 10:30:00。Logstash 的 date 插件就是干这个的:

filter {
  grok {
    match => { "message" => "%{TIMESTAMP_ISO8601:log_time} %{LOGLEVEL:level} %{GREEDYDATA:msg}" }
  }
  date {
    match => ["log_time", "ISO8601", "yyyy/MM/dd HH:mm:ss"]
    target => "@timestamp"
  }
  mutate {
    remove_field => ["log_time", "path"]
  }
}

注意:grok 正则表达式很消耗 CPU。如果你的日志量很大(比如每秒几万条),建议在 Logstash 里只做必要的解析,复杂的业务解析放到下游处理。我曾经因为 grok 规则写得太复杂,导致 Logstash CPU 飙到 90%,后来拆了一部分规则才解决。

3.3 Kafka:消息队列在日志系统中的作用

Kafka 在日志系统里扮演什么角色?说白了就是个「缓冲池」。你想想看,业务高峰期日志量暴增,Logstash 处理不过来怎么办?直接丢数据?那肯定不行。

有了 Kafka,Filebeat 只管往 Kafka 里写,Logstash 按自己的节奏从 Kafka 里读。这就叫削峰填谷。

Kafka 在日志系统中的三大作用:

  1. 解耦:采集端和处理端互不依赖,任何一方挂了都不影响另一方
  2. 缓冲:应对突发流量,数据不会丢
  3. 多消费:同一份日志,可以同时被 Logstash、实时计算、离线分析等多个系统消费

我记得有一次双十一大促,日志量从平时的每秒 2000 条飙升到每秒 5 万条。如果没有 Kafka,Logstash 直接扛不住,Elasticsearch 也得被写爆。但有了 Kafka 在前面顶着,Logstash 慢慢消费,虽然查询有延迟,但数据一条没丢。

避坑指南:Kafka 的 topic 分区数要提前规划好。我曾经图省事只设了 3 个分区,结果消费者多了之后,有的分区忙死,有的分区闲死。一般建议分区数 = 消费者线程数 × 2,方便后续扩展。

来看一个 Kafka 生产者的关键配置:

# Kafka 生产者配置(在 Filebeat 或 Logstash 中)
acks = 1                    # 只要 leader 确认
retries = 3                 # 重试次数
batch.size = 16384          # 批量发送大小(字节)
linger.ms = 100             # 等待时间(毫秒)
compression.type = gzip     # 压缩,减少网络带宽

这里 linger.ms 和 batch.size 是性能调优的关键。你想想看,如果每条日志都立即发送,网络开销很大。设一个 100ms 的等待时间,攒一批再发,吞吐量能提升好几倍。

3.4 三者配合的最佳实践

说了这么多,咱们总结一下这三兄弟怎么配合最舒服:

  • 采集层:Filebeat 部署在每台应用服务器上,只负责采集和发送
  • 传输层:Kafka 集群作为中间缓冲,保证数据不丢
  • 处理层:Logstash 从 Kafka 消费,过滤后写入 Elasticsearch

这种架构的好处是:任何一个环节出问题,都不会导致数据丢失。Filebeat 挂了?重启后断点续传。Kafka 挂了?Filebeat 会重试。Logstash 挂了?Kafka 里数据还在,重启后继续消费。

一句话总结:Filebeat 负责「采得动」,Kafka 负责「存得住」,Logstash 负责「洗得净」。各司其职,别越界。

嗯,这套架构我在多个项目中验证过,从日处理几百万条到几十亿条日志,都能扛得住。你照着这个思路搭,基本不会出大问题。


可可精品资料库