技术探索从来不是一条直线,而是一条不断修正方向的路径

后端便利贴
2025-06-20 04:33
阅读 209

引言:技术选型背后的故事

引言:技术选型背后的故事

我是一名从事后端系统架构设计多年的技术老兵。从业这么多年,最深的感受就是——技术本身并不是最难的部分,难的是如何在复杂、快速变化的业务场景中,找到一个既不过度设计又能支撑未来发展的平衡点

这篇文章我想结合一个我们团队去年经历的实际项目案例来讲讲“深入理解技术探索与实践”的体会。这个项目不算大,但过程跌宕起伏,在技术选型、落地执行过程中踩了不少坑,也收获了很多经验。

希望这些经历能给你带来一些启发和参考价值。


项目背景:从0到1搭建企业级日志平台

项目背景:从0到1搭建企业级日志平台

我们服务的是一个中型互联网公司,内部有多个业务线,数据源繁杂,涉及Web、APP、IoT、第三方系统的日志收集和分析需求日益增长。原有的日志方案是基于ELK(Elasticsearch + Logstash + Kibana)的一套简单结构,仅用于日常排查问题,已经明显无法满足:

  • 日志量快速增长带来的查询响应延迟
  • 多租户支持缺失,不同业务的日志没有隔离机制
  • 原始ELK方案缺乏自动化运维能力,升级扩容困难
  • 没有统一的日志生命周期管理策略
  • 缺乏可视化告警和集成看板能力

老板一声令下,我们开始从头规划一套全新的企业级日志平台,要求半年内上线,并且目标是为将来10倍增长做准备。


遇到的挑战:不是每个方案都“看起来好用”

遇到的挑战:不是每个方案都“看起来好用”

我们的目标很明确:建设一个高可用、可扩展、易运维、低成本的企业日志平台。这听起来像是个老生常谈的话题,但真动手的时候才发现现实有多骨感。

第一阶段尝试(失败)

初期我们延续了ELK的老思路,采用Logstash+Filebeat+Elasticsearch+Grafana的组合进行构建。但很快暴露出了几个关键问题:

  1. Logstash资源消耗太高,性能瓶颈明显
    • 单台服务器每秒只能处理5万~8万个事件(Event),CPU基本被打满。
  2. Elasticsearch写入压力大,频繁Full GC
  3. Filebeat在多节点部署时配置复杂,缺乏集中管理

更头疼的是,当时我们还没有成熟的运维平台,整套系统需要手动监控和巡检,故障恢复效率极低。

这时候我们就意识到,如果继续用ELK原始架构,根本扛不住未来的规模。


解决方案:技术选型的权衡与思考

在经过一次内部会议讨论之后,我们决定对技术栈进行重构。这次我们不再“盲目跟风”,而是回归本质,拆解了以下几点:

关键指标 目标
收集层稳定性 需要轻量化、低资源占用
数据清洗灵活性 支持规则配置化、多语言适配
存储扩展性 易于水平扩展、支持冷热分离
查询性能 降低高频查询的延迟
成本控制 尽量利用开源生态,减少商业组件依赖

带着这些诉求,我们做了几轮选型评估对比:

组件类型 可选项 我们的选择
收集器 Filebeat, Fluent Bit, Loki Fluent Bit + 自研采集Agent
清洗/转换 Logstash, Vector, Fluentd Vector
存储引擎 Elasticsearch, OpenSearch, ClickHouse ClickHouse + Elasticsearch
查询展示 Grafana, Superset, Redash Grafana + 自定义看板
分布式协调 ZooKeeper, ETCD, Consul ETCD(与现有环境兼容)

这套新架构最终帮助我们在性能、成本和运维方面取得了更好的平衡。


架构演进:新旧方案对比

旧版ELK架构图(简化)

Filebeat → Logstash → Elasticsearch → Kibana

优点:成熟、社区活跃
缺点:性能瓶颈显著,运维复杂度高

新版架构图(简化)

Agent/Fluent Bit → Vector → ClickHouse/Elasticsearch → Grafana

新版本架构的特点在于:

  • 使用 Vector 替代Logstash,轻量、高效、内存安全;
  • 使用 ClickHouse 替代部分Elasticsearch的存储和查询压力(特别是统计类日志场景);
  • 对接Grafana实现灵活仪表盘展示;
  • Agent自研,适配容器、宿主机等混合部署场景;
  • 结合ETCD做元数据管理、服务发现等基础设施支持。

代码实践:几个核心模块的关键实现片段

1. Vector的数据管道配置示例(toml格式)

[source.stdin]
type = "stdin"

[transform.rename_fields]
type = "remap"
inputs = ["stdin"]
source = '''
  .log_level = string!(.level)
  del(.level)
'''

[sink.ch_log]
type = "clickhouse"
inputs = ["rename_fields"]
endpoint = "http://ch-node1:8123"
database = "logs"
table = "app_logs"

这段配置实现了从标准输入读取日志,重命名字段后写入ClickHouse数据库的功能。实际应用中我们会根据不同的业务日志类型编写多个Pipeline。

2. 自研Agent启动脚本逻辑(Python伪代码)

