blade create jvm script

介绍

编写 java 或者 groovy 脚本实现复杂的故障场景,比如篡改参数、修改返回值、抛自定义异常等

参数

以下是此场景特有参数,通用参数详见:[blade create jvm](blade create jvm.md)
1
--effect-count string 影响的请求条数
2
--effect-percent string 影响的请求百分比
3
--script-content string 脚本内容,是 Base64 编码后的内容,相关工具类 [Base64Util](https://github.com/chaosblade-io/chaosblade-exec-jvm/blob/master/chaosblade-exec-plugin/chaosblade-exec-plugin-jvm/src/main/java/com/alibaba/chaosblade/exec/plugin/jvm/Base64Util.java)。注意,不能和 script-file 同时使用。
4
--script-file string 脚本文件,文件绝对路径
5
--script-name string 脚本名称,日志记录用,可不填写。
6
--script-type string 脚本类型,取值为 java 或 groovy,默认为 java。
Copied!
使用 script-content 指定演练脚本内容,不添加 script-type 参数,默认为 java 脚本,将调用 java 引擎解析器。
1
blade c jvm script --classname com.example.controller.DubboController --methodname call --script-content aW1wb3J0IGphdmEudXRpbC5NYXA7CgppbXBvcnQgY29tLmV4YW1wbGUuY29udHJvbGxlci5DdXN0b21FeGNlcHRpb247CgovKioKICogQGF1dGhvciBDaGFuZ2p1biBYaWFvCiAqLwpwdWJsaWMgY2xhc3MgRXhjZXB0aW9uU2NyaXB0IHsKICAgIHB1YmxpYyBPYmplY3QgcnVuKE1hcDxTdHJpbmcsIE9iamVjdD4gcGFyYW1zKSB0aHJvd3MgQ3VzdG9tRXhjZXB0aW9uIHsKICAgICAgICBwYXJhbXMucHV0KCIxIiwgMTExTCk7CiAgICAgICAgLy9yZXR1cm4gIk1vY2sgVmFsdWUiOwogICAgICAgIC8vdGhyb3cgbmV3IEN1c3RvbUV4Y2VwdGlvbigiaGVsbG8iKTsKICAgICAgICByZXR1cm4gbnVsbDsKICAgIH0KfQo= --script-name exception
Copied!
使用 script-file 参数指定文件演练:
1
blade c jvm script --classname com.example.controller.DubboController --methodname call --script-file /Users/Shared/IdeaProjects/Workspace_WebApp/dubbodemo/src/main/java/com/example/controller/ExceptionScript.java --script-name exception
Copied!
执行 groovy 脚本实验场景,参数同上,但必须添加 --script-type groovy 参数。如
1
blade c jvm script --classname com.example.controller.DubboController --methodname call --script-file /Users/Shared/IdeaProjects/Workspace_WebApp/dubbodemo/src/main/java/com/example/controller/GroovyScript.groovy --script-name exception --script-type groovy
Copied!

脚本规范

    必须创建一个类,对类名和包名没有要求,其中所依赖的类,必须是目标应用所具备的类。
    同包下的类引用,必须写全包名,比如故障脚本类是 com.example.controller.ExceptionScript,类中引入了同包下的 DubboController 类,则 DubboController 必须添加 com.example.controller.DubboController。引入非同包下的类,无需写全包名。
    必须添加 public Object run(Map<String, Object> params) 方法,其中 params 对象中包含目标方法参数,key 是参数索引下标,从 0 开始,比如目标方法是 public String call(Object obj1, Object obj2){},则 params.get("0")则返回的是 obj1 对象,可以执行params.put("0", ) 来修改目标方法参数(目标方法及 --classname 和 --methodname 所指定的类方法)。
    上述方法返回的对象如果不为空,则会根据脚本中返回的对象来修改目标方法返回值,注意类型必须和目标方法返回值一致。如果上述方法返回 null,则不会修改目标方法返回值。

案例

对以下业务类做修改返回值实验场景:
1
@RestController
2
@RequestMapping("/pet")
3
public class PetController {
4
5
@GetMapping("/list")
6
public Result<List<PetVO>> getPets() {
7
Map<Long, Discount> petDiscount = discountManager
8
.getPetDiscounts()
9
.stream()
10
.filter(discount -> discount.getExpired() == 0)
11
.collect(Collectors.toMap(
12
Discount::getPetId,
13
Function.identity()
14
));
15
16
List<PetVO> pets = petManager
17
.getPets()
18
.stream()
19
.map(pet -> {
20
PetVO petVO = PetVO.from(pet);
21
Discount discount = petDiscount.get(pet.getId());
22
23
if (null != discount && null != discount.getDiscountPrice() && discount.getDiscountPrice() > 0L) {
24
petVO.setDiscountPrice(discount.getDiscountPrice());
25
}
26
27
return petVO;
28
})
29
.collect(Collectors.toList());
30
31
return Result.success(pets);
32
}
Copied!
则编写 Java 脚本,实现对 getPets 方法做返回值修改:
1
package com.alibaba.csp.monkeyking.controller;
2
3
import java.util.ArrayList;
4
import java.util.List;
5
import java.util.Map;
6
7
import com.alibaba.csp.monkeyking.demo.model.Pet;
8
import com.alibaba.csp.monkeyking.model.PetVO;
9
import com.alibaba.csp.monkeyking.model.Result;
10
11
public class ChaosController {
12
13
public Object run(Map<String, Object> params) {
14
ArrayList<PetVO> petVOS = new ArrayList<>();
15
for (int i = 0; i < 3; i++) {
16
Pet pet = new Pet();
17
pet.setName("test_" + i);
18
PetVO petVO = PetVO.from(pet);
19
petVOS.add(petVO);
20
}
21
Result<List<PetVO>> results = Result.success(petVOS);
22
return results;
23
}
24
}
Copied!
保存文件后,通过上面 使用方式 部分的命令来调用,也可以将其进行 Base64 编码,通过指定 script-content 参数来指定编码后的内容。
1
blade c jvm script --classname com.alibaba.csp.monkeyking.controller.PetController --methodname getPets --script-file /Users/Shared/IdeaProjects/Workspace_WebApp/dubbodemo/src/main/java/com/alibaba/csp/monkeyking/controller/ChaosController --script-name specifyReturnObj
Copied!
未执行实验之前页面:
执行实验之后:

常见问题

Java 实验场景的日志在 进程用户下 logs/chaosblade/chaosblade.log 中。执行脚本成功,但不生效,原因可能是脚本编译错误(因为脚本编译方法调用时触发,所以下发脚本,不会进行编译),可查看此日志进行排查。
Last modified 4d ago