磁盘压力测试
查看磁盘的IO
每秒钟IO操作数(IOPS);
sata硬盘在总线上的速度大约是6Gbps(750MBps),如果速度低于这个值,磁盘可能有问题
测试块存储性能:
https://help.aliyun.com/document_detail/147897.html
安装iotop
# 安装iotop
yum install iotop -y
用dd命令模拟写入一个100G文件
# dd if=源目录 of=目标目录 count=数量 bs=blocksize(块大小)
## 模拟写入100G数据
## if 代表输入文件
## bs 代表字节为单位的块大小
## count 代表被复制的块数
## of 代表输出文件
dd if=/dev/zero of=/root/100G count=1024 bs=100M
# 不走缓存,非阻塞io方式写入数据
# oflag 指定写的方式
## direct: 读写采用直接io方式,不走缓存,直接从内存写硬盘上
## nonblock: 读写数据采用非阻塞IO方式,优先写DD命令的数据
dd if=/dev/zero of=/root/100G count=1025 bs=100M oflag=direct,nonblock
dd常用参数
https://wangchujiang.com/linux-command/c/dd.html
if=file # 输入文件名,缺省为标准输入。 从file读取,如if=/dev/zero,该设备无穷尽地提供0,(不产生读磁盘IO)
of=file # 输出文件名,缺省为标准输出。 向file写出,可以写文件,可以写裸设备。如of=/dev/null,"黑洞",它等价于一个只写文件. 所有写入它的内容都会永远丢失. (不产生写磁盘IO)
ibs=bytes # 一次读入 bytes 个字节(即一个块大小为 bytes 个字节)。
obs=bytes # 一次写 bytes 个字节(即一个块大小为 bytes 个字节)。
bs=bytes # 同时设置读写块的大小为 bytes ,可代替 ibs 和 obs。如bs=8k 每次读或写的大小,即一个块的大小为8K。
cbs=bytes # 一次转换 bytes 个字节,即转换缓冲区大小。
skip=blocks # 从输入文件开头跳过 blocks 个块后再开始复制。
seek=blocks # 从输出文件开头跳过 blocks 个块后再开始复制。(通常只有当输出文件是磁盘或磁带时才有效)。
count=blocks # 仅拷贝 blocks 个块,块大小等于 ibs 指定的字节数。
iflag=FLAGS # 指定读的方式FLAGS,参见“FLAGS参数说明”
oflag=FLAGS # 指定写的方式FLAGS,参见“FLAGS参数说明”
iotop监控磁盘
# 查看iotop
## -o 参数用于指定要排序的列,其后面可以跟以下选项之一:
### READ:按读取磁盘的速率排序
### WRITE:按写入磁盘的速率排序
### SWAPIN:按交换到磁盘的速率排序
### IO:按总磁盘I/O速率排序
iotop
iostat监控磁盘io
iostat监视系统输入输出设备和CPU的使用情况
iostat 分析IO性能
用来看磁盘读写性能的,比如IO使用率
参考地址 http://www.atoolbox.net/Tool.php?Id=826
安装iostat
# Centos7安装iostat
yum install sysstat -y
# ubuntu安装iostat
sudo apt install sysstat -y
模拟写入一个100G文件
## if 代表输入文件
## bs 代表字节为单位的块大小
## count 代表被复制的块数
## of 代表输出文件
dd if=/dev/zero bs=100M count=1024 of=/root/100G
监控磁盘io
# 每秒钟监控一次磁盘IO
iostat -t 1
# 综合用法
## -d:显示设备(磁盘)使用状态。
## -k:表示让某些使用block为单位的列强制使用kB为单位。
## 2:数据显示每隔2秒刷新一次。
iostat -d -k 2
iostat 分析IO性能
用来看磁盘读写性能的,比如IO使用率
# 使用 iostat 命令来监控系统输入/输出设备的负载状况
# -d:显示磁盘设备级别的I/O统计信息,而不是分区
# -x:显示扩展的I/O统计信息,包括更多详细的指标
# -k:以千字节为单位显示统计结果(默认是块为单位)
# 1:刷新间隔为1秒
# 10:刷新10次后停止
iostat -d -x -k 1 10
字段 | 解释 |
---|---|
Device | 设备名称。 |
r/s | 每秒读取请求数。 |
w/s | 每秒写入请求数。 |
rkB/s | 每秒读取的千字节数。 |
wkB/s | 每秒写入的千字节数。 |
rrqm/s | 每秒合并的读取请求数。 |
wrqm/s | 每秒合并的写入请求数。 |
%rrqm | 读取请求的合并率(rrqm/s 与 r/s 之比)。 |
%wrqm | 写入请求的合并率(wrqm/s 与 w/s 之比)。 |
r_await | 读取请求的平均等待时间(毫秒)。 |
w_await | 写入请求的平均等待时间(毫秒)。 |
aqu-sz | 平均I/O队列长度。 |
rareq-sz | 平均读取请求大小(千字节)。 |
wareq-sz | 平均写入请求大小(千字节)。 |
svctm | 平均每个I/O请求的服务时间(毫秒)。 |
%util | 设备的使用率(显示该设备在该时间段内忙碌的百分比,100%表示设备一直在处理I/O请求)。 |
示例
# 监测磁盘 I/O 性能
## -d: 仅显示磁盘设备的 I/O 统计信息。
## -m: 以兆字节(MB)为单位显示数据传输统计信息(如 kB_read/s 和 kB_wrtn/s)。
## -x: 显示扩展统计信息,包括I/O 数据,利用率(%util)、等待时间(await)、每次I/O操作的平均时间(svctm)等。
## 1: 表示每秒刷新一次输出结果。
iostat -dmx 1
blktrace—分析IO
实时查看io
## -d 指定要跟踪的设备为 /dev/sda
## -o -:将输出发送到标准输出(- 表示标准输出)
# blkparse 是 解析 blktrace 生成的数据并以人类可读形式显示的工具。
## -i -:从标准输入读取 blktrace 数据(- 表示标准输入)
blktrace -d /dev/sda -o - | blkparse -i -
下面分解步骤
先采集io事件数据
## -d 指定要跟踪的设备为 /dev/sda
blktrace -d /dev/sda
数据保存在sda.blktrace.${cpu}
中
查看I/O事件
# 查看I/O事件
blkparse -i sda
合并采集到的数据文件
先将之前采集到的 多个io事件数据文件合并为一个文件
读取名为 sda 的输入文件(这个文件包含了由 blktrace 工具生成的跟踪数据),然后解析该文件,并将解析的结果写入到名为 sda.blktrace.bin 的输出文件。
## -i sda:指定输入文件为名为 sda 的文件,该文件包含了由 blktrace 生成的跟踪数据
## -d sda.blktrace.bin:输出名为 sda.blktrace.bin 的文件
blkparse -i sda -d sda.blktrace.bin
使用btt来进行统计分析
# 分析这个采集数据
## 指定输入文件为名为 sda.blktrace.bin 的文件
btt -i sda.blktrace.bin
第三方磁盘压测工具fio
参考: https://www.linuxcool.com/fio
安装fio
# 安装依赖包
yum install libaio libaio-devel -y
# 安装fio
yum install fio -y
fio的常用参数
fio \
-filename=/mnt/FIOFILE \ # 指定测试文件的路径
-direct=1 \ # 指定是否绕过系统缓存直接访问磁盘
-iodepth 1 \ # 单个作业的 I/O 深度,即在队列中排队的 I/O 请求数目
-thread \ # 使用线程进行 I/O 操作
-rw=write \ # 读写模式,这里为写入模式
-ioengine=psync \ # 指定 I/O 引擎为 psync(适用于直写)
-bs=4k \ # 每个 I/O 操作的块大小
-size=40G \ # 测试文件的大小
-numjobs=30 \ # 启动的作业数
-runtime=120 \ # 测试运行时间(秒)
-group_reporting \ # 将所有线程的 I/O 操作报告合并为单个报告
-name=mytest # 测试任务的名称
# 测试IO性能
fio -filename=/mnt/FIOFILE -direct=1 -iodepth 1 -thread -rw=write -ioengine=psync -bs=4k -size=40G -numjobs=30 -runtime=120 -group_reporting -name=mytest
fio示例脚本
#!/usr/bin/env bash
# 定义函数 RunFio,用于运行 Fio 测试
function RunFio {
numjobs=$1 # 测试线程数
iodepth=$2 # 同时发出I/O数的上限
bs=$3 # 单次I/O的块文件大小
rw=$4 # 读写策略
size=$5 # 测试文件的大小
filename=$6 # 测试文件的路径
# 查询系统具有多少个逻辑CPU
nr_cpus=$(cat /proc/cpuinfo | grep "processor" -c)
# 如果逻辑CPU数量 < 测试线程数
if [ "$nr_cpus" -lt "$numjobs" ]; then
echo "线程数 超过 逻辑CPU数量,脚本退出!"
# 退出码255(正常范围之外的退出状态码)
exit 255
fi
let nu=$numjobs+1
cpulist=""
# 遍历获取 CPU 核心列表
for ((i = 1; i < 10; i++)); do
list=$(cat /sys/block/your_device/mq/*/cpu_list | awk '{if(i<=NF) print $i;}' i="$i" | tr -d ',' | tr '\n' ',')
if [ -z "$list" ]; then
break
fi
cpulist=${cpulist}${list}
done
# 获取需要绑定的 CPU 列表
spincpu=$(echo "$cpulist" | cut -d ',' -f 2-${nu})
echo "$spincpu"
# 分别将几个jobs绑定不同的CPU Core上
## cpus_allowed_policy FIO提供了参数cpus_allowed_policy以及cpus_allowed来绑定vCPU。
fio --ioengine=libaio --runtime=30s --numjobs="${numjobs}" --iodepth="${iodepth}" --bs="${bs}" --size="${size}" --rw="${rw}" --filename="${filename}" --time_based=1 --direct=1 --name=test --group_reporting --cpus_allowed="$spincpu" --cpus_allowed_policy=split
}
# 将块设备的系统参数rq_affinity取值修改为2
## rq_affinity取值 取值说明
### 1 表示块设备收到I/O完成(I/O Completion)的事件时,这个I/O被发送回处理这个I/O下发流程的vCPU所在Group上处理。在多线程并发的情况下,I/O Completion就可能集中在某一个vCPU上执行,造成瓶颈,导致性能无法提升。
### 2 表示块设备收到I/O Completion的事件时,这个I/O会在当初下发的vCPU上执行。在多线程并发的情况下,就可以完全充分发挥各个vCPU的性能。
echo 2 >/sys/block/your_device/queue/rq_affinity
sleep 5
# 运行 Fio 测试
RunFio 10 128 4k randwrite 1024g /dev/your_device