技术探索与实践
一次“摸着石头过河”的技术探索 —— 我如何从0到1搭建了一个高并发日志处理系统

引言:一个看似简单的任务,却暴露了架构的短板
去年我在一家中型电商平台负责后端架构优化。随着业务快速增长,我们原有的日志收集系统已经暴露出多个问题:响应延迟大、丢数据、排查困难。最初领导只是让我“优化一下”,但实际接触后才发现,这不仅仅是性能问题,而是一整套日志体系都需要重构。
于是,我决定推倒重来,用更现代、可扩展的方式构建一个新的日志采集和分析平台。整个过程历时两个月,中间踩了不少坑,也积累了不少实战经验,今天就结合这个项目,聊聊技术探索与实践的一些心得。
背景介绍:为什么我们要重构日志系统?
我们的原始架构非常简单粗暴:
- 应用层通过
logback写本地文件 - 每台机器上部署一个
logstash把日志打到 Kafka - 后面是 ELK(Elasticsearch + Logstash + Kibana)做分析
这套方案在初期确实能满足需求,但随着服务节点数量增长到 200+,访问量突破百万 PV/天后,出现几个问题:
- 丢日志严重:部分日志未能成功写入 Kafka
- 堆积延迟:Kafka 消费慢,日志经常滞后十几分钟
- 存储压力大:ELK 成本迅速上升,查询也变慢
- 定位困难:出问题时要登录多台机器查日志,效率极低
这时候我们就意识到:必须重新设计一整套日志处理链路,才能支撑未来 10 倍的业务增长。
面临的挑战:不只是选组件,而是重新思考整个流程
新的日志平台目标很明确:
- 实时性强,延迟控制在秒级内
- 稳定可靠,日志不丢失
- 可扩展性强,能应对不断新增的服务
- 查询友好,支持灵活分析
但这些要求具体怎么落地?我们首先要面对的是:
挑战一:采集方式的选择
是继续用 logstash?还是换成 filebeat 或者 Loki 这类轻量级组件?
我们做了个小实验,在 50 台应用服务器上分别跑 logstash 和 filebeat,结果发现 logstash 占用内存高出近两倍,CPU 使用率也不稳定。考虑到我们还有大量的 Kubernetes Pod 日志需要采集,最终我们选择了以 filebeat + fluent-bit 的组合为主。
挑战二:传输通道稳定性
Kafka 当然还是首选,但它本身也需要合理的 Topic 分区策略、副本配置等细节调整。另外,我们在测试过程中遇到消费者反压导致生产者阻塞的问题,后来加上了缓冲队列(Redis Stream)缓解高峰流量冲击。
挑战三:日志结构标准化
不同团队输出的日志格式五花八门,有的用 JSON,有的直接文本带时间戳。为了统一查询入口,我们制定了内部规范,强制要求所有服务使用 Structured Logging,并且每个条目包含 trace_id、service_name、timestamp、level 等字段。
技术实现:一条全新的日志管道搭建过程
最终我们构建的日志处理流水线如下:
[App Logs]
↓ (filebeat/fluent-bit)
[Kafka Topics]
↓
[Log Aggregator: Fluentd]
↓
[Elasticsearch / Object Storage (S3)]
↓
[Kibana / Grafana Loki]
核心组件:
| 组件 | 作用 |
|---|---|
| filebeat | 主机日志采集 |
| fluent-bit | 容器日志采集 |
| Kafka | 消息中间件,解耦采集和处理 |
| Fluentd | 日志清洗、过滤、路由 |
| Elasticsearch | 支持全文检索 |
| S3 | 归档冷数据 |
| Loki + Promtail | 结合 Prometheus 做日志监控 |
为什么要同时保留 Elasticsearch 和 Loki?
因为我们既希望快速检索特定关键字,又能基于 metric 找到对应日志上下文,两者互补效果更好。
关键代码片段 & 配置示例
1. Filebeat 输出到 Kafka 的配置片段:
output.kafka:
hosts: ["kafka-broker1:9092", "kafka-broker2:9092"]
topic: '%{[fields.log_type]}'
partition.round_robin:
reachable_only: true
required_acks: 1
compression: gzip
max_message_bytes: 1000000
这里我们根据日志类型动态分配 Topic,比如 app_log、access_log 等,方便后续按需消费。

