作者: 张明辉, 潘胜伟.
随着春节促销的临近,为保证线上业务的高效稳定运营,大部分电商企业都会对其重点业务应用进行多轮测试。 通过模拟高在线流量的请求,可以观察服务的实际性能。 以某企业业务测试报告为例:
图1 压测报告显示成功率很低,全局接口成功率很低。
从报告中可以看出:
当应用程序的流量达到某个临界点时,请求成功率会急剧下降,导致整个测试周期的平均成功率为 989%,响应时间 (RT) 高。 经过深入分析,发现这种高故障率在所有接口上都很普遍,并且在整个压力测试过程中没有任何恢复到稳定状态的迹象。
此类压力测试结果的直观推断是,应用程序可能已达到其性能瓶颈。 Prometheus 监控捕获的 CPU 使用率进一步支持了这样的假设:应用实例的 CPU 使用率几乎饱和,在当前场景下,应用无法处理如此高的 TPS(每秒事务数)。 一方面,通过溯源数据和CPU火焰图,逐步将性能瓶颈定位在顶层,进行针对性优化; 另一方面,为应用集成了开源流量控制保护和断路器降级组件,以应对在线流量的不确定性,并扩展关键业务应用以进一步增强应用可用性。
图 2 压力测试期间应用实例 Pod 的 CPU 指标。
类似的问题在实际业务场景中并不少见,可以归纳为以下两个挑战:
如何定位复杂业务系统中的性能瓶颈? 如何应对流量的不确定性,保护我们的服务? 示例中的公司对上述问题给出了自己的答案:模拟在线流量进行性能测试,使用链路数据+CPU火焰图作为问题定位的依据,通过限流和断路器降级来保护业务。 以上方案在开源领域有相对成熟的实现实践
使用 OpenTelemetry 的 SDK 代理收集跟踪数据使用异步探查器工具生成 CPU 火焰图使用 Sentinel 进行流量治理但实际上,无论是业务转型,还是构建用于数据接收的开放遥测服务器,都会带来一定的成本投入,研发不能再专注于业务开发和维护。 那么,有没有一种非侵入式的自动化方法来解决这个问题呢? 新 3X版J**A探针为这些问题带来了新的答案。
j**a 探测器(也称为 j**aagent)可以在应用程序运行时中增强应用程序本身的字节码,并且业务应用程序本身不需要进行任何 ** 更改即可实现额外的功能 [4]。 部署在 Kubernetes 中的应用也可以自动注入基于 init-container 的探针,进一步降低访问成本。如上所述,在定位和优化慢通话问题时,除了观察应用的关键指标外,还有“两宝”:追踪和CPU火焰图,可以帮助定位业务通话中耗时长且CPU高的段,并相应地修复。 然而,这“两宝”却有其自身的“重伤”:
跟踪数据往往存在盲点
对于 Tracing,其数据一般依靠 Agent SDK 提供的自动或手动跟踪来实现数据采集,然后上报给 Tracracing 数据采集器进行存储,然后由展示端的 Dashboard 关联展示。 显然,链接的细度取决于埋点的粒度。 但是,实际上,链路数据的采集也带来了一定的开销,它不会无限细分粒度,而只是将关键方法埋在了总框架中。 那么,对于一些业务中的高开销逻辑,埋点可能经常缺失,以至于无法准确判断业务逻辑的时间消耗,类似于下图中缺失埋点的问题,在调用链中经常存在。
图3 常见的追踪数据容易出现盲点,因为未被覆盖的埋点。
CPU 火焰图难以帮助定位在线问题
对于CPU火焰图,可以直观地显示业务应用执行过程中的CPU密度点。 火焰图中方法堆栈的宽度表示方法的执行时间,优化了“宽底”和“大平头”的方法,以减少提高性能所需的时间。 然而,许多隐藏的性能问题在测试阶段往往不容易暴露出来,但可以在环境中暴露出来。 火焰图的生成需要一些时间来收集,当重点是止血在线业务时,往往缺少网站的保存,毕竟问题发生后5分钟不可能运行火焰图。 这可能会使定位问题的整个过程复杂化。
图 4 常见 CPU 火焰图中的“大平头”与“宽底座”
那么,有没有无需手动建立密集的埋点您可以观察跟踪数据的盲点,并且可以自动识别慢速跟踪和过滤相关堆栈的 CPU 火焰图并将其与相应的跟踪相关联方法呢? 应用实时监控服务(Application Real-Time Monitoring Service,简称ARMS)。在 3X 版本 j**a 探针通过“热点”。该函数给出了答案。
接下来,我们以解析遍历JSON数据,调用下游HTTP接口的场景为例
public class hotspotaction extends absaction http call private void invokeapi() 读取文件数据并解析 private double readfile() gettype())double totalcount = 0; for (int i = 0; i < movielist.size();i++)return totalcount; }
结合下图,对于上述接口,在跟踪系统中找到一个慢调用链。 可以看出,这个调用链的总时间已经达到了2649ms,但是最后两个跨度和第一个跨度之间存在着2s以上的耗时盲隙(这个逻辑对应上面执行的json数据解析),单靠追踪系统,没有办法定位到缺失的2s耗时在哪个段**。
图5为业务系统的跟踪数据,可以看出,在第二跨度之前存在观察盲点。
针对上述问题,在访问最新版本的武器探头并打开**热点后,问题的根本原因很简单。 你只需要点击调用链详情中的热点选项卡,就可以在右边的火焰图中看到,与Tracing相比,除了左边的HTTP相关方法栈(对应Tracing中的HTTP调用)外,还包含comalibaba.cloud.pressure.memory.hotspotaction.readfile() 中。91s执行时间:
图 6 “热点”选项卡中的实际显示可以直接完成到耗时的方法堆栈。
图的左侧是此调用中涉及的所有方法所花费的时间列表,右侧是按相应方法的所有方法栈信息绘制的火焰图
1)"self"该列显示方法本身消耗的时间或资源。
此指标表示方法在其自己的调用堆栈中消耗的时间或资源,不包括其子方法调用消耗的时间或资源。 帮助确定哪些方法在内部花费了大量时间或资源。 2)"total"该列显示该方法及其所有子方法调用所消耗的总时间或资源量。
此指标包括方法本身及其所有子方法调用所消耗的时间或资源。 帮助您了解哪些方法在整个方法调用堆栈中贡献了最多的时间或资源。 关于如何使用**热点功能生成的火焰图来定位调用速度慢的根本原因,可以重点关注自栏,也可以直接看右边火焰图底部较宽的火焰,定位耗时的业务方法,这是上层耗时高的根本原因, 这通常是系统性能的瓶颈。
从上图可以看出,本文调用速度慢的核心原因是 LinkedList 不具备随机访问的能力,在频繁搜索的场景下开销较高,可以通过重构成索引列表实现(如 ArrayList)来解决。 有关如何使用热点的更多详细信息,请参阅与此功能相关的用户文档
事实上,在压测过程中,如果配置了依赖 CPU 指标和流量指标的弹性,为什么请求成功率会持续下降? 经过分析,从指标达到阈值到新服务实例就绪,其实有一定的时间间隔(可能是因为 j**a 应用启动缓慢,启动时间达到秒级),在突发流量场景中,新服务实例还没准备好,旧服务实例就已经过载了。 此时,业务成功率明显较高,部分原因是旧服务实例过载; 另一个原因是,由于原实例过载,请求处理能力降低,导致大量流量涌入新上线的服务实例,导致新服务实例也因流量过大而过载,陷入持续重启、持续扩容的“最坏情况”。 当系统面临突如其来的流量激增时,有没有办法有效地保护系统始终处于稳态状态?
那是微服务引擎 (MSE)。最新功能,自适应过载保护。
图 7 MSE 自适应过载保护页面。
一般情况下,面对突如其来的流量高峰(弹性来不及扩容),CPU会尖峰(即系统负载增加),全局接口性能明显恶化,如RT会持续加大,成功率会大大降低**。
图8 启用过载保护的大流量压力测试。
aliyun j**aagent 3.X版提供自适应过载保护,有效保护我们的系统。 自适应过载保护在CPU使用率达到阈值时调整限流策略,并以一定百分比限制电流,确保系统负载处于稳定水平,全局接口保持较高的RT和成功率。
图9 启用过载保护的接口性能
总成功率为5099%,在XX接口流量突然增加后,全球所有接口的成功率开始下降,RT也迅速飙升,自适应过载保护生效,成功率逐渐提升,RT也迅速恢复到正常水平。 需要注意的是,压力测试中的电流限制也被视为正常异常,因此成功率仅为5099%(其实去掉限速异常后,请求成功率在80%左右,这也可以从下半年的RT表现中看出来。 )
如前所述“**热点”和“自适应过载保护”。这些功能都基于新的 3X J**A 探针为您的 J**A 应用提供一整套非侵入式接入解决方案,深度集成了 OpenTelemetry、Arthas 和 Sentinel 等多种可观测和微服务治理组件和解决方案。 帮助您快速、无意识地访问应用实时监控服务(ARMS)、微服务引擎(MSE)、企业分布式应用服务(EDAS)、无服务器应用引擎(SAE)等云产品的重要功能。
如何访问 3X J**A 探头
阿里云 j**a 探针提供了多种便捷的访问方式,您可以根据需要自定义可观测性和业务治理能力的访问。 更多信息,请参见ARMS应用监控概述访问 MSE 服务治理应用程序访问。
适用于在阿里云容器服务 (ACK) 上运行的用户。可以使用最简单的访问方式:基于 pilot 模式自动注入和配置探针,无需修改镜像,只需在应用 YAML 中添加几个标签即可访问 J**A 应用的可观测性或服务治理能力。
首先为ack集群安装ack-onepilot,如图所示:
图10 安装ack-onepilot
安装完成后,在ACK集群中创建一个j**a应用,并在Pod中创建一个spec。template.元数据字段,也可以直接编辑部署的YAML文件,在规范中template.metadata.标签
如果要连接ARMS应用实时监控服务,请添加以下两个标签:
armspilotautoenable: "on"armspilotcreateappname: "$"
如果要连接到 MSE 微服务治理服务,请添加以下三个标签:
msepilotautoenable: "on"msepilotcreateappname: "$"msenamespace: "$"
应用部署成功后,可以在ACK控制台看到对应的部署,点击ARMS控制台即可跳转到ARMS控制台查看应用的监控信息。
图11 从ACK控制台跳转到ARMS控制台。
如果您的应用已接入MSE微服务治理,您可以单击ACK控制台的“更多>微服务治理”按钮,进入MSE服务治理控制台。
图12 从ACK控制台跳转到MSE控制台。
版本更改列表
除了“**热点”和“自适应过载保护”功能外,J**a探头还带来了其他新功能:
支持 J**A 21 应用程序的字节码增强功能,单个探测器可以同时支持 J**A 8-21 应用程序的非侵入式可观察数据采集和微服务治理解决方案。 全面升级ARMS数据上报架构,基于短连接和上报压缩,数据上报成功率从99%提升至99%,数据上报成功率从99%提升。99%,提供更稳定、更可用的数据采集服务。 ARMS推出了慢调用诊断工具——基于调用链的热点功能,提供接口慢调用过程的自动观察能力,帮助分析执行中的性能瓶颈。ARMS优化性能,使应用访问更轻、更不敏感。 在2C4G双副本容器场景下,挂载探针导致的额外CPU开销比之前版本减少了50%,在TPS接近极限的场景下CPU仅增加了10%,使用异步框架的场景下的CPU开销优化达到65%,从而获得了更好的性能。 启动时间大幅优化,探针挂载的启动时间减少到5秒以内,通过容器访问将init-container的启动时间减少到6秒以内,探针整体开机时间减少10s+。 详情请参考ARMS J**A探头性能压力测试报告。ARMS支持vertX 和 reactor-netty 等异步框架完整耗时的统计,补充了 OceanBase 和 XXL-JOB 等组件的自动埋藏,优化了 PostgreSQL、Kafka 等现有组件的埋藏,提供更准确、更丰富的指标和跨度数据。MSE 流量保护支持自定义 RPC 调用行为,有关详细信息,请参阅配置 MSE 流量保护行为。MSE 流量保护支持自适应过载保护,根据 CPU 指标和自适应算法自动保护系统不被过多流量淹没。通过其字节码增强功能,j**aagent技术可以在不侵入的情况下增强j**a微服务的功能,为用户带来全新的产品能力体验。 通过本文的解释,我们可以发现阿里云 3X版探针不仅引入了令人兴奋的新功能,而且在用户体验方面也取得了巨大的飞跃。
在性能方面:探头安装启动时间缩短至5秒以内,探头整体启动时间减少 10s+;来自安装探头的额外 CPU与以前的版本相比,开销降低 50%;接近极限的 TPS 场景CPU 仅增加 10%。在特性方面:它带来了诊断和治理领域的新功能,例如自适应负载保护、慢呼叫诊断以及对 J**A 21 的支持。 当然 3X系列J**A探针还不是终点,为了实现阿里云上最好的微服务的目标,我们才刚刚起航。 最新 4X 版本完全兼容开源 OpenTracing 协议,增加了对自定义线程池的监控,提供了更广泛的自动埋藏支持和更可靠的异步跟踪能力。
如果你对文章中提到的“热点”特别感兴趣,欢迎你加入ARMS持续分析产品能力交流钉钉群讨论。 (组号:2256001967)。
1] OpenTelemetry 官方**。
2] 异步分析器工具。
3] 使用 Sentinel 进行流量治理。
4] 什么是 j**a 代理
5] 使用热点来诊断慢速呼叫链。
6] 阿里云 j**aagent 性能压力测试报告。
7] J**ARMS 应用监控支持的组件和框架。
8] 配置MSE流量保护行为。
9] ARMS应用监控访问概述。
10] MSE 服务治理应用程序访问。
11] 容器服务 ACK
12] 配置系统保护。