微拍堂基于 DeepFlow 建设零侵扰的可观测平台 精华
本文整理自微拍堂高级运维工程师涂永春在「DeepFlow 可观测性 Meetup 杭州站 - 基于 eBPF 的可观测性实践」中的分享实录。回看链接[1],PPT 下载[2]。
微拍堂电商平台面临成本与性能优化瓶颈、问题定位困难以及业务流梳理困难等挑战,公司运维团队决定构建对业务零侵扰的可观测性平台。评估众多开源解决方案后,选择了基于 eBPF 的 DeepFlow 开源项目作为数据底座,在此基础上针对公司业务需求进行二次开发,实现了完整的用户界面。可观测性平台在试运行过程中得到了研发团队及 SRE 团队的充分认可,开始推进全面上线基于 DeepFlow 二开的零侵扰可观测性平台。
01、平台建设背景
微拍堂隶属于杭州微拍堂文化创意有限公司,2014年上线,是国内领先的文玩艺术品电商平台,公司总部位于中国杭州。微拍堂开创了文玩艺术品直播竞拍全新商业模式,实现了文玩竞拍行业线上化。随着逐年积累的成功和业务增长,微拍堂在行业中牢固树立了领导地位。
随着业务规模的扩大,公司对精细化的 IT 架构运营提出了更高要求,期望实现成本和性能的极致优化、故障的快速定位、并解开业务流程的"黑盒"之谜。实现这些目标面临的主要挑战包括:
01-建设背景
- 成本和性能优化困难:尽管通过基础设施的指标监控数据已经实现了服务器、Kubernetes Node、Pod 等资源的用量监控,但这不足以驱动成本和性能的优化。我们希望进一步细化采集服务粒度的资源消耗、服务间调用合理性分析等与业务成本和性能相关的数据。现有的数据无法满足要求,必须借助应用可观测性来完成。
- 问题定位困难:继续迅速而准确地定位故障、界定责任范围的问题排查能力,解决诸如"服务 A 发起请求但服务 B 未响应"、“客户端的时延大但服务端的时延小”等推诿问题,因此迫切需要全栈可观测性能力的支持。
- 业务流梳理困难:由于服务拆分细致,即使资深开发人员可能也只对自己参与的特定环节了解深入,新员工加入后了解和熟悉整个业务流程则更加困难。同时,文档的不完整和更新的不及时等现实情况使得业务变得越加“黑盒”,业务管理也越来越难,需要对业务零侵扰的工具来自动化的梳理业务,降低人力成本。
基于这些需求和挑战,我们开始着手进行产品的选择与评估。
02、开源产品选型
在项目开端,微拍堂采用了以开源产品为基础构建可观测性平台的策略,主要是为了降低人力成本并确保平台功能可跟随开源社区的迭代持续创新和升级。
最开始我们考虑的是基于现在市面上活跃的 APM 开源项目来构建可观测性平台,其中先后引入过 PinPoint、SkyWalking 两个项目,但是在最终落地过程都非常困难,主要因为微拍堂业务语言栈太多(PHP,Java,Golang,Python等),需要引入不同语言的 SDK 来埋点,需要业务代码改造,实现起来比较困难,APM 项目推进了将近半年并未达到预期效果。
后来我们关注到 eBPF 可以做无需业务修改代码的可观测性,并了解到 DeepFlow 已经有不少落地,Demo 验证并与社区多次交流后,就开始正式引入 DeepFlow 来做可观测性平台,下面是我们在实际落地中非常看中的点:
02-产品选型
- 技术栈:DeepFlow 使用cBPF/eBPF实现了自动化的 AutoMetrics/AutoTracing 机制,既能以业务零侵扰的形式自动化采集到应用的RED 性能指标,又能以语言无差异的低插码实现全链路追踪。
- 代码开源:DeepFlow 是一个基于 Apache License 的开源项目,有利于我们后续的定制化开发。
- 系统性能:deepflow-agent 采用了 Rust 语言开发,采集性能好且对业务影响可忽略不计,存储采用的 ClickHouse,在同等可观测性数据量的情况下,性能是时序数据库的 10 倍。
- 技术支持:项目近一年,持续活跃,稳定迭代,社区给的技术支持非常到位。例如我们所需的FastCGI协议在几个小时就开发完成。
03、平台二开成果
DeepFlow 社区版仅支持基于 Grafana 构建 Dashboard,对于业务人员来说操作不便,而且与我们内部的整个运维平台也是割裂开的,因此我们考虑基于 DeepFlow 的提供的 SQL API 二开了 UI 界面,接下来展示下我们二开的成果。
应用总览视图:可以清晰的知道目前系统有哪些服务、每个服务的健康状况、客户端或服务端异常比例、还可以选择个人关注的重点服务。
03-应用总览视图
接口统计:用于展示某个服务的所有接口调用次数,通过曲线图的形式表达,可以分析接口的历史变化,快速查找接口调用突变等问题。
04-接口统计
应用调用日志:用于查看某个服务的调用详情,包含客户端、服务端、域名、接口、状态、耗时等等、也可进一步通过拓扑的形式展示这个服务的调用关系,及下钻分析完整的调用链路。
05-应用调用日志
全景拓扑图:一目了然查看服务的调用关系,比如客户端、后端的 MySQL/Redis 服务、也可以展示每个服务的 RED 指标量
06-全景图拓扑图
04、全栈链路追踪
除去全栈链路追踪功能以外,其他的功能都是利用 DeepFlow 提供的数据基于 SQL API 在 UI 层面二开即可,而全栈链路追踪功能如果仅用 DeepFlow 的数据,会在跨线程或者异步调用的情况下出现断路的情况,与 DeepFlow 社区讨论要解决这个问题,需要依赖一个全局 ID 来将断路串联,于是我们做了以下改造:
- 构造全局 ID:入口服务构建全局的 trace_id,利用 HTTP/FastCGI 协议的 Header向下游服务透传。DeepFlow Agent 采集到数据后,在解析协议时将 Header 中的 trace_id 提取用于调用链追踪,从而解决了跨线程或异步调用断链的问题。
07-构造全局ID
- 开启 x_request_id:在解决完跨线程或异步调用问题后,我们发现过双 7 层网关(云 ALB -> K8s Ingress)的场景下,如果云 ALB 同时又无法部署 agent,不能利用 eBPF 自动追踪,就也会出现断链的情况。反馈给 DeepFlow 社区后,社区立马给出解决方案,同时开启云 ALB 与 K8s Ingress 的 x_request_id 能力即可解决,DeepFlow 的 AutoTracing 能利用不同方向的 x_request_id 解决了这种断链问题。
08-开启x_request_id
总结来说,相比 APM 系统来说,调用链追踪落地的过程顺滑非常多:业务开发仅仅只是透传了一个全局 ID,平台建设方的我们也只是联系了 7 层网关负责人帮忙开启 x-request-id 就得到了完整分布式调用的全栈链路追踪火焰图。通过火焰图的形式完整的展示一条调用的全链路,包含服务、系统进程、网络接口各个层面。
09-全栈链路追踪
05、资源开销
目前整个可观测性平台试跑在一个集群中,集群规模 50 个 Node(32C64G),1000 个 Pod,每分钟写入 5000w 条数据,一天下来大概需要消耗 4T 的存储空间。主要的资源开销如下:
10-资源开销
06、性能调优
在试运行过程中,我们从多个方面对整个可观测性平台的性能进行了优化,实现了平台的平稳运行。
Agent 端流量采集丢包:我们发现 Grafana 大盘中的 Agent 自监控指标 Packet Drops in Kernel 持续告警。解决这个问题我们进行了两个方面的调整:对 Agent 的资源量限制,即 max_cpus 和 max_memory,从默认值调高到了 1C1G;由于我们仅关注七层指标和调用日志,通过设置 l4_log_tap_type = -1 禁用了 Agent 的四层流日志采集功能,降低 Agent 的压力。经过上述两个调整,Agent 的负载有明显的降低。以此为基础,为了确保我们关注的调用日志能全量采集,我们将默认的调用日志采集速率 l7_log_collect_nps_threshold 从 10000 调整到了 20000。
11-丢包问题
Server 端接收数据丢包:排查下来发现,Agent 和 Server 之间的通信使用长连接,且我们在中间加入了 LB。而 LB 在长连接的场景下无法根据 Agent 的发送数据量做动态均衡。我们的解决方法是使用 K8s Node Port 进行流量均衡。但目前此方案还存在一个潜在问题,如果 K8s 某个 Node 流量过高,可能会导致该节点通信质量的降低,需要对此进行监控。
Server 端处理流程丢包:默认情况下 Server 内的所有组件之间使用单队列进行数据交换。通过调整 queue-count 为 2 可以提高 Server 的处理能力。另外,默认情况下 Server 的接收限速 throttle 为 50000 每秒,表示每秒处理 5 万条调用日志,我们根据实际资源消耗情况调高到了 150000。试运行过程中也发现了一些 Server 端的报错,我们及时反馈给了 DeepFlow 社区,得到了快速的解决。
12-超时问题
页面查询超时:上述丢包问题解决之后,我们发现平台的数据量激增上来了,整个平台每分钟的数据量达到了 5000 万条。这导致页面上的很多查询超时,我们和 DeepFlow 社区一起,进行了一系列 API 性能优化、deepflow-app 查询性能优化、ClickHouse 缓存性能优化。具体的优化点包括:
- 调用日志页面展现优化:原有查询未加时间范围,我们修改为查询最近两分钟的调用日志,且通过分页来实现异步加载。
- 火焰图查询参数优化:点查调用日志时,我们增加了调用日志前后两秒的时间范围约束,提高调用日志和调用链的查询效率。
- 调用日志主键调整:ClickHouse 中 l7_flow_log 表的主键索引中,将 time 提前到最前,提高时间过滤的查询加速效果。
- CK 查询语句优化:将 ClickHouse 中 time 过滤条件放到 PREWHERE 中,将其他条件放到 WHERE 中,提高 PREWHERE 的效率。
经过上述一系列的查询优化之后,我们可以明显的看到查询性能的提升。优化前链路查询大部分在 60 秒以上,优化后基本上查询耗时在 10-20 秒之间。
07、未来规划
经过一段时间的使用,发现 DeepFlow 能力很强大,我们基于 DeepFlow 构建的零侵扰可观测性平台,也让部分研发和 SRE 试用了,反馈也是非常好。接下来准备在各个业务线全方位推广使用,基于可观测性平台推动业务线对应用性能进行全方位的优化,实现降本增效的目标。
13-未来规划
参考资料
[1] 回看链接: https://www.bilibili.com/video/BV1zH4y1S7zG/
[2] PPT 下载: http://yunshan-guangzhou.oss-cn-beijing.aliyuncs.com/yunshan-ticket/pdf/ab5c0568c000db0d0669c8c6a59c3551_20230921103335.pdf