java故障注入
一、故障注入概述
(一)故障注入的定义
故障注入是一种软件测试和系统验证的技术,旨在通过向系统或应用程序中引入人工故障,来评估系统的可靠性、可用性、性能和容错性。这些人工故障可以模拟各种异常情况,如硬件故障、软件错误、网络故障、异常数据输入、资源耗尽等,帮助开发人员和测试人员发现系统中潜在的漏洞和弱点,从而对系统的健壮性进行评估和改进。
(二)故障注入的目的
-
可靠性测试:评估系统在面临故障时能否正常运行或从故障中恢复。
-
性能测试:观察系统在故障情况下的性能表现,如延迟、吞吐量等指标。
-
容错性测试:检查系统在故障发生时是否能继续提供服务或在故障恢复后能否恢复正常功能。
二、使用 Arthas 进行故障注入
(一)Arthas 简介
Arthas 是一款阿里巴巴开源的 Java 诊断工具,它可以对正在运行的 Java 程序进行监控和诊断。除了常规的诊断功能,它也可以在一定程度上实现故障注入。
(二)使用 Arthas 进行故障注入的步骤
1. 启动 Arthas
首先需要下载 Arthas(curl -O https://arthas.aliyun.com/arthas-boot.jar)
并启动它,通常可以使用以下命令:
java -jar arthas-boot.jar
启动后会列出正在运行的 Java 进程,你可以选择要诊断的进程编号进行连接。
2. 反编译源码
jad --source-only com.example.demo.web.IndexController > /tmp/IndexController.java
3. 修改源码
4. 内存编译java文件
mc -c 18b4aac2 /tmp/ActivateCodeBo.java -d /tmp
备注:18b4aac2 通过sc -d com.example.demo.web.IndexController | grep classLoaderHash ,通过这种方式,直接使用内存编译环境,如果编译失败,也可以直接使用本地的class文件
5. 字节码变更
retransform /tmp/com/example/demo/web/IndexController.class
6. 查看是否变更
7、恢复arthas变更
1)reset *IndexController
2)stop
(三)Arthas 故障注入的特点
-
运行时操作:可以在 Java 程序运行时动态进行故障注入,无需停止或修改原程序。
-
动态性:可以根据需要随时开启和关闭故障注入,且可根据观察到的情况灵活调整。
-
复杂性:部分操作,如修改返回值,涉及字节码操作,较为复杂,需要对 Java 字节码有一定了解,且容易出现问题,可能导致程序崩溃或不可预期的行为。
三、使用 Byteman 进行故障注入
(一)Byteman 简介
Byteman 是一个基于字节码操作的故障注入工具,通过编写 Byteman 规则文件(.btm
),可以在运行时修改 Java 程序的行为,实现对类和方法的监控、修改返回值、注入异常等操作。
(二)使用 Byteman 进行故障注入的步骤
1. 编写 Byteman 规则文件
以下是一个简单的 Byteman 规则文件示例,用于在 com.example.demo.web.IndexController 的 index 方法入口处注入异常:
RULE InjectException CLASS com.example.demo.web.IndexController METHOD index AT ENTRY DO traceln("Injecting RuntimeException into myMethod"); throw new RuntimeException("Simulated RuntimeException"); ENDRULE
2. 应用 Byteman 规则
将上述规则保存为 inject.btm
文件,然后在运行 Java 程序时添加 Java Agent 来应用规则:
premain启动:java -javaagent:/Users/javazhangyi/Desktop/demo/src/main/resources/byteman-download-4.0.23/lib/byteman.jar=script:/Users/javazhangyi/Desktop/demo/src/main/resources/inject.btm -jar /Users/javazhangyi/Desktop/demo/target/demo-0.0.1-SNAPSHOT.jar
agentmain启动:
1)attach pid:bminstall -b -Dorg.jboss.byteman.transform.all -Dorg.jboss.byteman.verbose pid
2)加载规则:bmsubmit -l /Users/javazhangyi/newcy/server/sdk-gateway/branches/gateway_m105/src/test/java/cc.btm
3)卸载规则:bmsubmit -u /Users/javazhangyi/newcy/server/sdk-gateway/branches/gateway_m105/src/test/java/cc.btm
3. 更复杂的 Byteman 规则
可以实现更多的功能,如修改返回值:
脚本1:
RULE IndexController.index
CLASS com.example.demo.web.IndexController
METHOD index
AT EXIT
IF true
DO
$! = "{\"errorCode\":0,\"obj\":{\"uid\":\"189882714\",\"openid\":\"\",\"pi\":\"1hoc88acppysexjcfdtbkxhjgn961p38n5m5uh\",\"age\":108,\"canModified\":0,\"status\":0,\"token\":\"3D9641DB4E9662AD6F9CE6D4EAD71B5563A156CCCABE2F5956BA7E46BCE9B7947F94E611BC10854A5E7BA353968157BAAC494D6440AA31C8\"},\"ret\":true}";
ENDRULE
脚本2:
RULE OrangeloAccountService.cysidToUserInfo CLASS com.cyou.modules.account.webservice.rest.NewOrangeloAccountController METHOD cysidToUserInfo AFTER WRITE $map ALL IF (!$map.isEmpty() && $map.get("uid").equals("189882714")) DO traceln("After write local variable: " + cn.hutool.json.JSONUtil.toJsonStr($map)); $map.put("age", 116); ENDRULE
(三)Byteman 故障注入的特点
-
强大的规则系统:可以编写丰富的规则,实现对 Java 程序的精确控制,如在方法入口、出口、异常抛出点进行操作,修改返回值、修改局部变量等。
-
基于字节码:直接操作字节码,能深入系统底层,可实现复杂的故障注入操作。
-
测试范围广:可以在系统测试、集成测试、性能测试等多个阶段使用。
四、Arthas 与 Byteman 的比较
(一)使用场景
-
Arthas:更适合在开发和测试阶段,对正在运行的 Java 程序进行临时的、简单的故障注入,观察和诊断系统。对于一些快速验证和简单故障注入场景,尤其是在已经运行的程序上,使用 Arthas 会比较方便。
-
Byteman:适用于从测试到生产前的整个测试阶段,可进行系统级的故障注入测试。可以编写复杂的规则文件,对系统进行持续的、有计划的故障注入,在性能测试、可靠性测试、异常注入测试等方面具有优势。
(二)操作难度
-
Arthas:部分操作简单,如观察方法调用和临时的异常注入,但对于复杂的操作,如修改字节码,需要对字节码和 Java 类加载机制有一定了解,操作相对复杂,且有一定风险。
-
Byteman:需要学习 Byteman 的规则语言,对于初学者来说,编写规则文件可能会有一定难度,但对于熟悉字节码操作的人员来说,能更精确地控制故障注入。
(三)功能丰富度
-
Arthas:主要集中在观察和简单的注入,其主要功能是诊断,故障注入是其辅助功能。
-
Byteman:专门的故障注入工具,提供了更丰富的故障注入功能,包括修改返回值、修改局部变量、条件判断等,并且可以在不同阶段(入口、出口、异常点)进行操作。
(四)对系统的影响
-
Arthas:由于是在运行时操作,可能会对运行的程序性能产生一定影响,尤其是进行复杂的观察和修改操作时。而且故障注入的持续时间较短,一般不会长期影响系统。
-
Byteman:由于是在程序启动时通过 Java Agent 加载规则,会对系统产生长期影响,可能会影响系统的性能和稳定性,因此需要谨慎使用,最好在测试环境中使用。
五、总结
故障注入是一种重要的软件测试和系统验证技术,Arthas 和 Byteman 是两种不同的工具,分别适用于不同的场景和需求。Arthas 更侧重于运行时的诊断和简单的故障注入,适合开发人员快速排查问题和进行简单测试;而 Byteman 更适合系统级的测试和复杂的故障注入,能够编写详细的规则对系统进行深度测试。在使用这些工具时,都需要谨慎操作,避免对生产系统造成不可恢复的影响,最好在测试环境中充分测试和验证后再考虑在更高级的环境中使用。