查看原文
其他

每秒百万数据点 Go 应用监控系统演进

Alan Zhang AfterShip 2024-01-27
本文共计 4,335 字,阅读需 6 分钟

AfterShip 是一家服务国际电商赛道的 B2B SaaS 公司,自 2012 年成立,近几年业务持续高速增长,目前公司的 Go 应用监控系统每秒已超过百万数据点,其系统如何从 0 到 1 的演进过程,对大量公司都有参考意义。
在近日,AfterShip 与 GoCN 联合举办的 GopherDay 技术交流会上,AfterShip 高级 SRE 工程师 Alan Zhang 进行了《每秒百万数据点 Go 应用监控系统演进》的主题分享。
以下是根据现场演讲所编辑的技术文章,希望对大家有所帮助。

1. AfterShip 监控架构概览
在当前云原生时代,可观测技术建设可以帮助我们跟踪,了解,诊断业务应用的问题,所以我们的监控系统建设也是基于可观测技术去建设的,下图便是 AfterShip 的监控系统架构。
首先我们来看一下 Metrics 系统,由于 Metrics 系统是最重要的基石,它不仅为业务监控和系统监控提供基础数据,还是构建告警系统的核心,所以这对 Metrics 体系的稳定、高性能提出了更多的要求。
我们的 Metrics 系统主要是基于 Prometheus 来实现的,由于业务,指标爆发式的增长,面临了很多问题,所以 2023 年我们对 Metrics 系统进行了架构升级,指标查询速度,稳定性上得到了大幅性能提升,同时还降低了资源成本和运维成本,我会在后续的部分做详细的分享。
由于我们的业务服务是分布式的微服务架构, Traces 系统可以帮助我们了解远程方法调用的执行过程和耗时,对于排查问题和服务性能提供了很大的帮助。
我们主要是通过使用 NewRelic 来帮助我们实现链路的跟踪。New Relic 是美国的一家软件服务供应商的产品,它是一个全栈可观测平台,提供了基础设施监控,应用性能监控,链路跟踪等能力。
而对于可观测三大支柱之一的日志,我们的日志系统主要是使用 Google Cloud Platform 的产品 Cloud Logging。他提供实时的 EB 级的存储、搜索、分析、告警等服务,他的日志路由功能可以很方便地过滤,排除我们不需要的日志。这些能力很好的满足了我们的需求。
可观测三大支柱 Metrics,Traces,Logs 很好的帮助研发同学排查问题,但是研发同学有时还需要深入应用程序本身,找到性能瓶颈点。
那么三大支柱就不能提供更多的细节,所以这个时候他们就需要一种更有效的办法 —— Profiling,当然仅仅有 Profiling 还是不够的,可持续的 Profiling 才能更好的使用于现在的应用场景中。
我们在 2023 年引入了 Grafana Pyroscope 来提供 Continuous Profiling 能力,它可以为我们的 Go 应用提供火焰图和根据时间线对比应用性能,内存使用情况的能力。
监控告警部分我们主要有 3 大告警来源,Google Cloud Platform ,Grafana Alerting,NewRelic。都是通过 Pagerduty 来管理发送通道,按照级别发送到需要的通道中。
以上便是支撑我们整个监控系统的工具。

2. 如何监控 Go 应用?
下面我们一起来看看,在 AfterShip 我们是如何监控一个 Go 应用的。
下图便是我们的指标接入的流程:
首先我们一般会确认相关的监控指标,通常有以下 3 大类:
Go 运行时指标(必备)
  • Goroutine 数量

  • GC Duration

  • Panic

应用层指标(必备)
  • infra_http_request_total

  • infra_http_client_dns_latency_bucket

  • infra_pubsubx_message_latencies_bucket

业务指标(Option)
  • 总 Tracking 查询量

  • Tracking 建速率

  • 某个 ENT 客户的 Tracking 查询失败率

