技术探索与实践总结:从一次日志平台升级说起

胡红_开发者
2025-06-21 20:50
阅读 564

开篇:技术人的日常就是不断解决问题

开篇:技术人的日常就是不断解决问题

大家好,我是某互联网公司的一名后端开发工程师,目前主要负责公司内部日志平台的维护与优化。在我们公司,日志平台是支撑多个业务线的核心系统之一,承担着日志采集、存储、查询、分析等重要职责。随着业务规模的扩张和日志数据量的激增,原有的架构逐渐暴露出性能瓶颈和运维复杂度高的问题。

这篇文章我打算结合最近一次日志平台的升级改造过程,聊聊我们在技术探索与实践中的具体经历。希望通过分享这次实战经验,能给正在面对类似挑战的朋友一些启发,也希望能引发更多关于“如何平衡技术先进性与工程落地性”的思考。

项目背景:为什么要做这次升级?

项目背景:为什么要做这次升级?

我们原来的日志平台基于 ELK(Elasticsearch + Logstash + Kibana)搭建,整体运行还算稳定。但随着接入的日志量持续增长(高峰期 QPS 超过 50,000),我们开始遇到几个明显的问题:

  • Elasticsearch 集群压力大:索引写入性能下降,查询响应变慢,频繁出现 GC 停顿。
  • Logstash 占用资源高:多个 Logstash 实例并行处理日志,CPU 和内存消耗严重。
  • 日志丢失风险存在:在网络抖动或下游服务异常时,部分日志会丢失,无法保证可靠性。
  • 查询性能瓶颈:用户使用 Kibana 进行聚合查询时响应时间超过预期,影响排查效率。

这些问题最终促使我们启动了日志平台的重构升级计划。

面临的挑战:不只是技术选型

在技术层面,我们需要考虑以下几个关键点:

  1. 日志采集层:是否继续使用 Logstash?还是引入更轻量级的替代方案?
  2. 消息队列层:是否需要 Kafka?还是使用 RabbitMQ 或者其他中间件?
  3. 存储引擎:Elasticsearch 是否仍是最佳选择?有没有更高效的替代方案?
  4. 高可用与灾备:如何保证整个链路的稳定性?
  5. 监控与告警体系建设:如何实现对各个组件的实时监控?

更重要的是,我们还需要权衡以下几点:

  • 现有系统的兼容性:升级不能影响已有业务。
  • 团队的技术栈匹配度:新技术的学习成本和维护成本是否可控?
  • 运维复杂度:新方案是否易于部署、监控和扩展?
  • 上线节奏:能否支持灰度发布、逐步替换?

解决思路:从架构设计到技术选型

架构分层设计

我们将新的日志平台重新划分为以下几个层次:

日志来源 -> 日志采集(Agent)-> 消息队列 -> 数据处理 -> 存储 -> 查询/分析

每一层都明确了其职责,并尽量解耦,提高可扩展性和容错能力。

关键技术选型对比

组件 备选方案A 备选方案B 最终选择
采集器 Logstash Fluentd / Filebeat Filebeat
消息队列 Kafka Pulsar Kafka
数据处理 Spark Streaming Flink Flink
存储 Elasticsearch Loki Elasticsearch
查询 Kibana Grafana + Loki DS Kibana + 自研查询接口

采集层:从 Logstash 到 Filebeat

虽然 Logstash 功能丰富,但我们发现其占用资源偏高,且插件机制有时不够灵活。于是我们转向使用 Filebeat,它轻量级、低资源消耗,且支持多种日志源配置方式。

Filebeat 的一个关键优势是 Tail-based 日志收集策略,可以自动识别新生成的日志文件,并支持多行日志合并,非常适合我们的场景。

数据传输层:Kafka vs Pulsar

我们曾一度考虑尝试 Apache Pulsar,因为它具备更强的多租户和延迟消息能力。但从运维角度出发,Pulsar 相对较新,社区活跃度虽高但文档和成熟案例略逊于 Kafka。

最终我们选择了 Kafka,因为:

  • 我们有成熟的 Kafka 运维经验;
  • 支持横向扩展且写入性能强;
  • 社区活跃,资料丰富,学习成本低;
  • 消费者生态完善,与后续处理层对接顺畅。

数据处理层:Flink 替代 Spark Streaming

Spark Streaming 是微批处理模型,延迟较高;而 Flink 的流处理是真正意义上的实时处理,而且状态管理做得更好。

我们使用 Flink 对日志进行预处理,比如字段提取、格式标准化、错误日志过滤等操作,极大提升了后续查询的效率。

存储层:Elasticsearch 仍是首选

Loki 确实是一个优秀的日志系统,在轻量级和云原生友好方面表现不错,但考虑到我们已有大量基于 ES 的查询逻辑和索引结构,迁移成本过高。

因此我们决定继续使用 Elasticsearch,同时引入了一些优化措施:

  • 使用 ILM(Index Lifecycle Management)策略控制索引生命周期;
  • 引入 hot-warm-cold 架构降低存储成本;
  • 调整分片数量以提升写入性能。

