好运设计-Profiling系统设计

文摘   2024-11-17 19:23   陕西  

史铁生有一篇散文《好运设计》,诙谐幽默的讲述了他眼中的人生道理;我们不妨尝试以此为题,来阐述下笔者眼中的在线Profiling/性能分析系统设计。

以终为始

在开始之前,我们不妨做一下这样的思考,我们设计这样的一个系统的定位是什么,目的是什么,目标用户/客户又是什么?

笔者在这里简单的将其定位成一款开箱即用的在线分布式性能优化工具平台。主要目的是协助发现性能瓶颈和进行性能优化。目标用户则是研发工程师。如果是SaaS服务,实际买单的人是老板,而买单的理由是可以提高排查效率、降低机器成本。

架构初步设计

最简单的模型中,我们需要如下的几个模块:

  • agent/sdk:接入在用户环境上,获取数据;
  • server:负责管理各种api;
  • 存储:存储各种元数据、结果数据;
  • 前端:可视化的展示各种指标、数据、图表等;
  • 分析:基于收集到的数据进行数据的分析和数据;

例如parca的架构设计:

parca

自顶向下:解决什么问题?

现在我们已经初步做完了顶层设计,我们开始向下拓展,在这个系统中,我们要解决/面对哪些问题/挑战?

笔者尝试罗列了如下几个问题/挑战:

  • 从哪收集数据?
  • 收集什么数据?
  • 数据收集要求?
  • 数据如何发挥作用?
  • 如何减少用户使用成本?

从哪收集数据

在云原生愈演愈烈的现在,上云已经成为了趋势,虽然带来了便利,但是对于Profiling也带来了一些影响;接下来我们逐个场景评估Profiling在不同环境的影响。

物理机

物理机作为最传统的部署方式,其相关的Profiling数据收集都是比较完备的,我们还可以在最新的硬件上来获取一些PMU/PEBS的数据。

虚拟机

虚拟机是在云环境中比较常见的一种形式,其一般的Profiling数据收集也是比较完备的,但是在涉及到PMU/PEBS等硬件高级特性的时候可能会遇到一些问题,在一些云厂商最新的虚拟机中已经具有了vPMU这样的特性。

容器(k8s)

涉及到容器环境就比较头疼了,在标准集群的背景下, 想通过perf_event_open或者bpf这样的系统调用来获取容器的Profiling数据是比较困难的:一方面是由于容器虽然隔离了,但是内核上没有隔离,我们往往会获取到整个内核的数据;另一方面则是出于安全考虑,诸多容器平台都不会考虑这种形式。

不过好在有serverless的出现,在这种场景下,有些云厂商的容器就是一个小的虚拟机,可以实现和虚拟机一样的效果,自然也就可以获取到相关数据。

对于云厂商而言,如果能提供开箱即用的容器Profiling数据,也许也是winback用户的一个手段。

收集什么数据

尽管我们的目标是设计一个Profiling系统,但是越多的数据也许越能帮助我们发现问题。

Profiling数据

Profiling系统的核心数据,通过该数据我们可以了解系统上正在发生什么。

PMU数据

PMU数据能够更好的帮助我们进行性能分析,但是并不是一个可选项,我们可以选择其中的部分数据来作为指导,或者提供该数据渠道。

辅助信息

辅助信息是指诸如内核版本、CPU型号等静态信息,能够帮助我们客观的了解这个机器;此外,也可以包括像容器名这样的容器信息,来帮助我们更好的做性能刻画。

APM

尽管Profiling即将或已经成为了OTEL事实上的第四个数据类型,我们在这里仍然将Profiling数据和传统APM的logmetricstracing数据做区分,而在收集数据的时候,如果我们能够有尽可能多的性能数据,就可以帮助我们更好的刻画业务负载(workload)情况。

Off-CPU

除了On-CPU,我们也可以借助Off-CPU来做性能分析,从而发现潜在的IO、网络、锁等瓶颈。

eBPF?

