性能测试容器化环境中最常见的目标之一是在需要自动扩展更多 pod 之前了解 pod 可以处理多少负载。由于众多自动扩展 K8 集群会根据 CPU 利用率触发扩展,实践当中这意味着要在 CPU 利用率超过一定水平之前测试 pod 可以承受的吞吐量。(我们认为失败的事务数或响应延迟等业务指标比单纯的 CPU 利用率更好,不过本文将不就此展开详述。)
获取该限值的方法之一是逐渐增加计算机上的负载,并观察何时超过给定的 CPU 利用率。这正是 TUSSLE 框架承担的任务,但其采用更为重要的最大延迟指标。然而这种方法亦有缺陷,操作若有不慎,可能会基于垃圾数据做出业务决策。如果遵循最佳实践,性能测试中的斜坡会非常有用。
为斜坡的每个阶跃留出足够的时间
执行斜坡容量测试时,可在斜坡测试中设置的主要参数包括:
- 初始负载
- 最终负载
- 负载增加速率
- 各负载的停留时间
其中用于得出有效结论的最关键参数为各负载的停留时间。这是因为通常需要很长时间才能看到处理较高负载的效果,例如分配率和垃圾收集。实时集合往往需要很久才能到达临界点。因此,如果斜坡中的每个阶跃都仅持续 5 分钟,但新负载的不良影响需要 15 分钟才会显现,那么故障点的负载实际上比测试结果所认为的负载要低得多。
如果斜坡中的每个阶跃都仅持续 5 分钟,但新负载的不良影响需要 15 分钟才会显现,那么故障点的负载实际上比测试结果所认为的负载要低得多。
“那么如何判断是否已为斜坡的每个阶跃留出了足够的时间?”您可能会这样问。这里给出一些思路。
检查 GC 日志
查看 GC 日志中的各项内容。通过查看 CPU 利用率和第 2 层编译队列,可以很容易地判断 JIT 是否已经完成。您可以查看实时集合是仍在增加还是已经稳定,总体内存利用率是否已经稳定,等等。
实践出真知,实际上,您应在每个阶跃和每次运行中获得可重复数据,并让关键业务指标(每秒事务数、完成的命令数、延迟数)保持稳定。如果仍然看到大量杂乱的测试结果或是测试之间存在较大差异,请继续增加整体测试运行时间以及阶跃之间的时间。
斜坡测试开始前充分预热
确保明确地将 JIT 预热作为单独阶跃进行处理。不要假定 JIT 会作为斜坡上升的一部分独立进行。最佳实践是以合理速率运行,待 JIT CPU 利用率稳定且第 2 层编译队列排定后再开始斜坡测试。
允许预热对于 Azul Platform Prime 等优化 JDK 来说尤其重要,这类 JDK 通过更长时间的 JIT 活动生成更高性能的代码。Prime 的最终预热容量几乎总是较高,但您的测试可能会显示较低的临界点,因为 JVM 将 CPU 同时用于 JIT 和业务逻辑。您可以考虑使用ReadyNow云原生编译器或其他预热优化来缩短预热曲线。
Azul Platform Prime 等优化 JDK 的最终预热容量几乎总是较高,但您的测试可能会显示较低的临界点,因为 JVM 将 CPU 同时用于 JIT 和业务逻辑。
评估结果
一般而言,我们不希望过多关注“何时达到 75%?”之类的非黑即白的测试,而是更倾向于在测试的整个生命周期中观察 CPU 的行为。您可以考虑如何实际收集 CPU 利用率信息。假设您正在查看 Grafana 图表,Prometheus 可能使用 top/ps 或其他命令来收集这些数据。请注意,这些数据通常是 30 秒到 2 分钟内的平均 CPU 利用率,而不是 1 秒实例的 CPU 计数值。这意味着您的 Grafana 图表中可能隐藏有大量 75% 峰值。
此外,还要观察整个运行过程中的趋势,而不仅仅是某事件触发时的趋势。CPU 是持续超过阈值,还是仅有孤立峰值?您能否通过将 CPU 峰值与 GC 周期等进行对照来解释这些峰值?您的峰值是无法控制,出现系统颠簸的迹象,还是可控的一次性峰值?您可能需要查看更细粒度的结果数据,以避免长时间平均窗口的数据隐藏真实情况。祝您在性能测试中使用斜坡时有所收获。
性能测试困难重重
我们的性能专家可协助您以更低云成本获得更好的性能