代码实践:核心模块代码片段

Filebeat 配置示例

开发工具界面-2

filebeat.inputs:
- type: log
  enabled: true
  paths:
    - /var/log/app/*.log
  fields:
    service: app
  fields_under_root: true
output.kafka:
  hosts: ["kafka-broker1:9092", "kafka-broker2:9092"]
  topic: 'logs'

Flink 日志处理逻辑片段(Java)

DataStream<String> logs = env.addSource(new KafkaSource<>(...));

logs.map(new MapFunction<String, JsonNode>() {
    @Override
    public JsonNode map(String value) throws Exception {
        // 解析 JSON 格式日志
        return objectMapper.readTree(value);
    }
})
.filter(jsonNode -> {
    // 过滤掉 error_level 为 warn 以下的日志
    return jsonNode.get("error_level").asInt() >= 2;
})
.addSink(new ElasticsearchSink<>(...));

Elasticsearch 索引模板配置

{
  "index_patterns": ["logs-*"],
  "settings": {
    "number_of_shards": 3,
    "number_of_replicas": 1
  },
  "mappings": {
    "dynamic": false,
    "properties": {
      "timestamp": { "type": "date" },
      "service": { "type": "keyword" },
      "message": { "type": "text" }
    }
  }
}

踩坑记录:那些让你崩溃的时刻

1. Kafka 吞吐上不去?

我们在初期测试时发现,Filebeat 发送到 Kafka 的吞吐始终上不去,即便调整了 batch.size、linger.ms 等参数依然不理想。

后来通过抓包发现,Kafka broker 的磁盘 IO 成为了瓶颈。我们最终通过以下几个优化解决了这个问题:

  • 增加 Kafka 的磁盘条数,做 RAID 0;
  • 启用压缩(snappy)减小网络带宽;
  • 增加副本因子,避免单节点热点。

2. Elasticsearch 写入抖动

上线初期,我们发现 Elasticsearch 的写入速度波动很大,GC 时间不稳定。

经过分析,是因为默认的 heap size 设置不合理,导致频繁 Full GC。最后我们根据官方建议,将堆内存设置为物理内存的 50%,不超过 30G,并且启用了 G1GC。

3. Flink Checkpoint 频繁失败

在使用 RocksDB 作为状态后端时,我们经常遇到 Checkpoint 超时的问题。

解决方法是:

  • 增大 checkpoint interval;
  • 将 state backend 拆分为 FsStateBackend 和 RocksDB;
  • 增加 TaskManager 内存;
  • 启用增量 Checkpoint。

4. 用户查询体验差

用户反馈说 Kibana 查询响应慢,尤其是聚合类查询。

我们一方面优化了 DSL 查询语句,另一方面引入了一个自研的查询缓存中间层,将高频查询结果缓存下来,减少 ES 的计算压力。

实施效果:改造后的成果

经过几个月的努力,我们完成了整个日志平台的升级迭代,取得了如下成果:

  • 日志采集吞吐量提升 3x,QPS 可稳定在 150,000 左右;
  • 查询平均响应时间降低 60%,用户反馈良好;
  • 资源利用率显著下降:CPU 使用率平均下降 25%,内存节省约 30%;
  • 可靠性增强:日志丢失率从原先的 0.1% 下降到几乎为零;
  • 扩展性增强:新增日志源只需简单配置,无需修改代码。

最重要的是,整个平台变得更加稳定、易维护,运维同学也轻松了不少。

经验分享:给同行的一些建议

技术原理图-1

如果你也在考虑重构或者优化你们的日志系统,我想分享几点建议:

1. 技术选型不要盲目追求“新”

很多新潮框架看起来很酷,但如果你们团队没有相关经验,或者周边生态不成熟,贸然使用可能会带来更大风险。要结合团队能力、历史包袱和长期投入来判断。

2. 分阶段、灰度推进最关键

我们这次采用了灰度升级的方式,先上线一部分日志源,再逐步覆盖全部。过程中不断调优,避免了一次性大规模切换带来的不可控风险。

3. 性能监控一定要前置

在整个链路中埋点监控非常关键,包括采集、传输、处理、落盘每个环节的指标都要采集到位,这样才能及时发现问题。

4. 留意日志格式的统一化

不同服务输出的日志格式差异大,容易造成处理困难。尽早推动规范定义,比如统一 timestamp、字段命名、结构化程度等标准。

5. 不要忽视用户体验

技术再牛,如果终端用户觉得不好用也没意义。我们这次特别重视 Kibana 的查询体验优化,甚至做了自研的查询封装层,让用户的搜索更高效。

结语:技术成长就在不断踩坑中

回想这次日志平台的升级过程,确实遇到了不少挑战,也踩了不少坑。但正是这些实际问题的解决,让我们对整个系统有了更深的理解,也积累了宝贵的经验。

技术这条路没有捷径,只有不断动手、不断试错、不断总结。希望我的分享能帮到你,也欢迎留言交流,一起探讨更多技术落地的可能性。

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