文章首发于微信公众号【软测小生】
Chaos Engineering(混沌工程),相信搞互联网的或多或少都听过,Netflix 发明了 Chaos Monkey,经过社区的发展回馈,慢慢形成了 Chaos Engineering。
混沌工程是在分布式系统上进行实验的学科, 目的是建立对系统抵御生产环境中失控条件的能力以及信心。
混沌工程原文地址:
https://github.com/wizardbyron/principlesofchaos_zh-cn
大规模分布式软件系统的发展正在改变软件工程。作为一个行业,我们很快采用了提高开发灵活性和部署速度的实践。紧随着这些优点的一个迫切问题是:我们对投入生产的复杂系统有多少信心?
即使分布式系统中的所有单个服务都正常运行, 这些服务之间的交互也会导致不可预知的结果。 这些不可预知的结果, 由影响生产环境的罕见且破坏性的事件复合而成,令这些分布式系统存在内在的混沌。
我们需要在异常行为出现之前,在整个系统内找出这些弱点。这些弱点包括以下形式:
我们必须主动的发现这些重要的弱点,在这些弱点通过生产环境暴露给我们的用户之前。我们需要一种方法来管理这些系统固有的混沌, 通过增加的灵活性和速率以提升我们对生产环境部署的信心, 尽管系统的复杂性是由这些部署所导致的。
我们采用基于经验和系统的方法解决了分布式系统在规模增长时引发的问题, 并以此建立对系统抵御这些事件的能力和信心。通过在受控实验中观察分布式系统的行为来了解它的特性,我们称之为混沌工程。
为了具体地解决分布式系统在规模上的不确定性,可以把混沌工程看作是为了揭示系统弱点而进行的实验。这些实验遵循四个步骤:
破坏稳态的难度越大,我们对系统行为的信心就越强。如果发现了一个弱点,那么我们就有了一个改进目标。避免在系统规模化之后被放大。
以下原则描述了应用混沌工程的理想方式,这些原则基于上述实验过程。对这些原则的匹配程度能够增强我们在大规模分布式系统的信心。
要关注系统的可测量输出, 而不是系统的属性。对这些输出在短时间内的度量构成了系统稳定状态的一个代理。 整个系统的吞吐量、错误率、延迟百分点等都可能是表示稳态行为的指标。 通过在实验中的系统性行为模式上的关注, 混沌工程验证了系统是否正常工作, 而不是试图验证它是如何工作的。
混沌变量反映了现实世界中的事件。 我们可以通过潜在影响或估计频率排定这些事件的优先级。考虑与硬件故障类似的事件, 如服务器宕机、软件故障 (如错误响应) 和非故障事件 (如流量激增或伸缩事件)。 任何能够破坏稳态的事件都是混沌实验中的一个潜在变量。
系统的行为会依据环境和流量模式都会有所不同。 由于资源使用率变化的随时可能发生, 因此通过采集实际流量是捕获请求路径的唯一可靠方法。 为了保证系统执行方式的真实性与当前部署系统的相关性, 混沌工程强烈推荐直接采用生产环境流量进行实验。
手动运行实验是劳动密集型的, 最终是不可持续的。所以我们要把实验自动化并持续运行,混沌工程要在系统中构建自动化的编排和分析。
在生产中进行试验可能会造成不必要的客户投诉。虽然对一些短期负面影响必须有一个补偿, 但混沌工程师的责任和义务是确保这些后续影响最小化且被考虑到。
混沌工程是一个强大的实践, 它已经在世界上一些规模最大的业务系统上改变了软件是如何设计和工程化的。 相较于其他方法解决了速度和灵活性, 混沌工程专门处理这些分布式系统中的系统不确定性。 混沌工程的原则为我们大规模的创新和给予客户他们应得的高质量的体验提供了信心。
当你看到这里的时候,相信你对混沌工程是有一丢丢想法的,要不然你也不会找到这里来,国内关于混沌工程的资料不多,多数都是讲解概念的,可借鉴的落地方案不多(但也不是没有),例如阿里的 Chaosblade,搞明白国内的之后,就可以朝着国外放眼了,这里有大量Chaos Engineering的资料。
本文就以 chaosblade 工具为例,来看看一个简单的 Chaos Engineering 怎么来落地,快速上手:chaosblade wiki,关于 chaosblade 的架构设计本文就不聊了,直接两个字:开干,所有操作均在/mnt/chaosblade-0.0.3 下进行
./blade -h
An easy to use and powerful chaos engineering experiment toolkit
Usage:
blade [command]
Available Commands:
create Create a chaos engineering experiment #create 创建一个chaos engineering
destroy Destroy a chaos experiment #destroy 销毁一个destroy,一般销毁完之后,再执行revoke子命令
help Help about any command #在任何子命令后输入help可查看该子命令的用法
prepare Prepare to experiment #prepare 准备一个chaos engineering实验
query Query the parameter values required for chaos experiments #查询已经注册的chaos
revoke Undo chaos engineering experiment preparation #撤回注册chaos engineering
status Query preparation stage or experiment status #查看注册的chaos engineering的状态
version Print version info
Flags:
-d, --debug Set client to DEBUG mode
-h, --help help for blade
Use "blade [command] --help" for more information about a command.
ps:其中 prepare、create、destroy、revoke 四个指令用的比较多,prepare 是运行 java 程序的时候需要提前使用的一个指令,提前 attach 到 jvm 上
./blade create -h
Create a chaos engineering experiment
Usage:
blade create [command]
Aliases:
create, c
Examples:
create dubbo delay --time 3000 --offset 100 --service com.example.Service --consumer
Available Commands:
cpu Cpu experiment #cpu负载测试,还可以指定负载在哪个cpu上
disk Disk experiment #disk负载测试,支持disk的read/write负载模拟,还支持模拟磁盘填充
docker Execute a docker experiment #docker负载测试,支持docker的cpu、disk、network、process、remove、script等负载测试
druid Druid experiment #支持druid连接池的连接满模拟
dubbo dubbo experiment #支持dubbo的延迟、连接池满、异常模拟
jvm method #这个支持的就多了,下面细聊
k8s Kubernetes experiment #k8s负载测试,支持k8s的同期的删除测试
mysql mysql experiment #支持mysql的延迟、异常模拟
network Network experiment #network负载测试,支持网络的延迟、dns查询延迟、丢包、远程服务丢失等场景
process Process experiment #process负载测试,支持模拟kill process的场景
script Script chaos experiment
servlet java servlet experiment #支持servlet的延迟、异常模拟
Flags:
-h, --help help for create
Global Flags:
-d, --debug Set client to DEBUG mode
Use "blade create [command] --help" for more information about a command.
其中 network、jvm、mysql、docker 都是一些热门组件的异常模拟场景。
下面看看 jvm 的,jvm 支持以下五个场景:
delay delay time
outofmemoryerror JVM out of memory
return Return the specify value
throwCustomException throw custom exception
throwDeclaredException Throw the first declared exception of method
ps:其中 delay、throwCustomException 都是需要指定到方法级别的,如果测试人员对业务代码了解深入的话,可以利用这个特性做破坏性测试。
看着支持的场景很多,其实在 Chaosblade 没出现之前,cpu、disk、network、process、k8s 这些场景都是可以通过 linux 下面的某些命令来模拟的,如果是阿里生态系的,jvm、druid、dubbo 这三个需要熟练的使用, 如果官方能提供 oracle 的异常场景就更好了。
blade 需要和待测试的运行进程属于同一用户,且 JAVA 版本、JAVA_HOME 要设置正确。针对系统层面的设置,则需要管理员权限。
./blade prepare jvm --process 19761
---
{"code":200,"success":true,"result":"2679c66005a0aadd"}
ps:2679c66005a0aadd 需要记住,如果忘记也可以通过 query 查询
./blade create network delay --interface eth0 --exclude-port 22 --time 10000
---
{"code":200,"success":true,"result":"dc913ccc9a7e5ea1"}
ps:注意针对接口的延迟需要管理员权限才能操作
#测试前
time curl http://192.168.1.6:8000/test/index.php -I
---
HTTP/1.1 200
Content-Type: application/json;charset=UTF-8
Content-Length: 69
Date: Mon, 10 Jun 2019 08:35:31 GMT
real 0m0.026s
user 0m0.003s
sys 0m0.000s
#测试后
time curl http://192.168.1.6:8000/test/index.php -I
---
curl: (7) couldn't connect to host
real 0m3.003s
user 0m0.001s
sys 0m0.003s
ps:可以看到针对 url 的访问明显失败
./blade status --type create
{
"code": 200,
"success": true,
"result": [
{
"Uid": "dc913ccc9a7e5ea1",
"Command": "network",
"SubCommand": "delay",
"Flag": "--exclude-port 45685 --debug false --help false --interface eth0 --time 10000",
"Status": "Success",
"Error": "",
"CreateTime": "2019-06-10T16:36:31.072125181+08:00",
"UpdateTime": "2019-06-10T16:36:31.107533437+08:00"
}
]
}
./blade destroy dc913ccc9a7e5ea1
---
{"code":200,"success":true,"result":"command: network delay --exclude-port 22 --debug false --help false --interface eth0 --time 10000"}
先查询id
./blade status --type prepare
---
{
"code": 200,
"success": true,
"result": [
{
"Uid": "2679c66005a0aadd",
"ProgramType": "jvm",
"Process": "19761",
"Port": "16698",
"Status": "Running",
"Error": "",
"CreateTime": "2019-06-10T16:31:58.09072211+08:00",
"UpdateTime": "2019-06-10T16:32:05.907016597+08:00"
}
]
}
再撤销
./blade revoke 2679c66005a0aadd
---
{"code":200,"success":true,"result":"success"}
ps:默认的场景肯定不能完全适应你的需求,所以我们还是需要了解 Chaosblade 的设计模型的,看看如何自定义扩展需求场景
阿里 Chaosblade 项目地址: https://github.com/chaosblade-io/chaosblade/wiki/%E6%96%B0%E6%89%8B%E6%8C%87%E5%8D%97
ChaosEngineering工程实战–chaosblade https://my.oschina.net/guol/blog/3060265
作者:China_OS(开源中国)