上述 3 大类指标,其中运行时和应用层指标在我们的 Go 应用基础框架中就默认集成,业务指标需要开发同学根据需求做开发埋点,在经历应用部署,CI/CD 环节自动配置服务发现的配置。
服务发现我们主要是使用 ServiceMonitor 来实现的。
整个流程主要分为 3 步:
第一步,通过 Labels 匹配对应的 Prometheus 集群。
第二步,ServiceMonitor 通过 selector 来匹配应用的 Service 的 labels 来确认是哪个应用。
第三步,Prometheus-Operator 管理对应的 Prometheus 生成抓取监控指标的 Job。
在 Prometheus 执行抓取 Job 之后,指标就存储在指标系统中了,最后研发同学就可以通过 Grafana 查看具体的指标。
以上便是我们如何实现 go 应用指标接入到指标系统中的。

3. Metrics 系统架构演进
这个时候指标就已经存储在指标系统中,接下来我们使用 Metrics。那么指标系统能否提供高性能,稳定,低成本的服务就成了关键。
下面我们就一起来看一下在指标数量不断增长情况下,我们的 Metrics 系统是如何演进的。
我们把演进主要分为 3 个时间段:
第一个时间段是 2018-2020 年,在这个时间段,我们刚把业务部署在 Kubernetes 上,那时候我们的服务数量比较少 ,只存储了一些简单的容器监控指标,业务指标非常的少,所以整体的写入量峰值大约是 40k datapoint/s。
当时我们的 Metrics 系统架构如下图:
架构非常的简单,我们当时按业务分了多个 Kubernetes 集群,在每个集群使用 Prometheus-Operator 来管理一套单副本的 Prometheus 集群,无论是 infra 的指标,还是业务指标都存在同一个 Prometheus 集群。我们会将多个 Prometheus 接入到 Grafana 中,方便研发同学主要使用 Grafana 来查询指标。
随着业务的发展,无论是 Infra 指标还是业务指标都大幅增加,从 2020 年底开始我们开始面临以下几个问题:
  • 无法查询超过 30 天的数据

  • 查询慢,平均时间超过 2 分钟

  • 跨集群指标无法聚合

  • Prometheus 集群经常崩溃

  • 维护时 Prometheus 会丢数据

  • 成本高,需要大容量 SSD 磁盘

面对这些问题以及可以预见的业务增长需求,我们从 2020 年底开始就着手调研解决上述问题,于是我们就进入了第二个阶段:2021-2022 年。经过分析我们当时主要有以下几个核心的需求:
  • 兼容 Prometheus

  • 长期存储

  • 可跨集群查询

  • 拓展性强

  • 无入侵性

我们发现可选的方案其实并不多。只有 Cortex 、M3、Thanos 这 3 个方案,他们总体上都可以满足我们的需求,Cortex 架构是参考 Thanos 设计的,而 M3 部署难度较大且文档很少,具体的使用案例也非常少。
综合考虑社区活跃度,项目当前状态,生产案例等信息后,最后决定采用 Thanos。下面是我们当时接入 Thanos 后的架构:
如图,Thanos 的核心组件主要有 query-frontend,querier,store gateway 和对象存储。其中 query-frontend 主要是将大查询拆分成多个小查询以提供查询性能,而 querier 主要是负责短期,长期数据查询组件以及执行具体的查询。其中 Prometheus 提供短期数据查询,通常 Prometheus 只存储 6 小时数据,而 sidecar 每隔 2 小时将最近 2 小时的数据写入到对象存储中一直保存,作为长期数据。而 store gateway 就是负责提供 6 小时以上的长期数据查询的服务。
这样架构的好处是可以从多个 Prometheus 集群查询数据,统一了查询入口,提高了用户的体验。同时提供长期数据,另外 Thanos 可以通过 Prometheus-Operator 来管理,所以大大降低了整体管理成本和入侵性。
除了引入 Thanos,我们为主要的 Prometheus 集群多增加了 1 个副本,从而解决我们在做集群维护时监控数据中断的问题。当然 Thanos 也可以很好地帮我们解决 2 个副本数据重复的问题。
在我们引入 Thanos 系统后一年多的时间里,2022 年我们的产品线,业务服务都出现了爆发式的增长,业务指标数量大幅增加。
对于指标系统来说 datapoint 的写入量也暴增到 600k/s。对于 Thanos 的系统来说压力在持续不断增加,我们在 2022 年中又对指标系统做了一番优化从而希望可以满足我们的需求。具体的架构图如下:
我们主要做了 3 个方面的优化:
  1. 升级了 Thanos 的版本,为 query-frontend 和 storegateway 服务增加了 Redis 缓存,从而提升查询的性能。

  2. 我们为 store gateway 做了基于时间的分片。比如最近 30 天的数据使用一个独立的 store gateway,30-90 天前的数据使用另外一个独立的 store gateway,90 天前的使用一个独立的 store gateway,从而提升长期数据的查询性能。

  3. 我们结合 Prometheus 的压力情况,根据业务线等纬度拆了多套 Prometheus 集群。因为 Thanos 的每一个查询需要他接入的每一个 Prometheus 都返回,因此 Thanos 的查询性能取决于最慢的 Prometheus 集群或者 store gateway。所以我们这么拆分的主要目的是提高 Prometheus 返回查询结果的性能,最终实现提高 Thanos 查询返回的速度。