class LogCollector:
    def __init__(self):
        self.conf = self.load_config()
        self.sources = []

    def load_sources(self):
        # 根据本地或远程配置加载日志采集源(文件、socket、journal等)
        for src in self.conf['sources']:
            if src.type == 'file':
                self.sources.append(FileSource(src.path))
            elif src.type == 'docker':
                self.sources.append(ContainerSource())

    def run(self):
        while True:
            for source in self.sources:
                log_events = source.collect()
                forward_to_vector(log_events)  # 通过TCP转发给Vector实例
            time.sleep(1)

if __name__ == "__main__":
    collector = LogCollector()
    collector.run()

这段代码展示了我们采集端的基本运行逻辑,它会自动识别多种日志源并推送到Vector节点上进行后续处理。

3. Grafana数据源配置(使用ClickHouse插件)

在Grafana中添加ClickHouse插件后,可以非常方便地通过SQL直接绘图。

SELECT
    toStartOfHour(timestamp) AS hour,
    count(*) AS total_logs
FROM app_logs
WHERE log_level = 'error'
GROUP BY hour
ORDER BY hour

这样就可以轻松生成按小时划分的错误日志数量曲线图。


踩坑经验:从实践中汲取教训

虽然整体架构跑起来了,但在推进过程中我们也踩了一些典型的坑,值得记录一下:

坑1:低估了ClickHouse的Schema变更代价

ClickHouse的列式结构在大数据量下查询性能优越,但它不支持原生的在线Alter Schema操作。

我们初期为了测试方便,直接在表里加了一个user_id字段,结果线上表几十亿条数据,导致ALTER TABLE ADD COLUMN几乎卡死了整个集群,甚至影响了其他查询任务。

教训总结:

  • 在ClickHouse中做Schema变更前,一定要评估表数据量和变更耗时
  • 长期来看建议引入Iceberg或者Delta Lake这类可变schema结构

坑2:Vector并发模型配置不当引发丢包

Vector默认是以单线程方式运行的,但我们初期没注意这一点,导致在高流量场景下出现丢包。

解决方式:

  • 启用了multi-threaded模式:
[global]
max_cpu_cores = 4
  • 同时优化了网络传输buffer大小

坑3:误删索引导致Elasticsearch重建耗时长

由于一开始对Elasticsearch的索引生命周期不够熟悉,曾误删过一个生产索引,导致第二天早上被报警吵醒——大量日志丢失。

解决方案:

  • 加强权限管控,限制生产环境DELETE操作
  • 建立每日快照策略
  • 设置索引锁定策略(Index Read-Only Lock)

实施效果:不仅仅是性能提升

在新方案上线半年后,我们做了全面复盘,主要成果如下:

指标 上线前 上线后 提升幅度
写入吞吐 8w EPS 50w EPS 6.25倍
查询延迟(P99) >5s <300ms 减少94%
系统维护时间 每周约3小时 每月<1小时 大幅下降
日志保留周期 7天 90天(热数据) + 360天(冷归档) 提升5倍以上
整体运维成本 中等 节省30%以上

更重要的是,随着系统的稳定运行,我们开始接入更多业务部门的需求:

  • 金融风控部用来分析用户行为日志
  • 运维团队建立了完整的异常检测体系
  • 支撑了BI部门的实时报表系统

整个系统成为了公司基础设施的一部分,真正体现了“平台”的价值。


经验分享:关于技术探索的几点建议

如果你也在面对类似的日志平台搭建或其他技术难题,这里是我总结的一些实战建议:

1. 别盲从流行架构,先问自己“真实需要什么”

我见过很多团队上来就选Kubernetes+Istio+Envoy的全栈微服务架构,结果连CI/CD流程都没跑通。技术和架构应该服务于业务,而不是相反

2. 技术选型是一个权衡的过程,没有银弹

每种技术都有其适用边界,比如:

  • ELK适合全文检索场景,不适合大规模统计
  • ClickHouse适合聚合分析,不适合文档搜索
  • Vector适合轻量级管道处理,但不适合复杂的多阶段计算

了解你所选技术的“擅长领域”,才能发挥出最大效益。

3. 不要忽视团队的能力和知识储备

再牛的架构,如果没有人能维护也是灾难。比如我们在后期考虑引入Apache Iceberg的时候就停了下来——因为团队还没完全掌握Spark的调优技巧。

合适比先进更重要。

4. 做好长期演进的设计,避免过度重构

一个优秀的系统往往是在迭代中慢慢打磨出来的。不要一开始就想搞个“全能平台”,而是从解决当前痛点出发,逐步扩展。

我们在建设日志平台的时候也是这样,第一步先解决了稳定性和容量问题,第二步才引入多租户、告警等功能。

让技术随着业务一起成长,才是最好的节奏。


写在最后:技术探索,本质上是认知的进化

回顾整个项目的历程,其实并不都是顺利的。中间有很多深夜加班、也有争执和怀疑,甚至一度想放弃换回旧架构。

但回头来看,正是那些困难让我们一步步走到了今天,也让团队在技术认知、架构能力和协作方式上完成了一次质的飞跃

我也越来越相信一句话:“优秀的架构是磨出来的,不是画出来的。

希望通过这篇来自实战经验的分享,能给你一点启发。也希望你在自己的技术探索之路上,少走弯路,多些成就感。

愿你我都能在技术这条路上,走得坚定又从容。


📌 如果你觉得这篇文章对你有帮助,欢迎点赞收藏;若有问题或观点想交流,也可以留言告诉我。

评论 0

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