-
Notifications
You must be signed in to change notification settings - Fork 955
混沌实验模型
遵循此模型,可以简单明了的执行一次混沌实验,控制实验的最小爆炸半径。并且可以方便快捷的扩展新的实验场景或者增强现有场景。chaosblade 和 chaosblade-exec-jvm 工程都根据此模型实现。
在给出模型之前先讨论实施一次混沌实验明确的问题:
- 对什么做混沌实验
- 混沌实验实施的范围是是什么
- 具体实施什么实验
- 实验生效的匹配条件有哪些
举个例子:一台 ip 是 10.0.0.1 机器上的应用,调用 com.example.HelloService@1.0.0 Dubbo 服务延迟 3s。根据上述的问题列表,先明确的是要对 Dubbo 组件混沌实验,实施实验的范围是 10.0.0.1 单机,对调用 com.example.HelloService@1.0.0 服务模拟 3s 延迟。 明确以上内容,就可以精准的实施一次混沌实验,抽象出以下模型:
- Target:实验靶点,指实验发生的组件,例如 容器、应用框架(Dubbo、Redis、Zookeeper)等。
- Scope:实验实施的范围,指具体触发实验的机器或者集群等。
- Matcher:实验规则匹配器,根据所配置的 Target,定义相关的实验匹配规则,可以配置多个。由于每个 Target 可能有各自特殊的匹配条件,比如 RPC 领域的 HSF、Dubbo,可以根据服务提供者提供的服务和服务消费者调用的服务进行匹配,缓存领域的 Redis,可以根据 set、get 操作进行匹配。
- Action:指实验模拟的具体场景,Target 不同,实施的场景也不一样,比如磁盘,可以演练磁盘满,磁盘 IO 读写高,磁盘硬件故障等。如果是应用,可以抽象出延迟、异常、返回指定值(错误码、大对象等)、参数篡改、重复调用等实验场景。
回到上述的例子,可以叙述为对 Dubbo 组件(Target)进行故障演练,演练的是 10.0.0.1 主机(Scope)的应用,调用 com.example.HelloService@1.0.0 (Matcher)服务延迟 3s(Action)。
伪代码可以写成:
Toolkit.
// 实验靶点
dubbo.
// 范围,此处是主机
host("1.0.0.1").
// 组件匹配器,消费者还是服务提供者
consumer().
// 组件匹配器,服务接口
service("com.example.HelloService").
// 组件匹配器,1.0.0 接口版本
version("1.0.0").
// 实验场景,延迟 3s
delay(3000);
针对上述例子,chaosblade 调用命令是:
blade create dubbo delay --time 3000 --consumer --service com.example.HelloService --version 1.0.0
-
dubbo
: 模型中的 target,对 dubbo 实施实验。 -
delay
: 模型中的 action,执行延迟演练场景。 -
--time
: 模型中 action 参数,指延迟时间。 -
--consumer
、--service
、--version
:模型中的 matchers,实验规则匹配器。
注: 由于 chaosblade 是在单机执行的工具,所以混沌实验模型中的 scope 默认为本机,不再显示声明。
为了有个更加直观的认识,我们先通过一下的模型结构图来大致看一下模型之间的关系。核心接口模型是:ExpModelCommandSpec,由它引申出来的是ExpActionCommandSpec和ExpFlagSpec这两个接口。其中,ExpModelCommandSpec已有的具体实现有:cpu、network、disk等;ExpActionCommandSpec则是如cpu下的fullload之类的;ExpFlagSpec是各类自定义参数,比如--timeout。更加详细的模型定义说明请见后续小节。
type ExpModelCommandSpec interface {
// 组件名称
Name() string
// 支持的场景列表
Actions() []ExpActionCommandSpec
// ... 略
}
注: 一个组件混沌实验模型的定义,包含组件名称和所支持的实验场景列表。
type ExpActionCommandSpec interface {
// 演练场景名称
Name() string
// 规则匹配器列表
Matchers() []ExpFlagSpec
// Action 参数列表
Flags() []ExpFlagSpec
// Action 执行器
Executor(channel Channel) Executor
// ... 略
}
注: 一个实验场景 action 的定义,包含场景名称,场景所需参数和一些实验规则匹配器
type ExpFlagSpec interface {
// 参数名
FlagName() string
// 参数描述
FlagDesc() string
// 是否需要参数值
FlagNoArgs() bool
// 是否是必要参数
FlagRequired() bool
}
注: 实验匹配器定义。
拿 network 组件举例,network 作为混沌实验组件,目前包含网络延迟、网络屏蔽、网络丢包、DNS 篡改演练场景,则依据模型规范,具体实现为:
type NetworkCommandSpec struct {
}
func (*NetworkCommandSpec) Name() string {
return "network"
}
func (*NetworkCommandSpec) Actions() []exec.ExpActionCommandSpec {
return []exec.ExpActionCommandSpec{
&DelayActionSpec{},
&DropActionSpec{},
&DnsActionSpec{},
&LossActionSpec{},
}
}
network target 定义了 DelayActionSpec
、DropActionSpec
、DnsActionSpec
、LossActionSpec
四中混沌实验场景,其中 DelayActionSpec
定义如下:
type DelayActionSpec struct {
}
func (*DelayActionSpec) Name() string {
return "delay"
}
func (*DelayActionSpec) Matchers() []exec.ExpFlagSpec {
return []exec.ExpFlagSpec{
&exec.ExpFlag{
Name: "local-port",
Desc: "Port for external service",
},
&exec.ExpFlag{
Name: "remote-port",
Desc: "Port for invoking",
},
&exec.ExpFlag{
Name: "exclude-port",
Desc: "Exclude one local port, for example 22 port. This flag is invalid when --local-port or remote-port is specified",
},
&exec.ExpFlag{
Name: "device",
Desc: "Network device",
Required: true,
},
}
}
func (*DelayActionSpec) Flags() []exec.ExpFlagSpec {
return []exec.ExpFlagSpec{
&exec.ExpFlag{
Name: "time",
Desc: "Delay time, ms",
Required: true,
},
&exec.ExpFlag{
Name: "offset",
Desc: "Delay offset time, ms",
},
}
}
func (*DelayActionSpec) Executor(channel exec.Channel) exec.Executor {
return &NetworkDelayExecutor{channel}
}
-
DelayActionSpec
包含 2 个场景参数和 4 个规则匹配器。
通过以上事例,可以看出此模型简单、易实现,并且可以覆盖目前已知的实验场景。后续可以对此模型进行完善,成为一个混沌实验标准。
应用级别通用的故障场景:
- 延迟
- 异常
- 返回特定值
- 修改参数值
- 重复调用
- try-catch 块异常