2. Fluentd Kafka 插件配置:
<source>
@type kafka
brokers "kafka-broker1:9092,kafka-broker2:9092"
topics app_log,access_log
format json
tag_prefix logs.
</source>
<match logs.app_log>
@type elasticsearch
host "es-host"
port 9200
index_name "logs_app_%Y%m%d"
type_name _doc
</match>
这段配置从 Kafka 拉取日志,并插入 Elasticsearch。
3. Loki 接收日志的 Promtail 配置:
server:
http_listen_port: 9080
grpc_listen_port: 0
positions:
filename: /tmp/positions.yaml
scrape_configs:
- job_name: application_logs
static_configs:
- targets:
- localhost
labels:
job: "application-logs"
__address__: "localhost:12345"
pipeline_stages:
- regex:
expression: '^(?P<time>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) \[(?P<level>\w+)\] (?P<message>.*)$'

Promtail 会监听日志路径,并将日志转发给 Loki 服务。
踩过的坑 & 解决方法分享
1. Kafka 数据堆积怎么办?
上线初期某天晚上,突然收到告警,Kafka 中积压了上百 GB 日志,Fluentd 消费不过来。
排查发现是 Elasticsearch 在某个时间段写入异常缓慢,导致 Fluentd 缓冲池撑满。
解决办法:
- 加了 Redis Stream 作为二级缓冲
- Fluentd 增加了 retry 机制
- 对 Elasticsearch 写入速度做压测并扩容了两个节点
2. 日志丢失现象严重
一开始 filebeat 的默认配置里没有开启 ACK 确认机制,导致某些日志被“静默”忽略。
解决方式是在 filebeat.yml 中添加:
spool_size: 2048
publish_async: false
这样确保每条日志都真正写到了 Kafka 才从本地删除。
3. 磁盘 IO 不堪重负
因为 Elasticsearch 是每天一个 index,我们一开始没做 TTL 控制,导致磁盘暴涨。
解决方案很简单,加了 ILM(Index Lifecycle Management)策略:
{
"policy": {
"phases": {
"hot": {
"min_age": "0ms",
"actions": {
"rollover": {
"max_age": "1d",
"max_size": "50gb"
}
}
},
"delete": {
"min_age": "7d",
"actions": {
"delete": {}
}
}
}
}
}
这样可以自动滚动 index 并删除旧数据。
最终成果与收获
新系统上线后,整体表现提升明显:
- 日志延迟从原来的几分钟下降到秒级
- 日志完整率达到 99.9%+
- 查询响应速度提升 3~5 倍
- 存储成本降低约 40%,归档转存 S3 显著减轻 ES 压力
更关键的是,运维同学现在可以通过 Kibana 和 Grafana 快速定位故障根因,节省了大量的排障时间。
此外,这次经历让我们意识到:一个好的日志体系不是靠堆组件,而是要在结构设计、标准化、上下游协同上下功夫。
我的几点建议与反思
如果你也在考虑搭建或升级日志系统,不妨参考以下几个方向:
✅ 标准化永远是第一位
无论你用什么工具,先制定好日志格式规范、采集方式、命名规则,否则后续维护起来极其痛苦。
✅ 不要追求“一步到位”
很多同学总想找个“终极方案”,其实没有银弹。可以根据当前痛点先解决最严重的瓶颈,再逐步迭代。
✅ 监控一定要提前布局
无论是采集端、传输通道还是下游存储,都要有完整的健康检查和报警机制。我们就是在日志积压之后才补上了 Prometheus + Grafana 的监控体系。
✅ 做好性能测试和容量规划
上线前一定要压测!压测!再压测!包括高并发场景下的 Kafka 吞吐、ES 写入速度、Filebeat 的负载能力等等。
✅ 技术选型要考虑团队能力
不要盲目追新。比如当时我们考虑过 Vector,但团队对 Rust 不熟悉,最后还是选择了熟悉的 Fluentd + Filebeat 组合。
写在最后:每一次“折腾”都是成长
回顾这次技术重构的过程,其实并不是那么顺利。有很多深夜都在调试 Kafka 消费、优化索引结构,甚至还要和业务部门沟通他们写的日志乱七八糟……
但正是因为经历了这些“磨合期”,我才更加理解了什么是“工程化的日志处理系统”。它不仅仅是几个工具搭在一起运行,更是涉及到可观测性、服务治理、团队协作等多个维度的复杂工程。
如果你也在做类似的技术尝试,别怕麻烦,也不要怕犯错。技术探索从来都不是一蹴而就的事,有时候就是得边走边看,边学边改——毕竟,真正的成长,往往藏在那些你不愿意重复的“坑”里。

评论 0