当前团队考虑通过一些故障注入或者故障模拟的方式来进行故障分析的测试.因此选择了ChaosBlade来进行技术实现.
阿里开源的混沌实验实施工具
支持Java 应用、C++ 应用、Docker 容器、云原生平台等
其中的Chaosblade-exec-jvm模块,基于jvm-sandbox(https://github.com/alibaba/jvm-sandbox)
ChaosBlade的具体介绍可以到这里了解: https://github.com/chaosblade-io/chaosblade/blob/master/README_CN.md
开箱即用,下载最新版release版本解压可用(记得配置环境变量或临时环境变量)
下载地址: https://github.com/chaosblade-io/chaosblade/releases
当前下载版本chaosblade-1.4.0,解压可得下图内容,通过blade执行命令
chaosblade支持两种调用方式:CLI 和 HTTP
cli即客户端模式,http即url调用模式,以下给出http示例,本文主要基于cli模式的jvm场景使用
//启动http服务,在指定端口,开放给功能调用
blade server start -p 端口号
//执行 CPU 满载实验 注意:此处的%20是url空格
curl "http:/xxxx:9526/chaosblade?cmd=create%20cpu%20fullload"
执行场景命令之前,需要先挂载java agent,此操作需要一点点时间
操作成功,会返回实验准备的UID
命令: blade prepare jvm --pid {java进程pid}
[root@JXQVKDSAP04 test]# blade prepare jvm --pid 26383
{"code":200,"success":true,"result":"7b2893ef0b180fab"}
在卸载实验时会用到此处返回的UID
实验执行完毕,停止场景
命令: blade destroy {场景UID}
[root@JXQVKDSAP04 test]# blade destroy e02bb5bc8792ced9
{"code":200,"success":true,"result":{"target":"jvm","action":"script","flags":{"classname":"cn.xxx.community.activity.controller.GuessController","methodname":"queryTop","script-file":"/home/test/ChaoTools.java","script-name":"ChaoTools"}}}
卸载UID
命令: blade revoke {实验UID}
简写: blade r {实验UID}
[root@JXQVKDSAP04 test]# blade r 7b2893ef0b180fab
{"code":200,"success":true,"result":"success"}
当忘记UID时,可以通过此命令查询
命令: blade status --type prepare --target jvm
简写: blade s --type p --target jvm
[root@JXQVKDSAP04 test]# blade s --type p --target jvm
{
"code": 200,
"success": true,
"result": [
{
"Uid": "7b2893ef0b180fab",
"ProgramType": "jvm",
"Process": "",
"Port": "25855",
"Pid": "17682",
"Status": "Revoked",
"Error": "",
"CreateTime": "2021-12-29T14:36:58.917334484+08:00",
"UpdateTime": "2021-12-29T16:08:38.856833797+08:00"
}
]
}
不同的场景有专属的参数,具体参数可以在场景命令中查询,通过此命令可以查询通用的参数
所有的命令都可以添加-h查看帮助文档
命令: blade create jvm 或 blade create jvm.md
[root@JXQVKDSAP04 test]# blade create jvm.md
Create a chaos engineering experiment
Usage:
blade create [command]
Aliases:
create, c
Examples:
blade create cpu load --cpu-percent 60
Available Commands:
cplus C++ chaos experiments
cpu Cpu experiment
cri CRI experiment
disk Disk experiment
docker Docker experiment
druid Experiment with the Druid
dubbo Experiment with the Dubbo
es ElasticSearch experiment!
file File experiment
gateway gateway experiment!
hbase hbase experiment!
http http experiment
jedis jedis experiment
jvm Experiment with the JVM
k8s Kubernetes experiment
kafka kafka experiment
lettuce redis client lettuce experiment
log log experiment
mem Mem experiment
mongodb MongoDB experiment
mysql mysql experiment
network Network experiment
process Process experiment
psql Postgrelsql experiment
rabbitmq rabbitmq experiment
redisson redisson experiment
rocketmq Rocketmq experiment,can make message send or pull delay and exception
script Script chaos experiment
servlet java servlet experiment
strace strace experiment
systemd Systemd experiment
tars tars experiment
Flags:
-a, --async whether to create asynchronously, default is false
-e, --endpoint string the create result reporting address. It takes effect only when the async value is true and the value is not empty
-h, --help help for create
-n, --nohup used to internal async create, no need to config
--uid string Set Uid for the experiment, adapt to docker and cri
Global Flags:
-d, --debug Set client to DEBUG mode
Use "blade create [command] --help" for more information about a command.
命令: blade create jvm delay
#对xx类中的xxxname方法注入延迟4s故障
blade c jvm delay --time 4000 --classname=xxx.xxx.xxxclass --methodname=xxxname --process tomcat
返回值类型仅支持基本类型、null、和String
命令: blade create jvm return
#将xx类中的xxxname方法的返回值修改为hello-world
blade c jvm return --value hello-world --classname xxxxclass --methodname xxxname --process tomcat
命令: blade create jvm cpufullload
简写: blade c jvm cfl
#全满载
blade c jvm cfl --process tomcat
#指定2核满载
blade c jvm cfl --cpu-count 2 --process tomcat
支持HEAP,NOHEAP,OFFHEAP,用Heap来表示Eden+Old,用NOHEAP来表示metaspace,用OFFHEAP来表示堆外内存
命令: blade create jvm OutOfMemoryError
简写: blade c jvm oom
#堆空间内存溢出
blade c jvm oom --area HEAP --wild-mode true --process tomcat
#元数据空间内存溢出
blade c jvm oom --area NOHEAP --wild-mode true --process tomcat
CodeCache主要用于存放native code,其中主要是JIT编译后的代码。被JIT编译的一般都是“热代码”,简单说就是调用频率比较高的代码,JIT编译后,代码的执行效率会变高,CodeCache满会导致JVM关闭JIT编译且不可再开启,那么CodeCache满会引起系统运行效率降低,导致系统最大负载下降,当系统流量较大时,可表现为RT增高、QPS下降等
命令: blade create jvm CodeCacheFilling
简写: blade c jvm ccf
blade c jvm CodeCacheFilling --process tomcat
命令: blade create jvm throwCustomException
简写: blade c jvm throwCustomException
简写: blade c jvm tce
#xxx类的xx方法抛出Exception异常,影响次数2
blade c jvm throwCustomException --exception java.lang.Exception --classname xxxx.class --methodname xxxname --process tomcat --effect-count 2
通过自己编写脚本的方式,可以实现复杂的故障注入,例如篡改参数、修改返回值、抛自定义异常等
/**
* 自定义故障注入测试类
* @Author: QQQ
* @Date: 2021/12/29 10:37 上午
*/
public class ChaoTools {
/**
* chaos 默认必须要实现的方法
*/
public Object run(Map<String, Object> params) {
// 调用内存溢出模拟方法
oomHeadTest();
// 返回值,修改原方法的返回值. 返回null 不修改返回值
return null;
}
/**
* 内存溢出模拟
*/
private void oomHeadTest(){
System.out.println("进入oom_head_test");
String randomTxt = "dushdpo9ahdpoaihdpsahdyioandupoiund;oiauern;obvolrsybzlryewrwerkbiwuebyreisuyr";
List<Object> list = new ArrayList<>();
while (true){
randomTxt += randomTxt;
// 自定义对象(目标类中也有此对象的依赖)
Guess guess = new Guess();
guess.setId(UUID.randomUUID().toString());
guess.setTitle(randomTxt);
list.add(guess);
}
}
}
命令: blade create jvm script
--effect-count string 影响的请求条数
--effect-percent string 影响的请求百分比
--script-content string 脚本文本内容,是Base64编码后的内容,不能和script-file同时使用
--script-file string 脚本文件,文件绝对路径
--script-name string 脚本名称,日志记录用,可不填写
--script-type string 脚本类型,取值为java或groovy,默认为java
示例:
#目标类xxxxclass下的xxxname方法,执行脚本/home/test/ChaoTools.java
[root@JXQVKDSAP04 test]# blade c jvm script --classname cn.xxx.xxx.activity.controller.GuessController --methodname queryTop --script-file /home/test/ChaoTools.java --script-name ChaoTools
{"code":200,"success":true,"result":"e02bb5bc8792ced9"}
此时调用cn.xxx.xxx.activity.controller.GuessController#queryTop接口,则会出现内存溢出,自定义故障注入实现