第4章 日志采集实战:Filebeat配置与部署、多数据源采集、日志过滤与清洗

日志采集这件事,说白了就是做市系统的「耳朵」和「眼睛」。

我见过太多团队,策略写得漂亮,回测曲线完美,一上线就抓瞎。为什么?因为日志没采好。系统崩了不知道原因,延迟高了找不到瓶颈,订单丢了查不到痕迹。嗯,这章我们就来搞定这件事。

4.1 Filebeat 是什么?为什么选它?

做市系统每秒产生成千上万条日志。你想想看,如果用传统的 Logstash 直接采集,CPU 和内存分分钟被打满。Filebeat 不一样,它是个轻量级的采集器,资源占用极低。

我个人习惯把 Filebeat 部署在每台交易服务器上。它只负责一件事:读日志文件,然后发出去。至于解析、过滤、清洗,那是后面 Logstash 或 Kafka 的事。

核心优势:

  • 内存占用通常不到 20MB
  • 自带背压机制,不会把下游打爆
  • 支持 SSL/TLS 加密传输
  • 断点续传,日志不会丢

4.2 安装与基础配置

安装其实很简单。我一般用 RPM 包直接装,省事。

# 下载并安装
curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-7.17.0-x86_64.rpm
sudo rpm -vi filebeat-7.17.0-x86_64.rpm

# 或者用 Docker
docker run -d \
  --name=filebeat \
  --user=root \
  -v /var/log/market_maker:/var/log/market_maker \
  -v /etc/filebeat/filebeat.yml:/usr/share/filebeat/filebeat.yml \
  docker.elastic.co/beats/filebeat:7.17.0

装完之后,核心就是配置 filebeat.yml。我直接给你看一个做市系统的典型配置:

filebeat.inputs:
- type: log
  enabled: true
  paths:
    - /var/log/market_maker/trade.log
    - /var/log/market_maker/order.log
  fields:
    service: market_maker
    env: production
  fields_under_root: true

- type: log
  enabled: true
  paths:
    - /var/log/market_maker/risk.log
  fields:
    service: risk_engine
    env: production
  fields_under_root: true

output.elasticsearch:
  hosts: ["http://elasticsearch:9200"]
  index: "market-maker-%{+yyyy.MM.dd}"
  pipeline: "market_maker_pipeline"

logging.level: info

这里有个细节要注意:fields_under_root: true 这个参数。如果不加,自定义字段会被嵌套在 fields 对象里,后面查询的时候要多点一层,很烦人。

我曾经踩过的坑:

有一次我把 trade.log 和 order.log 放在同一个 input 里,结果日志行号错乱了。因为 Filebeat 是按文件 inode 来跟踪读取位置的,两个日志文件写入频率不同,会导致读取指针互相干扰。所以,不同业务类型的日志,一定要分开配置 input。

4.3 多数据源采集实战

做市系统的数据源,远不止交易日志这么简单。我列一下常见的采集目标:

数据源 日志路径 采集频率 说明
交易日志 /var/log/market_maker/trade.log 实时 每笔成交记录
订单日志 /var/log/market_maker/order.log 实时 订单生命周期
风控日志 /var/log/market_maker/risk.log 实时 风控规则触发记录
系统指标 /var/log/syslog 每10秒 CPU、内存、磁盘
网络延迟 /var/log/market_maker/latency.log 实时 交易所到本机的网络延迟

多数据源采集的关键,在于给每个数据源打上正确的标签。我习惯用 fields 来标记,这样到了 Elasticsearch 里,直接按 service 字段就能区分。

filebeat.inputs:
- type: log
  paths:
    - /var/log/market_maker/latency.log
  fields:
    service: latency_monitor
    type: network
  fields_under_root: true

- type: log
  paths:
    - /var/log/syslog
  fields:
    service: system_monitor
    type: infrastructure
  fields_under_root: true

4.4 日志过滤与清洗

