Skip to content

可用性捣乱

About 2414 wordsAbout 8 min

架构

2025-05-10

如何验证系统高可用,这需要我们能模拟一些可能出现的情况,在这些情况下系统仍然正常响应或者降级服务。包括

  • 主机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 filteriptables 操作的是filter表,表示过滤表,其他表还有NAT表,NAT表示转发,Mangle表用来修改数据包
-I OUTPUTfilter它有以下三种内建链(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 DROPDROP 表示丢弃,但不响应客户端,会导致客户端尝试发送包,直到超时。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此选项后指定网络接口
roottc进行网络流量管理的时候,决定数据包在哪一个队列时候,通过一个叫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
网络IOSO_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/

知行合一