但在 2022 年年底的时候,我们的系统依然会面临以下几个问题:
  • 超 100+ 倍数据点增长导致查询缓慢

  • 架构复杂,参数调优困难

  • 频繁 OOM

  • 集群规模受制于 Prometheus

  • 集群成本上升

因此,我们从 2022 年底开始调研行业的其他解决方案,综合对比了多种开源方案,同时我们也与其他公司做了交流。
我们主要对比了 Grafana Mimir,Cortex,M3,VictoriaMetrics,由于 Grafana Mimir 相当于是 Cortex 的企业级版本且 Cortex 的架构设计借鉴了很多 Thanos 的思路。所以我们首先排除了 Cortex。而 M3 经过多年发展,社区活跃度依然不是很好,所以我们也排除了 M3。
最终我们决定在 Grafana Mimir 和 VictoriaMetrics 中做出选择,我们首先对他们做了一轮压测测试,最终结果 VictoriaMetrics CPU 使用率更平稳且比 Grafana Mimir 低 1.7 倍,内存使用率更平稳且低 5 倍,存储空间减少 3 倍,同时我们发现国内有很多中大厂也在使用 VictoriaMetrics,同时反馈收益也非常的高。
所以 VictoriaMetrics 似乎可以满足我们未来相当长一段时间对于 Metrics 系统的需求,但是否合适还是要经过验证才知道。于是我们 2023 年年初开始调研,4 月份开始测试环境部署,10 月份上线生产环境部署,经过数月的测试,验证,我们最终在 12 月初完成了全部告警,看板数据源的切换,逐步下线了 Thanos。
下面我们来看一下当前的最新架构:
我们总体上是将 Thanos 替换了,其他部分总体上没有任何的变化。如图我们可以看到 VictoriaMetrics 只有 3 个组件,vmselect,vminsert 和 vmstorage。顾名思义 vmselect 主要是提供指标查询服务,vminsert 主要是负责指标数据插入的服务,而 vmstorage 主要是负责指标数据存储。所以其架构非常的简单,同时又非常好地满足了我们的需求。
我们的主要收益如下:
  • 高性能,看板加载时间从 120s 降低到 10s

  • 兼容 Prometheus,可以无缝迁移

  • 成本更低,只需要 Thanos 的 50% 资源

  • 扩展性强,所有组件支持水平扩容

那么此时我们的业务经过 2023 年的发展,我们的业务指标数量超过 2.5 万 ,datapoint 的写入量也增到 1Mil/s。

4. Why VictoriaMetrics So Good?

