第二章:日志采集架构深度解析

日志采集架构,说白了就是解决一个问题:日志怎么从分散的服务器,安全、高效地送到分析平台。我见过太多团队,一开始随便搭个采集就上线,结果日志丢了、格式乱了、甚至把业务系统拖垮了。嗯,这章咱们就把三种主流架构掰开揉碎讲清楚。

2.1 集中式日志采集:ELK Stack

ELK 是 Elasticsearch、Logstash、Kibana 的缩写。这是最经典的集中式方案,我个人习惯把它叫做「日志界的瑞士军刀」。

2.1.1 架构原理

它的工作流很简单:

  1. Beats(轻量采集器)部署在业务服务器上,采集日志文件
  2. Logstash 接收日志,做过滤、解析、格式化
  3. Elasticsearch 存储和索引日志数据
  4. Kibana 做可视化和分析

我在项目中遇到过一个问题:Logstash 处理能力跟不上,导致日志积压。后来我调整了 pipeline 的 workers 数量,才把吞吐量提上去。这里有个坑——Logstash 默认只配了 2 个 worker,你想想看,如果日志量每秒上万条,肯定扛不住。

核心配置示例(Logstash pipeline):

input {
  beats {
    port => 5044
    client_inactivity_timeout => 60
  }
}

filter {
  grok {
    match => { "message" => "%{COMBINEDAPACHELOG}" }
  }
  date {
    match => [ "timestamp", "dd/MMM/yyyy:HH:mm:ss Z" ]
  }
}

output {
  elasticsearch {
    hosts => ["localhost:9200"]
    index => "weblog-%{+YYYY.MM.dd}"
  }
}

2.1.2 适用场景与局限

优势 劣势
部署简单,社区活跃 Logstash 资源消耗大
Kibana 可视化强大 扩展性有限(单点瓶颈)
适合中小规模(日均百GB以内) 日志格式变化时需要改配置

避坑指南:我曾经在客户现场看到他们把 Logstash 和 Elasticsearch 部署在同一台机器上。结果 Logstash 吃掉了大量内存,ES 的 JVM 堆直接爆了。记住:Logstash 和 ES 必须分开部署,最好用不同的物理机。

2.2 分布式日志采集:Flume + Kafka

当日志量达到 TB 级别,集中式架构就撑不住了。这时候需要引入消息队列做缓冲。我常用的组合是 Flume + Kafka

2.2.1 为什么需要 Kafka?

你想想看,如果日志采集速度 > 消费速度,会发生什么?Logstash 会直接丢数据。Kafka 就像一个巨大的缓冲区,数据先写到磁盘,消费端慢慢拉取。这样即使下游挂了,日志也不会丢。

2.2.2 Flume 的三种角色

  • Source:从哪里采集(tail -F 文件、监听端口、读取 Kafka)
  • Channel:临时存储(内存、文件、JDBC)
  • Sink:发送到哪里(HDFS、Kafka、Elasticsearch)

Flume 配置示例(采集 Nginx 日志到 Kafka):

agent.sources = tail-source
agent.channels = memory-channel
agent.sinks = kafka-sink

agent.sources.tail-source.type = spooldir
agent.sources.tail-source.spoolDir = /var/log/nginx
agent.sources.tail-source.fileHeader = true

agent.channels.memory-channel.type = memory
agent.channels.memory-channel.capacity = 10000

agent.sinks.kafka-sink.type = org.apache.flume.sink.kafka.KafkaSink
agent.sinks.kafka-sink.kafka.topic = nginx-log
agent.sinks.kafka-sink.kafka.bootstrap.servers = kafka1:9092,kafka2:9092

2.2.3 架构对比

特性 ELK 集中式 Flume + Kafka 分布式
吞吐量 百 MB/s GB/s 级别
数据可靠性 低(内存缓冲) 高(磁盘持久化)
扩展性 垂直扩展 水平扩展
运维复杂度 高(需要维护 Kafka 集群)

我的经验:如果日志量日均超过 500GB,别犹豫,直接上 Kafka。我曾经帮一家电商公司从 ELK 迁移到 Flume+Kafka,日志处理延迟从 30 秒降到了 2 秒以内。嗯,迁移过程确实痛苦,但效果立竿见影。

2.3 Agent 部署策略

Agent 怎么部署?这是个容易被忽视但极其重要的问题。我见过最离谱的案例:有人把采集 Agent 和业务进程混在一起,结果 Agent 出 bug 把 CPU 打满,业务直接挂了。

2.3.1 三种部署模式

  1. Sidecar 模式:每个业务容器/进程配一个 Agent
  2. Node 模式:每台物理机/虚拟机部署一个 Agent,采集所有日志
  3. DaemonSet 模式:Kubernetes 环境下,每个节点一个 Agent

2.3.2 选型建议

场景 推荐模式 原因
传统虚拟机部署 Node 模式 资源利用率高,管理简单
容器化/K8s DaemonSet 自动感知 Pod 生命周期
高安全隔离要求 Sidecar 一个 Agent 出问题不影响其他业务

2.3.3 资源限制与监控

Agent 必须做资源限制。我建议:

  • CPU:限制在 0.5 核以内
  • 内存:不超过 512MB
  • 磁盘:日志缓冲目录单独挂载,限制大小

我曾经踩过的坑:有一次 Agent 的日志缓冲目录写满了,导致系统盘爆掉。从那以后,我强制要求所有 Agent 的缓冲目录必须单独挂载,并且设置磁盘配额。你想想看,如果因为采集日志把业务系统搞崩了,那真是得不偿失。

2.4 架构选型总结

最后给个简单的选型建议:

  • 日均日志量 < 100GB:ELK 集中式就够了,别折腾
  • 日均 100GB - 1TB:Flume + Kafka,稳
  • 日均 > 1TB:上 Flume + Kafka + 多级聚合,必要时用 Spark Streaming 做实时处理

嗯,这一章的内容就到这里。记住一句话:日志采集架构没有银弹,适合你的业务场景才是最好的。下一章咱们聊聊日志格式标准化,这可是日志分析的基础中的基础。