日志采集架构设计

做 IM 通道日志分析,第一步就是把日志弄进来。说白了,你得先解决「数据怎么到分析平台」这个问题。

我在不少项目里见过同一个坑:业务方直接往 Elasticsearch 里写日志,结果索引乱成一锅粥。千万别这么干。日志采集层必须统一,这是架构底线。

为什么需要统一的采集层?

没有采集层,每台机器自己往外吐日志——格式不一样、传输协议不一样、压缩方式也不一样。后期你对接告警系统、做实时聚合,全都得改代码。

我个人的习惯是:所有采集端都用标准化 agent,别信什么「我用 SDK 打日志就够了」。IM 通道的日志量级,稍微大一点就能撑爆客户端。

  • 解耦:日志产生方和消费方不直接依赖
  • 弹性:采集端可以水平扩展,扛突发流量
  • 统一格式:到 Kafka 或 ES 前就完成结构化和字段映射
一个小建议:哪怕初期只有几台机器,也把采集层搭好。我见过从 5 台扩到 200 台时,因为没有采集层,整个日志管道重建的场景——那叫一个酸爽。

主流采集工具怎么选

目前 IM 场景里最常用的就两个:Filebeat 和 Logstash。很多人问能不能只用其中一个?可以,但你要清楚它们的分工。

对比项FilebeatLogstash
定位轻量日志收集器数据处理管道
资源占用极小(几 MB 内存)较大(JVM 开销)
数据处理能力弱(仅支持简单过滤)强(grok、mutate、丰富数据等)
输出插件覆盖常用(ES、Kafka、Logstash)丰富(100+ 种)
典型用法部署在业务服务器上收集日志中心化服务做数据清洗和路由

简单画个架构图就清楚了:

日志采集架构示意图 IM 应用服务器 IM 应用服务器 IM 应用服务器 Filebeat Logstash Kafka / ES 说明 Filebeat 部署在业务服务器上 Logstash 作为中心化处理层 Kafka/ES 作为最终存储与索引

Filebeat 配置实战

很多团队会纠结:我到底用 Filebeat 还是 Logstash 取日志?其实不冲突。我的惯用套路是:Filebeat 只负责收,Logstash 负责洗。

下面给一个我在 IM 项目中用过的配置文件模板,你直接拿去改。

filebeat.inputs:
- type: log
  enabled: true
  paths:
    - /var/log/im/access.log
    - /var/log/im/error.log
  fields:
    service: im-channel
    env: production
  fields_under_root: true

output.logstash:
  hosts: ["logstash-01:5044", "logstash-02:5044"]
  loadbalance: true

logging.level: info
logging.to_files: true
logging.files:
  path: /var/log/filebeat
  name: filebeat.log
  keepfiles: 7

关键配置解析

  • paths:支持通配符,别写死单个文件,IM 日志经常按天滚动
  • fields:加个 service 字段,方便后期区分是哪个模块的日志
  • loadbalance: true:一定要开,我踩过 Logstash 挂了一台后,Filebeat 还傻乎乎一直连那台的坑

Logstash 配置实战

Logstash 是真正的「管道核心」。它能把你丢过来的日志揉碎了、洗干净、再发出去。

我个人习惯把 pipeline 分成三段:input → filter → output。IM 通道的日志格式通常都不是标准的 JSON,得先用 grok 解析。

input {
  beats {
    port => 5044
  }
}

filter {
  if [service] == "im-channel" {
    grok {
      match => { "message" => "%{TIMESTAMP_ISO8601:timestamp} %{LOGLEVEL:loglevel} %{DATA:msg}" }
    }
    mutate {
      rename => { "loglevel" => "level" }
      add_field => { "source" => "im" }
    }
    date {
      match => [ "timestamp", "ISO8601" ]
      target => "@timestamp"
    }
  }
}

output {
  elasticsearch {
    hosts => ["es-01:9200", "es-02:9200"]
    index => "im-logs-%{+YYYY.MM.dd}"
    user => "${ES_USER}"
    password => "${ES_PASS}"
  }
}
我曾经踩过的坑:直接在 filter 里写大量 if-else 分支,导致 pipeline 处理延迟飙升。后来我把不同服务的日志分流到不同端口(比如 5044 给 IM,5045 给支付),pipeline 各自独立,性能提升了几倍。你想想看,一个 pipeline 里的 if 多了,照样影响吞吐。

采集端配置归纳总结

下面这张表你保存好,IM 通道日志采集的配置要点基本都在里面了。

配置项推荐值/策略理由
Filebeat input 类型log 类型 + 通配符路径IM 日志文件按时间滚动,用通配符避免遗漏
Filebeat outputLogstash 集群(loadbalance)避免单点挂掉数据丢失
Logstash inputbeats 插件 + 独立端口不同服务隔离,性能更好
Logstash filtergrok + date + mutate标准解析,时间字段对齐
Logstash outputES 或 KafkaES 直接查,Kafka 做缓冲
资源限制Filebeat CPU 上限 1 核,Logstash 上限 4 核我压测过,再高了收益递减

嗯,以上这些配置,基本能覆盖 90% 的 IM 通道日志采集场景了。剩下 10% 可能是跨机房、多 Region 的情况,那个我们后面再说。采集层搭好了,日志才能稳地流进后面的告警系统。