这里想说的是eBPF能带给我们的想象力,也许我们可以收集某个函数的使用次数、函数单独延时、网络调用延时、内存分配情况等多种新的、低开销的数据,从而帮助我们更好的分析性能问题。

数据收集要求

在这里,考虑到我们需要有一个agent在用户环境上持续不断地收集数据,我们必须考虑这个agent在收集数据上有哪些特点。

多种运行模式

在某些场景我们并不希望源源不断的收集数据,而只是希望在某些特定场景下收集数据,因此我们的agent也需要支持单次执行模式;还有一些情况我们希望能够在某些特定的时间下收集数据,这也是单次模式,只是在更上层添加一个按时触发的能力。

如果是持续Profiling的模式,我们只需要将数据源源不断的推送到某个具体的server即可(push);但是如果涉及到按需的单次执行模式,我们就需要考虑如何让agent能够获取到这样一个启动的信号,因此我们可以考虑采取pull模式,每次由agent主动去server端拉取任务。当然,这两也可以放到一个请求中,请求参数是采集的Profiling数据,而返回参数是单次的任务参数。

低开销

作为一个持续运行的agent,我们不能占据过多的cpu、内存、网络等资源,否则将会影响用户的业务正常运行。因此,我们需要尽可能的减少agent带来的性能损耗,为了解决这个问题,业界有诸多开源项目通过eBPF来实现。

无侵入

作为一个开箱即用的产品,我们应当尽可能的减少给用户带来的改动,尽可能的减少侵入性,让用户无需修改代码就可以快速的接入,减少用户的使用成本。针对这一点,eBPF也是一个非常好的选择。

支持多语言

用户的业务负载多种多样,语言上就可能会有GolangJavac++php等多种不同的语言,因此,我们的agent应当尽可能的支持all on one能力,一个agent即可处理多种语言。退而求其次,我们可以维护多个语言sdk/agent,让用户基于实际情况进行选择。

同时,在服务端,我们也应当留出接口让用户上传使用其他的工具获取到的性能分析工具。

正确栈回溯

在实际的生产环境中,我们往往会遇到栈回溯不准确的情况,这通常是由于fp(frame pointer)指针在编译过程中被丢弃导致的。另外,也有一种情况是由于函数调用过程中PCS不一致导致的无法解析。针对前一种情况,我们应该尽可能的使用dwarf进行解析,或者在编译时通过编译选项显式保留fp指针,这会导致一定的性能损失;针对后一种情况,我们需要让我们的agent能够支持多种函数调用过程约定。

符号表处理

在完成栈回溯以后,我们需要将地址映射到具体的函数,从而帮助我们了解到是哪个函数导致的。这一转换需要符号表的支持,在实际的生产环境中,有诸多可执行程序会进行strip等操作去掉符号表,这会导致进程出现比较多的unknown情况。针对这一问题,业界诸多项目都采取了服务端存储符号表的形式,由用户上传对应的符号表,在服务端通过程序将地址和函数名进行关联;更进一步的,可以将流水线和性能分析系统结合,每次出包的过程中降符号表推送到性能分析系统,从而实现自动解析。

易存储

在单机时代,我们通常使用perf等工具来进行数据的收集、分析,考虑到数据存储的因素,perf也提供了诸如perf archive等功能来帮助打包信息,但是其数据仍然是文本的非结构化数据或者说是二进制的不完整信息,无法进行结构化处理或者时序上的关联,存储形式更多的是文本存储;考虑到后续我们会经常性的使用到这些数据,并且不会经常性的改动这些数据,在agent侧,需要将数据尽可能的转换成通用的标准数据结构,如OTEL最近的Profiling数据格式;在服务端存储,我们倾向于通过时序数据库或者列式存储等方式来进行数据的数据。

数据如何发挥作用

性能数据可视化

在诸多的开源项目中,都提供了优秀美观的前端可视化来减少工程师分析数据的工作量。这里存在两大挑战,一个是如何将数据分析准确、易懂的进行展示和渲染;第二个是在面对大量数据的时候,如何高性能的将数据渲染出来。

对比