原始日志里,90% 都是垃圾信息。你想想看,做市系统每秒可能打印几百条 debug 日志,真正有用的可能就几条。不过滤的话,Elasticsearch 的存储成本会让你哭。

我一般分三层来做过滤:

  1. Filebeat 层:用 include_linesexclude_lines 做粗过滤
  2. Logstash 层:用 grok 做结构化解析
  3. Elasticsearch 层:用 ingest pipeline 做最终清洗

先看 Filebeat 层的配置:

filebeat.inputs:
- type: log
  paths:
    - /var/log/market_maker/trade.log
  include_lines: ['(ERROR|WARN|CRITICAL|成交|撤单)']
  exclude_lines: ['^DEBUG', '^INFO.*心跳']
  multiline:
    pattern: '^\d{4}-\d{2}-\d{2}'
    negate: true
    match: after

这里 multiline 配置很重要。做市系统的异常日志经常跨多行,比如 Java 的堆栈信息。如果不合并,一条异常会被拆成几十条记录,根本没法看。

我的个人经验:

多行合并的正则,一定要用日志行首的时间戳格式来匹配。别用异常关键字,因为有些日志行首是空格或 tab,匹配不准。

再看 Logstash 层的 grok 解析。我直接给一个做市系统订单日志的解析示例:

filter {
  if [service] == "market_maker" {
    grok {
      match => {
        "message" => "%{TIMESTAMP_ISO8601:timestamp} \[%{LOGLEVEL:level}\] %{DATA:thread} %{DATA:class} - 订单ID=%{NUMBER:order_id} 方向=%{WORD:side} 价格=%{NUMBER:price} 数量=%{NUMBER:quantity} 状态=%{WORD:status}"
      }
    }
    
    date {
      match => ["timestamp", "ISO8601"]
      target => "@timestamp"
    }
    
    mutate {
      convert => {
        "order_id" => "integer"
        "price" => "float"
        "quantity" => "integer"
      }
    }
  }
}

解析完之后,原始日志里的字符串就变成了结构化的字段。你可以直接在 Kibana 里按 order_id 搜索,按 price 做聚合,按 status 做过滤。这才是我们想要的。

4.5 核心架构图

下面这张图,是我在做市系统里实际使用的日志采集架构。你看一眼就明白了:

做市系统日志采集架构 交易日志 风控日志 系统指标 Filebeat 采集器 多数据源采集 · 粗过滤 · 多行合并 · 断点续传 Logstash / Elasticsearch Pipeline Grok 结构化解析 · 字段类型转换 · 数据清洗 Elasticsearch 存储 · Kibana 可视化

4.6 避坑指南

最后,我把自己这些年踩过的坑总结一下:

我曾经犯过的错误:

  • 日志轮转问题:Linux 的 logrotate 默认会重命名日志文件。Filebeat 如果没配置 close_renamed: true,会丢失轮转期间的日志。我那次丢了整整 10 分钟的订单数据,排查了三天才发现是这个原因。
  • 正则性能陷阱:grok 正则写得太复杂,CPU 直接飙到 90%。后来我把正则拆成多个小规则,用 break_on_match 控制,性能提升了 5 倍。
  • 时间戳时区:做市系统日志用的是 UTC 时间,但 Elasticsearch 默认用本地时区。如果不显式指定时区,你查到的日志时间全是乱的。记得在 Logstash 里加 timezone => "UTC"

嗯,日志采集这块,说白了就是「采得全、传得快、存得省」。Filebeat 只是第一步,后面还有 Logstash 解析、Elasticsearch 存储、Kibana 可视化。但这一步如果没走稳,后面全是白搭。

本章核心要点:

  • Filebeat 配置要按业务类型分开 input
  • 多数据源用 fields 打标签区分
  • 过滤分三层:Filebeat 粗过滤 → Logstash 结构化 → ES 最终清洗
  • 多行合并用时间戳正则,别用关键字
  • 日志轮转、正则性能、时区设置是三大常见坑

公众号:蓝海数据掘金营,微信deep3321