那么相信大家都很好奇 VictoriaMetircs 为什么这么牛?这些非常好的特点他是如何做到的呢?我们从他们的代码中是可以窥探到一些的,比如:
  • 根据容器可用的 CPU 数量计算协程数量

  • 区分 IO 协程和计算协程,同时提供了协程优先级策略

  • 使用 ZSTD 压缩传输内容降低磁盘性能要求

  • 根据可用物理内存限制对象的总量,避免 OOM

  • 区分 fast path 和 slow path,优化 fast path 避免 GC 压力过大

而对于资源需求低,他又是怎么做到的呢?主要是对时序数据压缩做了优化,大幅提升了压缩的效率,从而最终降低内存,磁盘带宽,网络带宽。我们都知道几乎所有的时序数据库压缩算法都是采用 Facebook 开源的 Gorilla 压缩算法,比如 Prometheus,Thanos,Timescale,Victoriametrics 等等。我们知道时序数据主要由两部分组成,时间戳和浮点数值组成。那么 Gorilla 算法主要是针对这 2 部分做压缩,具体的步骤如图:
由于过程还是比较复杂的,这里就不展开讲,各位可以查看 Gorilla 的论文。Prometheus 等主要是采用原生的 Gorilla 算法,而 Victoriametrics 对 Gorilla 算法进行了改进。主要从以下几个方面进行了改进:
  • 改进 XOR,通过应用 10^X 乘数将 value 浮点值转换为整数值

  • 根据具体情况选择压缩算法

    • 数值相同,那么只存储第一个值

    • 数值是等差数列,那么只存存储第一个值和 Delta 值

    • Gauges 类型的 value 先用一阶增量编码( Delta )压缩,然后再用 zigzag 算法压缩

    • Counters 类型的 value 先用二阶增量编码( Delta of Delta )压缩,然后再用 zigzag 算法压缩

  • 最后再应用 ZSTD 算法进行二次压缩

那么经过改进后的压缩算法,实际压缩效果如下图:
很明显 VictoriaMetrics 的压缩效率更高,我们的生产集群中每个 Sample 大小仅为 Prometheus,Thanos 的一半左右 0.7 Byte。那么对应的存储资源,网络带宽,磁盘性能需求都要低很多。
以上便是我们总结的 why Victoriametrics 可以满足我们的需求。
到此时相信大家有一个疑问,我们都知道没有一个系统是完美的,适用于任何场景,那就是 Victoriametrics 就没有什么不足吗?
下面我们就来看一下 VictoriaMetrics 一些不能忽视的问题:
  • 由于其完全的性能取向,数据完整性校验缺失

  • 可能会丢数据

    • 没有 WAL(Write-Ahead Log)

  • 扩容/维护时可能容易崩溃

    • vmstorage 没有服务自动发现

  • 兼容性需要关注

    • 与 Prometheus 一些设计思路有差异


5. 总结和展望

首先我们来总结一下 2023 年我们引入 VictoriaMetrics 系统后,为我们带来的关键成果:
  • 查询性能大幅提升,用户体验好

  • 稳定性大幅提升,OOM 率大幅下降

  • 资源成本得到降低,至少降低 30% 的成本

而对于后续为了能满足更多的需求,我们需要持续不断优化 metrics 指标系统的建设。
VictoriaMetrics 高性能,良好的兼容性,高稳定性,低资源需求这些优良的特性很好的支持我们未来的  metrics 指标系统建设。我们计划在 2024 年继续在以下几个方面做建设:
  • 成本优化

    • 使用 vmagent 替换 Prometheus

    • 根据实际需求调整指标存储周期

  • 性能优化

    • 优化高基数指标

最后,我们总结了一些经验供各位借鉴:
  • 不同阶段选型侧重点不同

  • 兼容 Prometheus 是首要关注点随着业务增长,性能和成本需要重点关注

  • 不要相信互联网上的报告

    • 你可以并行运行多个方案,然后再决定

当然,如果你也想在一家工程师氛围浓厚的国际 SaaS 公司工作,那么欢迎你点击“阅读原文”,加入我们。
继续滑动看下一个

每秒百万数据点 Go 应用监控系统演进

Alan Zhang AfterShip
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存