可用性捣乱
如何验证系统高可用,这需要我们能模拟一些可能出现的情况,在这些情况下系统仍然正常响应或者降级服务。包括
- 主机CPU增高
- 主机网络阻塞
- 虚拟机漂移导致网络丢包丢弃
- 下游服务不可用
- 基础服务不可用,如Redis,数据库
程序员或者运维人员可以主动制造这些故障,以验证服务的可用性,电商经常在大促之前由专门团队对系统进行捣乱。传统企业应用也会定期故障演练
分享集中在使用linux命令来模拟系统故障,不涉及到故障演练的方案,适合开发人员自测
2 定义
3 实践
网络捣乱对于微服务系统最常用的捣乱
CPU捣乱
使用耗费CPU资源的计算类命令,如下命令使用openssl命令,用来测试所有加密算法的速度
> openssl speed -multi 1
-multi 后指定的CPU个数,如果想让主机CPU使用率100%,可以使用
openssl speed -multi $(grep -ci processor /proc/cpuinfo)
OpenSSl1.1版本以上,还支持指定运行时间
openssl speed -multi 4 -seconds 19
gzip命令也可以导致CPU使用率非常高,如下命令按照最大压缩比压缩/dev/urandom,会使用1C
cat /dev/urandom | gzip -9 > /dev/null
如果是多核系统,可以使用多次gzip,如下命令会占满4C
cat /dev/urandom | gzip -9 | gzip -9 | gzip -9 | gzip -9 > /dev/null
磁盘IO捣乱
模拟磁盘IO写频率高
需要使用dd命令,反复CP文件。如下命令使用dd生成一个512M的文件loadfile
dd if=/dev/zero of=loadfile bs=1M count=512
在shell中执行一个循环cp命令
> for i in {1..100}; do cp loadfile loadfile1; done
// 或者一直循环
> while true; do cp loadfile loadfile1; done
通过sar -b 2 命令观测,可以看到磁盘使用负载增加
01:52:55 tps rtps wtps bread/s bwrtn/s
01:52:59 0.00 0.00 0.00 0.00 0.00
01:53:03 0.00 0.00 0.00 0.00 0.00
01:53:07 0.00 0.00 0.00 0.00 0.00
01:53:11 0.00 0.00 0.00 0.00 0.00
01:53:15 0.00 0.00 0.00 0.00 0.00
01:53:19 0.00 0.00 0.00 0.00 0.00
01:53:23 0.00 0.00 0.00 0.00 0.00
01:53:27 0.00 0.00 0.00 0.00 0.00
01:53:31 471.50 0.00 471.50 0.00 787040.00
01:53:35 544.75 0.00 544.75 0.00 919592.00
01:53:39 484.50 0.00 484.50 0.00 915682.00
内存捣乱
模拟主机内存不够
需要挂载一个ramfs文件系统,ramfs是Linux下一种基于RAM做存储的文件系统,如下命令创建一个ramfs文件系统
mkdir memory
mount -t ramfs ramfs memory/
查看内存,内存free显示
>free -m
total used free shared buffers cached
Mem: 2026 1441 584 0 145 631
使用dd命令在memory目录下创建一个256M大小文件
dd if=/dev/zero of=file1 bs=1M count=256
再次查看内存
>free -m
total used free shared buffers cached
Mem: 2026 1697 329 0 145 887
需要注意,创建内存文件,需要计算好大小,linux不限制使用ramfs大小, 如果占用过大内存,将导致系统崩溃!
网络捣乱
使用iptables
iptables 是 Linux 防火墙系统的重要组成部分,iptables 的主要功能是实现对网络数据包进出设备及转发的控制。当数据包需要进入设备、从设备中流出或者由该设备转发、路由时,都可以使用 iptables 进行控制。
比如:服务器A连接服务器B(10.205.243.247)时,模拟服务器B无响应,需要在A上配置如下两条命令(因为在B上做限流可能会影响B的其他交互方,故在A上做配置)
如下第一行命令运行在服务A上,对目标服务器10.205.243.247 (如上图服务B)访问限流,允许每秒通过50个MTU,即50*1500字节=75K.
第二行命令是对不符合第一条规则情况下的处理,采用了drop动作,即每秒超出75K后,不响应客户端。
$sudo iptables -t filter -I OUTPUT -p tcp -d 10.205.243.247 -m limit --limit 50/s -j ACCEPT
$sudo iptables -t filter -A OUTPUT -p tcp -d 10.205.243.247 -j DROP
此命令的具体含义如下
-t filter | iptables 操作的是filter表,表示过滤表,其他表还有NAT表,NAT表示转发,Mangle表用来修改数据包 |
-I OUTPUT | filter它有以下三种内建链(chains):INPUT链 – 处理来自外部的数据。OUTPUT链 – 处理向外发送的数据。FORWARD链 – 将数据转发到本机的其他网卡设备上。这里-I表示插入,-A表示添加 |
-p tcp | 这里指定协议是tcp协议,还可以是 udp, icmp或者all表示所有协议 |
-d 10.205.243.247 | 表示对外发送链路的ip地址 |
-m | 表示一个match |
limit --limit 50/s | 这里表示限流,每秒50个包,1/m,表示每分钟1个包 |
-j ACCEPT | 这里j表示jump,跳转到一个个执行动作,ACCEPT表示接收,另外还有DROP和REJECT |
-j DROP | DROP 表示丢弃,但不响应客户端,会导致客户端尝试发送包,直到超时。REJECT,表示响应客户端并拒绝数据包。 |
命令sudo iptables -L -n -v --line-number
可以查看防火墙设置的内容, 可以在Chain OUTPUT
成功设置了限流
$ sudo iptables -L -n -v --line-number
Chain OUTPUT (policy ACCEPT 380 packets, 23738 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT tcp -- * * 0.0.0.0/0 10.205.243.247 limit: avg 50/sec burst 5
2 0 0 DROP tcp -- * * 0.0.0.0/0 10.205.243.247
如果需要重新设置限流,可以调用iptables --flush
清空防火墙
作为服务B,也可以设置输入限流,则使用INPUT链路,如下是一个例子,对来源请求10.205.243.15进行限流,每分钟5个包通过
sudo iptables -t filter -I INPUT -p tcp -s 10.205.243.15 -m limit --limit 5/s -j ACCEPT
sudo iptables -t filter -A INPUT -p tcp -s 10.205.243.15 -j DROP
设置防火墙必须谨慎,需要运维人员参与把关,如果限流动作是 "--limit 1/m". 每分钟一个包,则有可能远程登录不上此服务器
使用tc
Linux内核内置了一个Traffic Control框架,可以实现流量限速,流量整形, 通常用于网络管理。
tc通过一个qdisc('queueing discipline' 排队规则的简称)对流量进行控制,,每当内核需要向网络接口发送数据包时,就会将其排入qdisc,之后,内核立即尝试从qdisc获取尽可能多的数据包发送
下图是要给默认的排队规则pfifo_fast
*来自:*https://arthurchiao.art/blog/lartc-qdisc-zh/
pfifo_fast根据IP协议的tos(type of service)字段决定将报文放到哪一个队列.
模拟网络故障可以使用netem (Network Emulation)规则,此规则可以模拟网络延迟,丢包等故障
如下命令对网络接口eth0 的发送造成延迟100ms ,这样可以模拟本机访问服务器延时,而不需要服务器真的出现故障,类似iptable设置OUTPUT规则
>tc qdisc add dev eth0 root netem delay 100ms
或者设置丢包率10%
>tc qdisc add dev eth0 root netem loss 10%
选项含义如下
选项 | |
---|---|
qdisc | 'queueing discipline' 排队规则的简称,默认是pfifo_fast,还有netem,tbf(令牌桶过滤器) |
add | 增加一条规则,其他选项还有delete,replace,show |
dev | 此选项后指定网络接口 |
root | tc进行网络流量管理的时候,决定数据包在哪一个队列时候,通过一个叫root的处理器处理。 |
netem | 网络仿真器 Network Emulator 简称,对指定网络接口输出提供包丢失,包延迟,包重复等特性 |
loss | 设置丢包率,如10% |
delay | 设置延迟,如100ms |
show选项可以查看当前网络丢包配置
> tc qdisc show
qdisc netem 8001: dev enp0s8 root refcnt 2 limit 1000 loss 10%
delete选项可以删除网络TC配置
>tc qdisc show dev eth0
入口限速
tc 也支持入口限流,模拟客户端响应慢,参考 https://blog.csdn.net/zhangskd/article/details/8240290
在Java代码捣乱
例子 | 捣乱点 | 目的 |
---|---|---|
线程池配置 | 线程数设置到最小1或者队列设置1 | 模拟调用量大 |
工作线程阻塞 | 模拟工作线程执行时间长导致线程池满 | |
方法调用 | 增加延迟 | 模拟方法在后期迭代调用时间逐渐变长对系统影响 |
连接池配置 | 连接池设置最小 | 模拟访问量大 |
连接使用后不归还 | 模拟数据库处理时间较长或者代码BUG | |
网络IO | SO_RCVBUF 设置较小 | 模拟缓慢接收对端发送的数据 |
Servlet Filter | 抛出Runtime异常 | 模拟在不应该抛出异常地方抛出RuntimeException |
ChaosBlade 提供java agent,自动注入捣乱代码
4 ChaosBlade
ChaosBlade 是阿里巴巴 2019 年开源的混沌工程项目,包含混沌工程实验工具 chaosblade 和混沌工程平台 chaosblade-box,旨在通过混沌工程帮助企业解决云原生过程中高可用问题。实验工具 chaosblade 支持 3 大系统平台,4 种编程语言应用,共涉及 200 多的实验场景,3000 多个实验参数,可以精细化的控制实验范围。 混沌工程平台 chaosblade-box 支持实验工具托管,除已托管 chaosblade 外,还支持 Litmuschaos 实验工具。已登记使用企业 40 多家,其中已在工商银行、中国移动、小米、京东等企业中落地使用。https://chaosblade.io/
5 参考
系统负载模拟:https://bash-prompt.net/guides/create-system-load/
tc netem命令: https://www.man7.org/linux/man-pages/man8/tc-netem.8.html
tc 原理详解:https://arthurchiao.art/blog/lartc-qdisc-zh/