在实际生产过程中,我们时常会遇到发版本前后性能回退、服务异常(内存泄漏、CPU使用率异常)等情况,在这些情况下,提供两个版本的前后数据进行定量的分析可以帮助我们发现差异点,从而结合改动情况来进行针对性的性能优化。

此外,结合对比情况的每日推送,也可以帮助我们发现潜在的问题。

聚合

在实际生产过程中,我们面对的可能是一个巨大的集群,而不是一个单机的性能分析。考虑到这一点,通过将整个集群的基础信息如CPU核数、Profiling数据等进行加权聚合,从而得到整个集群的Profiling数据,结合调用关系等其他可观测数据,也许能够帮助我们更好的进行性能分析。

成本可视化

结合前面提到的聚合功能,通过结合云服务器成本等数据,我们可以实时的感知、监控成本的变化,借助业务层面的性能优化来尽可能的减少机器成本,降本增效。

实时分析

在实际的问题解决中,我们可能会经常性的遇到对比、下钻、聚合等功能,这些功能要求我们支持比较实时的性能分析,最好能够有一个规则引擎持续性的进行分析和数据渲染。

数据导出(PGO等)

Profiling数据除了可以作为性能分析的指导,也可以成为PGO这样的反馈优化的数据源。例如,我们可以持续性的收集pprof的数据并且将这些数据和GolangPGO优化结合到一起(参考auto-FDO思路),尽可能的释放编译器的性能潜力。这在一些开源项目中已经落地。

智能运维

作为一个本质上还是可观测系统的平台,我们的系统除了尽可能的提供客观的性能数据,也可以适当的结合工程师的经验、分析引擎、AI知识等能力,给用户提供一些分析建议,更好的帮助用户解决问题;作为进一步延伸的,将系统数据融入到整个CiCd中可能更有业务价值,真正的在整个流程中做到反馈优化。

如何减少用户使用成本?

文档与workshop

当用户面对一个全新的产品的时候,如何更好的指导用户使用?

文档是首先需要的,简单、清晰、易懂、有实时性的文档能够给用户提供较多的帮助,同时减少服务方的运营成本。

为了能够更好的帮助用户熟悉平台并进行性能分析,我们可以提供诸多的workshop,例如perf-ninja,可以让用户快速的构建出一个模拟的有问题的环境,并通过工具去解决问题,一方面能够让用户学习到性能分析的知识,另一方面也可以让用户更好的熟悉平台。

AI

作为解决最后一公里逃不开的方向,我们也不妨尝试将AI引入到系统中,提供客观+主观结合的信息。

总结

本文尝试基于一些已有的实践文章和一些业务实践,草率的勾勒了一下笔者理想中的Profiling系统的模样。在每个问题上,仍然有诸多的细节问题没有解决;笔者将会逐渐的对文章进行完善和修补。

由于笔者能力、眼界有限,难免有问题和理解上的失误,欢迎各位读者不吝指教。

参考资料

  • 快速定位线上性能问题:Profiling 在微服务应用下的落地实践架构( https://www.infoq.cn/article/eqAzVi015lokJE9EjmLk)
  • 字节跳动算力监控系统的落地与实践
  • otel-profiling-agent(https://github.com/elastic/otel-profiling-agent)(https://github.com/elastic/otel-profiling-agent)(https://github.com/elastic/otel-profiling-agent)
  • 探索可观测的新视角—— eBPF 在小红书的实践
  • pyroscope(https://github.com/grafana/pyroscope)
  • parca(https://www.parca.dev/docs/overview/)
  • vPMU(https://docs.redhat.com/zh_hans/documentation/red_hat_enterprise_linux/7/html/virtualization_tuning_and_optimization_guide/sect-virtualization_tuning_optimization_guide-monitoring_tools-vpmu)
  • AAPCS(https://blog.csdn.net/FJDJFKDJFKDJFKD/article/details/102967031)
  • auto-FDO(https://research.google/pubs/autofdo-automatic-feedback-directed-optimization-for-warehouse-scale-applications/)


Linux内核之旅
Linux内核之旅
 最新文章