3. 日志采集与传输:Filebeat、Logstash 与 Kafka 的实战配合
日志系统,说白了就是运维的「眼睛」。你想想看,线上出了故障,没有日志,你连问题在哪都不知道。我做了这么多年运维,最怕的就是半夜被叫起来,然后发现日志没采上来——那感觉,真叫一个绝望。
今天咱们聊聊日志采集与传输的铁三角:Filebeat、Logstash 和 Kafka。这三兄弟各司其职,配合好了,你的日志系统稳如老狗;配合不好,那就是灾难现场。
核心一句话:Filebeat 负责「采」,Logstash 负责「洗」,Kafka 负责「存和传」。各干各的活,别让它们串了。
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 在日志系统中的三大作用:
- 解耦:采集端和处理端互不依赖,任何一方挂了都不影响另一方
- 缓冲:应对突发流量,数据不会丢
- 多消费:同一份日志,可以同时被 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 负责「洗得净」。各司其职,别越界。
嗯,这套架构我在多个项目中验证过,从日处理几百万条到几十亿条日志,都能扛得住。你照着这个思路搭,基本不会出大问题。
可可精品资料库