2、日志采集架构设计:采集层、传输层、存储层

日志采集不是把文件一读就完事。我早期做CA日志项目时,就踩过这个坑——以为随便写个tail -f + scp就能搞定。结果呢?日志没丢是万幸,但半夜告警全堆上来了。后来我才明白,必须把架构拆成三层来设计:采集层、传输层、存储层。

说白了,这三层各管一摊事,但又要无缝配合。你想想看,采集层负责“拿到日志”,传输层负责“安全送过去”,存储层负责“好好存着”。嗯,咱们一层一层聊。

核心原则:采得快、送得稳、存得牢。任何一层出问题,整个日志链路就断了。

采集层:从源头拿到日志

采集层是所有日志的起点。CA系统的日志来源五花八门:syslog、文本文件、数据库审计、API接口、Windows Event Log… 我习惯把采集器部署在靠近日志源的地方,尽量不增加被采集系统的负载。

采集方式对比:

方式 适用场景 常见工具
轮询读取 文件日志(如/var/log/ca*.log) Filebeat、Logstash
syslog接收 网络设备、Linux服务器 rsyslog、syslog-ng
API拉取 云服务、审计接口 自定义HTTP采集器
Agent推送 Windows/C/S架构 Winlogbeat、Telegraf

避坑指南:我曾经在采集层忘了加“断点续采”能力,结果网络一抖,日志文件被truncate了,后面全部丢了一截。后来每个采集器都必须记录cursor(偏移量),哪怕机器重启也能接着读。

注意:确保采集器有足够的本地缓存。CA日志一天的量可能上百GB,网络短暂阻塞时,采集器内存别爆掉。Filebeat有spool大小限制,调大一点有备无患。

传输层:把日志安全送到目的地

传输层是中间的“高速公路”。我见过不少项目直接拿HTTP POST传日志——简单是简单,但一旦连接断开、数据积压,基本就崩了。我个人建议用消息队列做缓冲,比如Kafka、RabbitMQ、Redis Stream。

怎么做?

  • 采集器把日志发到Kafka Topic(按类型分区:CA_audit、CA_error、CA_syslog等)
  • 消费者从Topic拉出来,可以加一层轻量处理(格式清洗、脱敏、压缩)
  • 再转发给存储层

安全层面:传输必须加密。我曾在一个客户环境里,日志明文走公网跑,结果被第三方抓包看到了CA的证书请求记录… 那场面,嗯,尴尬。所以传输层至少要做TLS加密,如果内网也要考虑ACL和网络隔离。

传输协议对比:

协议 吞吐量 可靠性 适用场景
Kafka(TCP) 高 高 大规模、高可用
HTTP/HTTPS 中 低(需重试) 轻量、内网调试
gRPC 高 中 微服务、双向流
syslog over TLS 低 中 传统设备

个人经验:Kafka的partitions数不要拍脑袋设。我一般按日志类型的平均QPS来算,每个partition吞吐约1MB/s,再预留30%余量。直接默认值往往会遇到倾斜问题。

存储层:让日志随时可用

存储层是归宿。CA日志需要长期保留(合规要求有时3-7年),还要支持快速检索。我建议分层存储:热数据放Elasticsearch或ClickHouse,温数据用对象存储(S3/MinIO),冷数据归档到廉价存储甚至磁带。

分层策略表:

层级 存储引擎 保留周期 查询响应
热 Elasticsearch 30天 秒级
温 MinIO / S3 1年 分钟级(需加载)
冷 磁带 / Glacier 7年 小时级

索引策略:不能所有字段都建索引,否则Elasticsearch的映射膨胀成灾难。我一般只保留:时间戳、日志级别、来源IP、错误码、证书序列号。其他字段走全文检索。

我曾经… 没考虑存储的容量预警,结果ES集群磁盘写满,导致整个采集链路阻塞。后来每个存储节点必须配80%告警、90%只读、95%自动清理策略。

整体架构图

日志采集三层架构图 采集层 syslog 文件监控 API拉取 Agent推送 传输层 Kafka 消息队列 TLS 加密通道 流量整形/去重 存储层 Elasticsearch 热 MinIO 温 Glacier 冷 自动归档 采集 传输 存储

上面这张图已经说得很清楚了。三层各司其职,数据流从上到下。实际部署时,每一层都可以分布式扩展——比如采集层用Filebeat集群,传输层Kafka加多broker,存储层ES做多节点集群。

再次强调:采集层不要设计成单点故障,传输层要有背压和重试机制,存储层要周期做健康检查。这三层一旦形成Pipeline,监控也要跟上——我习惯给每层打“心跳日志”,十分钟一次,如果某条链路断了,告警系统立刻能发现。

好了,第二层到这一步,你应该对日志采集的整体架构有个清晰的轮廓了。我最后分享一个实战教训:有一次上线,我忘了给传输层加限流,结果日志量突然激增,Kafka consumer消费不过来,最后OOM挂掉。从那以后,每个采集器我都会设置采集速率上限(比如20MB/s),传输层再加一层背压。切记,不要相信“永远不会满”的系统。三层设计给的冗余,就是为了应对这些突发情况。