• ChaosBlade Java 场景性能优化,那些你不知道的事


    01

    介绍

    Aliware

    ChaosBlade 是阿里巴巴开源的一款遵循混沌工程原理和混沌实验模型的实验注入工具,帮助企业提升分布式系统的容错能力,并且在企业上云或往云原生系统迁移过程中业务连续性保障。

    目前支持的场景有:基础资源、Java 应用、C++ 应用、Docker 容器以及 Kubernetes 平台。该项目将场景按领域实现封装成单独的项目,不仅可以使领域内场景标准化实现,而且非常方便场景水平和垂直扩展,通过遵循混沌实验模型,实现 ChaosBlade cli 统一调用。

    不过 Java 场景下的故障注入目前有一些性能问题,主要体现在故障注入时会让 CPU 的使用率大幅度抖动,严重情况下可能会导致 CPU 的使用率 100%。这种情况对于线下服务的影响还好,但是对于线上服务就比较严重了,因为 CPU 的使用率较高有可能会导致服务的整体性能变差,从而影响接口的耗时。

    通过对 ChaosBlade Java 场景的性能优化,使 CPU 在故障注入时的抖动得到了有效的控制,不会再出现 CPU 使用率达到 100% 的抖动,经过测试在线上 8C,4G,QPS 3K 左右的服务实例上注入 Dubbo 自定义抛异常的故障,CPU 的使用率可以控制在 40% 左右的瞬时抖动范围内,性能整体提升近 2.5 倍。

    本文将会详细的介绍影响性能的问题点以及是如何对这些问题进行优化的。

    02

    Java 场景

    Aliware

    在介绍前先了解下 ChaosBlade Java 场景的注入流程。

    Java 场景的故障注入是基于字节码增强框架 JVM-Sandbox 实现的,注入一个故障分为两步:

    1. ChaosBlade 执行 prepare 命令,触发 sandbox 对目标 JVM 挂载 Java agent。

    2. ChaosBlade 执行 create 命令,触发 sandbox 对目标 JVM 进行字节码增强,从而达到故障注入的目的。

    03

    Prepare(挂载)阶段优化

    Aliware

    01

    现象

    本地模拟一个简单的 HTTP 服务,控制其 CPU Idle 在 50% 左右,当执行 blade prepare jvm --pid 挂载 agent 后,发现 CPU 空闲率迅速下降,并且下降的幅度较大。在生产中进行故障注入有可能会直接让 Idle 掉低从而触发告警:

    02

    定位

    通过采集 CPU profile 生成火焰图来观察在执行 blade prepare 时 CPU 的使用情况,如下图可以看到 loadPlugins 方法是资源消耗的重灾区。

    loadPlugins方法中主要是加载 ChaosBlade Java 中支持的全部插件,例如 dubbo,redis,kafka 等。当加载了这些插件后就可以进行故障注入了。加载插件的过程中会对插件中定义的类以及方法进行字节码增强。

    导致 CPU 消耗的问题就在于加载全量的插件耗时较大,而我们故障注入时会选择具体某个插件进行故障注入,显然全量加载并不是最优解

    03

    优化

    优化思路:既然故障注入时会选择具体的插件,那么通过懒加载的方式即可解决,当我们要针对哪一个插件故障注入就加载哪个插件,加载的粒度变小,CPU 的消耗自然就小了:

    核心代码:

    在故障注入阶段,通过指定的插件进行懒加载。

    1. private void lazyLoadPlugin(ModelSpec modelSpec, Model model) throws ExperimentException {
    2. PluginLifecycleListener listener = ManagerFactory.getListenerManager().getPluginLifecycleListener();
    3. if (listener == null) {
    4. throw new ExperimentException("can get plugin listener");
    5. }
    6. PluginBeans pluginBeans = ManagerFactory.getPluginManager().getPlugins(modelSpec.getTarget());
    7. if (pluginBeans == null) {
    8. throw new ExperimentException("can get plugin bean");
    9. }
    10. if (pluginBeans.isLoad()) {
    11. return;
    12. }
    13. listener.add(pluginBean);
    14. ManagerFactory.getPluginManager().setLoad(pluginBeans, modelSpec.getTarget());
    15. }

    详细代码 PR:

    https://github.com/ChaosBlade-io/ChaosBlade-exec-jvm/pull/233

    04

    改进后效果

    CPU Idle 下降幅度降低

    火焰图中的 CPU 使用率几乎“消失”

    04

    Create(注入)阶段优化

    Aliware

    在实际使用中发现故障注入导致 CPU Idle 跌底的情况比较多,跌底的持续时间是比较短暂的基本都在 20S 左右,有一些情况是和目标服务的业务代码有关系或者是和目标服务的 jvm 参数设置有关,本文只介绍由 ChaosBlade 导致的或间接导致的 CPU Idle 跌底问题。

    CPU Idle 跌底:这里指的是 CPU 空闲率降低为 0,同时意味着 CPU 使用率达到了 100%。

    01

    Dubbo 故障优化

    • 问题描述

    ChaosBlade 中支持对 dubbo provider 或者 consumer 进行故障注入(例如抛异常),当一个服务既是 provider 又是 consumer 的时候,如果对 provider 故障注入则会触发 bug,有可能会导致 CPU Idle 跌底。

    正常情况:一个既是 provider 又是 consumer 的服务,它的请求处理流程是流量会首先进入到 provider 经过处理后交由业务逻辑执行,最后通过 consumer 将请求转发出去。

    针对 consumer 故障注入:当利用 ChaosBlade 对 consumer 进行故障注入时,流量到达 consumer 就会抛出异常,不会将流量真正的转发出去,从而达到一个模拟故障发生的效果。

    针对 provider 故障注入:当利用 ChaosBlade 对 provider 进行故障注入时,流量到达 provider 就会抛出异常,不会将流量向下转发。

    上面说的都是预期效果,实际上 ChaosBlade 无论是对 provider 或者 consumer 进行故障注入时,都会同时 p

  • 相关阅读:
    Linux驱动开发(外传)---驱动开发调试方法
    Spring-依赖注入findAutowireCandidates源码实现
    若依vue前端 报错error:0308010C:digital envelope routines::unsupported
    2023.9.2 关于 JVM 垃圾回收机制(GC)
    基于C# wimfom框架的图书管理系统开题报告
    Flink DataStream 作业调优
    【八股总结】至今为止遇到的八股(上半)
    卸载各种方式安装的K8S集群
    【集装箱调度】基于粒子群算法实现考虑重量限制和时间约束的集装箱码头满载AGV自动化调度附matlab代码
    AIDL+MemoryFile匿名共享内存实现跨进程大文件传输
  • 原文地址:https://blog.csdn.net/java_lujj/article/details/126776056