采集架构设计:Agent模式、无Agent模式、集中式与边缘采集、高可用与容错
日志采集架构是整个系统的骨架。骨架歪了,后面加再多肉也站不稳。我见过不少团队一上来就选 Filebeat 配 Kafka,结果业务量上去后 Agent 占满磁盘 IO,或者无 Agent 模式被防火墙堵死。说白了,选架构不是拍脑袋,得从场景、资源、容错三个维度去权衡。
这一章我们就把四种核心架构掰开揉碎。我会结合自己踩过的坑,聊聊 Agent 模式和无 Agent 模式的适用边界,集中式与边缘采集的取舍,以及怎么让采集链路在高负载下不丢数据。
Agent模式 vs 无Agent模式
先上一个对比表,方便你快速建立认知:
| 维度 | Agent模式 | 无Agent模式 |
|---|---|---|
| 部署方式 | 每台机器安装独立进程(如 Filebeat、Fluentd) | 应用 SDK 直写 / syslog 推送 / 挂载共享卷 |
| 资源占用 | 额外 CPU 和内存,需要独立运维 | 在应用进程内消耗,无独立进程开销 |
| 灵活性 | 可独立升级、配置、过滤、缓冲 | 依赖应用改造,变更影响面大 |
| 安全性 | Agent 需要一定系统权限 | 通常只需网络端口权限 |
| 典型场景 | 物理机 / 虚拟机 / 容器化环境 | Serverless / 云原生短生命周期任务 |
Agent 模式 是我用得最多的方案。记得有一次在 Kubernetes 集群里跑 Filebeat,每个 Pod 配一个 sidecar,结果集群规模从 200 节点涨到 500 节点,Agent 的 CPU 飙升到 15%。后来我把采集规则从全量正则改成结构化 JSON 解析,再配合背压机制,才稳住。嗯,这里有个关键点——Agent 不是装上去就完事,你得给它设置好保护:内存上限、磁盘缓冲大小、重试间隔。
无 Agent 模式 听起来轻量,其实坑不少。比如 Java 应用直接通过 Log4j2 的 SocketAppender 发日志,一旦接收端故障,日志就会在应用内存里堆积甚至 OOM。我建议只在两种场景用:一是函数计算等天然无服务器环境,二是日志量极小且容错要求不高的内部工具。你想想看,如果丢失几个日志不影响核心 SLA,用无 Agent 确实省事。
集中式采集 vs 边缘采集
说完了 Agent,再看数据该往哪 flush。这是一个典型的网络拓扑问题,但很多人一开始只盯着 Kafka 集群,忽略了边缘节点的重要性。
| 对比项 | 集中式采集 | 边缘采集 |
|---|---|---|
| 数据流 | Agent → 中心集群(Kafka / Logstash) | Agent → 边缘网关 → 中心集群 |
| 网络压力 | 所有流量直打中心,带宽容易成瓶颈 | 边缘做预聚合、过滤,大幅降低上行带宽 |
| 延迟 | 端到端延迟低(一跳) | 多一跳,增加 10~50ms |
| 运维复杂度 | 中心集群压力大,需做读写分离 | 需要管理边缘节点,但中心集群压力分散 |
| 适用规模 | 百台级别 | 千台以上或跨区域部署 |
我曾在一个跨国电商项目中遇到一个典型场景:东南亚机房日志直连到国内中心,跨国专线带宽不够,而且晚上高峰时日志经常堵在 Agent 的磁盘缓冲里。后来我们在每个区域部署一个轻量边缘网关(用 Vector 实现),做了三件事:
- 预过滤——丢弃 DEBUG 级别日志,只保留 WARN 以上 + 慢查询。
- 本地持久化——用 RocksDB 做缓冲,避免网络抖动丢数据。
- 分批传输——每 30 秒压缩一批,减少连接数。
效果很明显:中心集群的写入压力降低了 60%,跨区域带宽费用减了一半。不过别高兴太早,边缘网关本身也是故障点。我曾经因为边缘节点磁盘写满,导致日志积压了 4 小时才恢复。所以边缘节点必须做磁盘水位监控和自动清理策略。
高可用与容错:怎么让采集链路不丢数据
架构选好了,如果传输链路一跳就断,前面全白忙。我见过最惨的一次:Kafka 集群磁盘写满,Logstash 消费线程被熔断,结果 Agent 的磁盘缓冲也满了,开始循环丢弃旧日志。等恢复后一看,丢了 3 个小时的线上错误日志。
高可用设计需要覆盖三个层面:
- Agent 层:配置本地磁盘缓冲(推荐大小 = 最大消息体 × 峰值每秒 × 15 分钟)。Filebeat 的
queue.mem.events和 Fluentd 的buffer插件都可以做。注意缓冲不能放在 tmpfs,否则机器重启就全没了。 - 传输层:使用至少冗余的两条上游链路。比如 Agent 配置两个 Kafka Broker 列表,或者用 load balancer 做 TCP 代理。别只依赖 DNS 轮询——DNS 缓存失效时连接会全断。
- 中心层:Kafka 配置副本数 ≥ 2,ACK 策略设为 all(确保所有副本都收到才返回)。Logstash 或 Flink 消费端要开启 exactly-once 语义,或者退而求其次用 at-least-once + 去重。
关于容错,我特别想提一个细节——背压(backpressure)。很多 SDK 和 Agent 默认是不限制发送速率的,一旦下游慢,上游就会把内存打爆。我现在每个 Agent 都会配一个速率限制:
# Filebeat 示例:限制输出最大吞吐
output.kafka:
hosts: ["kafka1:9092", "kafka2:9092"]
topic: "app-logs"
max_message_bytes: 1048576
# 关键:限制每秒发送批次
bulk_max_size: 2048
# 背压超时,下游不可用时等待 60 秒再重试
backoff.init: 1s
backoff.max: 60s
架构选型决策流程图
下面这张 SVG 图总结了四种架构的关系和适用边界。灰色框是决策点,彩色节点是你最终选择的方案。你可以把它贴在团队技术文档里当速查表。
你发现没有,这个图右上角那个无Agent模式有一条回退线——如果你不能接受丢日志,就加本地缓冲退化成 Agent 模式的变体。实际上,很多云原生场景就是用这种混合方式:函数计算里加一个轻量 sidecar 做缓冲,平时不用,异常时自动拉起。
好了,关于采集架构的核心模型就聊到这。下次你要做日志方案评审时,拿这张图和三个表格去怼需求方,基本不会翻车。记住一点:架构没有银弹,只有权衡。