新聞中心
簡(jiǎn)介
一般來說,想檢查磁盤I/O情況,可以使用iostat、iotop、sar等,但這些命令只能做一個(gè)整體的了解,沒法具體到某一次io的詳細(xì)情況,而今天介紹的blktrace就可以深入到Linux I/O棧的方方面面,把一切都搞得明明白白的!

成都創(chuàng)新互聯(lián)專業(yè)為企業(yè)提供建安網(wǎng)站建設(shè)、建安做網(wǎng)站、建安網(wǎng)站設(shè)計(jì)、建安網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計(jì)與制作、建安企業(yè)網(wǎng)站模板建站服務(wù),十年建安做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。
Linux內(nèi)核I/O棧
先了解下Linux內(nèi)核I/O棧,一般來說,我們對(duì)網(wǎng)絡(luò)協(xié)議棧比較熟悉,比如網(wǎng)絡(luò)協(xié)議分了5層,每一層都是干什么的,但對(duì)于I/O棧,則了解相對(duì)較少,如下:
Linux內(nèi)核I/O棧大概分了6層,如下:
- 文件系統(tǒng)層
提供了open、read、write等文件操作的系統(tǒng)調(diào)用給應(yīng)用程序使用,并且Linux提供了文件系統(tǒng)的統(tǒng)一抽象vfs,使得Linux中可適配各種類型的文件系統(tǒng),如ext4、btrfs、zfs、fat32、ntfs等,而我們常說的磁盤格式化,實(shí)際上就是在安裝文件系統(tǒng),重新寫入相關(guān)文件系統(tǒng)的初始元數(shù)據(jù)信息到磁盤。 - 卷管理層
比如我們常聽到的Device Mapper、LVM、soft raid就屬于這一層,用于將多個(gè)磁盤合為一個(gè),或?qū)⒁粋€(gè)磁盤拆分為多個(gè)。 - 塊存儲(chǔ)層
這一層主要實(shí)現(xiàn)io調(diào)度邏輯,比如將一個(gè)大io請(qǐng)求拆分為多個(gè)小的io請(qǐng)求,將相鄰的io請(qǐng)求合并,實(shí)現(xiàn)各種io調(diào)度算法等,常見io調(diào)度算法有CFQ、NOOP、Deadline、AS。 - 存儲(chǔ)驅(qū)動(dòng)層
每一個(gè)硬件都需要驅(qū)動(dòng)程序,硬盤也不例外,如常聽到的SCSI、ACHI、NVME等,且如/dev/sda這樣的設(shè)備抽象文件,也由這一層實(shí)現(xiàn)。 - 硬件層
硬件層就是具體的硬盤實(shí)物了,但我們經(jīng)常聽到ATA、SATA、SCSI、PCIe、SAS等這樣的名詞,這是不同的硬盤接口規(guī)范,就像手機(jī)充電線有Type-A、Type-B、Type-C一樣。
blktrace相關(guān)概念
blktrace跟蹤在塊存儲(chǔ)層(包括卷管理層),它的使用方法如下:
- 第一個(gè)字段:8,0 這個(gè)字段是設(shè)備號(hào) major device ID 和 minor device ID。
- 第二個(gè)字段:3 表示 CPU
- 第三個(gè)字段:11 序列號(hào)
- 第四個(gè)字段:0.009507758 Time Stamp 是時(shí)間偏移
- 第五個(gè)字段:PID 本次 I/O 對(duì)應(yīng)的進(jìn)程 ID
- 第六個(gè)字段:Event,這個(gè)字段非常重要,反映了 I/O 進(jìn)行到了哪一步
- 第七個(gè)字段:R 表示 Read, W 是 Write,D 表示 block,B 表示 Barrier Operation
- 第八個(gè)字段:223490+56,表示的是起始 block number 和 number of blocks,即我們常說的Offset 和 Size
- 第九個(gè)字段:進(jìn)程名
其中第六個(gè)字段表示I/O事件,它代表了 I/O 請(qǐng)求進(jìn)行到了哪一階段,有如下這些事件:
- A?: remap 對(duì)于棧式設(shè)備,進(jìn)來的 I/O 將被重新映射到 I/O 棧中的具體設(shè)備。
- X?: split 對(duì)于做了 Raid 或進(jìn)行了 device mapper(dm) 的設(shè)備,進(jìn)來的 I/O 可能需要切割,然后發(fā)送給不同的設(shè)備。
- Q?: queued I/O 進(jìn)入 block layer,將要被 request 代碼處理(即將生成 I/O 請(qǐng)求)。
- G?: get request I/O 請(qǐng)求(request)生成,為 I/O 分配一個(gè) request 結(jié)構(gòu)體。
- M?: back merge 之前已經(jīng)存在的 I/O request 的終止 block 號(hào),和該 I/O 的起始 block 號(hào)一致,就會(huì)合并,也就是向后合并。
- F?: front merge 之前已經(jīng)存在的 I/O request 的起始 block 號(hào),和該 I/O 的終止 block 號(hào)一致,就會(huì)合并,也就是向前合并。
- I?: inserted I/O 請(qǐng)求被插入到 I/O scheduler 隊(duì)列。
- S?: sleep 沒有可用的 request 結(jié)構(gòu)體,也就是 I/O 滿了,只能等待有 request 結(jié)構(gòu)體完成釋放。
- P?: plug 當(dāng)一個(gè) I/O 入隊(duì)一個(gè)空隊(duì)列時(shí),Linux 會(huì)鎖住這個(gè)隊(duì)列,不處理該 I/O,這樣做是為了等待一會(huì),看有沒有新的 I/O 進(jìn)來,可以合并。
- U?: unplug 當(dāng)隊(duì)列中已經(jīng)有 I/O request 時(shí),會(huì)放開這個(gè)隊(duì)列,準(zhǔn)備向磁盤驅(qū)動(dòng)發(fā)送該 I/O。這個(gè)動(dòng)作的觸發(fā)條件是:超時(shí)(plug 的時(shí)候,會(huì)設(shè)置超時(shí)時(shí)間);或者是有一些 I/O 在隊(duì)列中(多于 1 個(gè) I/O)。
- D?: issued I/O 將會(huì)被傳送給磁盤驅(qū)動(dòng)程序處理。
- C?: complete I/O 處理被磁盤處理完成。
這些Event中常見的出現(xiàn)順序如下:
Q – 即將生成 I/O 請(qǐng)求
|
G – I/O 請(qǐng)求生成
|
I – I/O 請(qǐng)求進(jìn)入 I/O Scheduler 隊(duì)列
|
D – I/O 請(qǐng)求進(jìn)入 Driver
|
C – I/O 請(qǐng)求執(zhí)行完畢
由于每個(gè)Event都有出現(xiàn)的時(shí)間戳,根據(jù)這個(gè)時(shí)間戳就可以計(jì)算出 I/O 請(qǐng)求在每個(gè)階段所消耗的時(shí)間,比如從Q事件到C事件的時(shí)間叫Q2C,那么常見階段稱呼如下:
Q------------>G----------------->I----------------------------------->D----------------------------------->C
|-Q time(Q2G)-|-Insert time(G2I)-|------schduler wait time(I2D)-------|--------driver,disk time(D2C)-------|
|------------------------------- await time in iostat output(Q2C) -----------------------------------------|
- Q2G?– 生成 I/O 請(qǐng)求所消耗的時(shí)間,包括 remap 和 split 的時(shí)間;
- G2I?– I/O 請(qǐng)求進(jìn)入 I/O Scheduler 所消耗的時(shí)間,包括 merge 的時(shí)間;
- I2D?– I/O 請(qǐng)求在 I/O Scheduler 中等待的時(shí)間,可以作為 I/O Scheduler 性能的指標(biāo);
- D2C?– I/O 請(qǐng)求在 Driver 和硬件上所消耗的時(shí)間,可以作為硬件性能的指標(biāo);
- Q2C?– 整個(gè) I/O 請(qǐng)求所消耗的時(shí)間(Q2I + G2I + I2D + D2C = Q2C),相當(dāng)于 iostat 的 await。
- Q2Q?– 2個(gè) I/O 請(qǐng)求的間隔時(shí)間。
ok,了解了這些關(guān)鍵概念后,就可以看懂blktrace命令的輸出結(jié)果了,繼續(xù)往下看...
blktrace用法
安裝blktrace
# 安裝blktrace包
$ sudo apt install blktrace
# blktrace依賴debugfs,需要掛載它
$ sudo mount -t debugfs debugfs /sys/kernel/debug
blktrace包安裝后有blktrace、blkparse、btt、blkiomon這4個(gè)命令,其中blktrace負(fù)責(zé)采集I/O事件數(shù)據(jù),blkparse負(fù)責(zé)將每一個(gè)I/O事件數(shù)據(jù)解析為純文本方便閱讀,btt、blkiomon負(fù)責(zé)統(tǒng)計(jì)分析。
實(shí)時(shí)查看
$ sudo blktrace -d /dev/sda -o - | blkparse -i -
8,0 3 1 0.000000000 3064475 A W 367809144 + 8 <- (8,1) 367807096
8,0 3 2 0.000001498 3064475 Q W 367809144 + 8 [kworker/u256:3]
8,0 3 3 0.000013880 3064475 G W 367809144 + 8 [kworker/u256:3]^C
先采集后分析
# 采集io事件數(shù)據(jù)
$ sudo blktrace -d /dev/sda
^C=== sda ===
CPU 0: 477 events, 23 KiB data
CPU 1: 1089 events, 52 KiB data
CPU 2: 216 events, 11 KiB data
CPU 3: 122 events, 6 KiB data
Total: 1904 events (dropped 0), 90 KiB data
# 數(shù)據(jù)保存在sda.blktrace.中,每個(gè)cpu一個(gè)文件
$ ls -l *blktrace*
-rw-r--r-- 1 root root 22928 2022-02-12 16:11:37 sda.blktrace.0
-rw-r--r-- 1 root root 52304 2022-02-12 16:11:37 sda.blktrace.1
-rw-r--r-- 1 root root 10408 2022-02-12 16:11:37 sda.blktrace.2
-rw-r--r-- 1 root root 5864 2022-02-12 16:11:37 sda.blktrace.3
# 查看I/O事件
$ blkparse -i sda
8,0 3 1 0.000000000 3064475 A W 367809144 + 8 <- (8,1) 367807096
8,0 3 2 0.000001498 3064475 Q W 367809144 + 8 [kworker/u256:3]
8,0 3 3 0.000013880 3064475 G W 367809144 + 8 [kworker/u256:3]
8,0 3 4 0.000016012 3064475 P N [kworker/u256:3]
8,0 3 5 0.000025289 3064475 A W 367809136 + 8 <- (8,1) 367807088
8,0 3 6 0.000025867 3064475 Q W 367809136 + 8 [kworker/u256:3]
...
Total (sda):
Reads Queued: 14, 220KiB Writes Queued: 299, 1556KiB
Read Dispatches: 14, 220KiB Write Dispatches: 213, 1556KiB
Reads Requeued: 0 Writes Requeued: 0
Reads Completed: 14, 220KiB Writes Completed: 213, 1556KiB
Read Merges: 0, 0KiB Write Merges: 86, 348KiB
IO unplugs: 34 Timer unplugs: 39
Throughput (R/W): 4KiB/s / 30KiB/s
Events (sda): 1766 entries
Skips: 0 forward (0 - 0.0%)
由于I/O事件通常很多,一個(gè)個(gè)的分析并不容易,因此一般使用btt來進(jìn)行統(tǒng)計(jì)分析。
btt
- 首先需要使用blkparse將blktrace采集到的多個(gè)文件合并為一個(gè),如下:
# 先合并為一個(gè)文件
$ blkparse -i sda -d sda.blktrace.bin
$ ll sda.blktrace.bin
-rw-rw-r-- 1 work work 90K 2022-02-12 16:12:56 sda.blktrace.bin
- 然后使用btt分析sda.blktrace.bin,如下:
$ btt -i sda.blktrace.bin
==================== All Devices ====================
ALL MIN AVG MAX N
--------------- ------------- ------------- ------------- -----------
Q2Q 0.000000410 0.165743313 5.193234517 312
Q2G 0.000000297 0.000169175 0.004261675 227
G2I 0.000000341 0.000023664 0.000284838 225
Q2M 0.000000108 0.000000336 0.000002798 86
I2D 0.000000716 0.000708445 0.003329311 227
M2D 0.000004063 0.000106955 0.000737934 84
D2C 0.000111877 0.000718769 0.004067916 313
Q2C 0.000134521 0.001402772 0.008234969 313
==================== Device Overhead ====================
DEV | Q2G G2I Q2M I2D D2C
---------- | --------- --------- --------- --------- ---------
( 8, 0) | 8.7464% 1.2126% 0.0066% 36.6269% 51.2391%
---------- | --------- --------- --------- --------- ---------
Overall | 8.7464% 1.2126% 0.0066% 36.6269% 51.2391%
==================== Device Merge Information ====================
DEV | #Q #D Ratio | BLKmin BLKavg BLKmax Total
---------- | -------- -------- ------- | -------- -------- -------- --------
( 8, 0) | 313 227 1.4 | 8 15 200 3552
==================== Device Q2Q Seek Information ====================
DEV | NSEEKS MEAN MEDIAN | MODE
---------- | --------------- --------------- --------------- | ---------------
( 8, 0) | 313 24620107.8 0 | 0(94)
---------- | --------------- --------------- --------------- | ---------------
Overall | NSEEKS MEAN MEDIAN | MODE
Average | 313 24620107.8 0 | 0(94)
==================== Device D2D Seek Information ====================
DEV | NSEEKS MEAN MEDIAN | MODE
---------- | --------------- --------------- --------------- | ---------------
( 8, 0) | 227 35300234.0 0 | 0(10) 8
---------- | --------------- --------------- --------------- | ---------------
Overall | NSEEKS MEAN MEDIAN | MODE
Average | 227 35300234.0 0 | 0(10)
...(more)
注意這里面的D2C與Q2C,D2C代表硬盤實(shí)際處理時(shí)間,不包含在I/O隊(duì)列中的等待時(shí)間,而Q2C代表整個(gè)I/O在塊層的處理時(shí)間。
可以看到上面Q2C(IO處理時(shí)間)平均耗時(shí)1.402ms,最大8.234ms,D2C(硬盤處理時(shí)間)平均耗時(shí)0.718ms,最大4.076ms,而旋轉(zhuǎn)磁盤耗時(shí)一般在幾毫秒到十幾毫秒,所以這個(gè)磁盤表現(xiàn)正常,但如果D2C經(jīng)常到100ms以上,則可能磁盤損壞了,需要盡快更換磁盤。
如果要檢測(cè)磁盤情況,還有一些簡(jiǎn)便的工具,如ioping或fio等,如下:
$ ioping .
4 KiB <<< . (ext4 /dev/sda1): request=1 time=307.9 us (warmup)
4 KiB <<< . (ext4 /dev/sda1): request=5 time=818.9 us
4 KiB <<< . (ext4 /dev/sda1): request=6 time=381.2 us
4 KiB <<< . (ext4 /dev/sda1): request=7 time=825.4 us (slow)
4 KiB <<< . (ext4 /dev/sda1): request=8 time=791.7 us
4 KiB <<< . (ext4 /dev/sda1): request=11 time=837.8 us (slow)
4 KiB <<< . (ext4 /dev/sda1): request=12 time=815.6 us
...
^C
--- . (ext4 /dev/sda1) ioping statistics ---
23 requests completed in 17.0 ms, 92 KiB read, 1.35 k iops, 5.28 MiB/s
generated 24 requests in 24.0 s, 96 KiB, 1 iops, 4.00 KiB/s
min/avg/max/mdev = 381.2 us / 739.2 us / 842.7 us / 151.3 us
可以發(fā)現(xiàn)平均響應(yīng)時(shí)間也在739.2us,和上面blktrace的結(jié)果基本一致。
blkiomon
blkiomon也能分析I/O事件,對(duì)設(shè)備/dev/sda的io監(jiān)控120秒,每2秒顯示一次,如下:
$ sudo blktrace /dev/sda -a issue -a complete -w 120 -o - | blkiomon -I 2 -h -
time: Sat Feb 12 16:37:25 2022
device: 8,0
sizes read (bytes): num 0, min -1, max 0, sum 0, squ 0, avg 0.0, var 0.0
sizes write (bytes): num 2, min 4096, max 24576, sum 28672, squ 620756992, avg 14336.0, var 104857600.0
d2c read (usec): num 0, min -1, max 0, sum 0, squ 0, avg 0.0, var 0.0
d2c write (usec): num 2, min 659, max 731, sum 1390, squ 968642, avg 695.0, var 1296.0
throughput read (bytes/msec): num 0, min -1, max 0, sum 0, squ 0, avg 0.0, var 0.0
throughput write (bytes/msec): num 2, min 6215, max 33619, sum 39834, squ 1168863386, avg 19917.0, var 187744804.0
sizes histogram (bytes):
0: 0 1024: 0 2048: 0 4096: 1
8192: 0 16384: 0 32768: 1 65536: 0
131072: 0 262144: 0 524288: 0 1048576: 0
2097152: 0 4194304: 0 8388608: 0 > 8388608: 0
d2c histogram (usec):
0: 0 8: 0 16: 0 32: 0
64: 0 128: 0 256: 0 512: 0
1024: 2 2048: 0 4096: 0 8192: 0
16384: 0 32768: 0 65536: 0 131072: 0
262144: 0 524288: 0 1048576: 0 2097152: 0
4194304: 0 8388608: 0 16777216: 0 33554432: 0
>33554432: 0
bidirectional requests: 0
其它
另外,發(fā)現(xiàn)一大佬基于blkparse寫了一個(gè)shell腳本來分析I/O事件數(shù)據(jù),如下:
========
summary:
========
total number of reads: 1081513
total number of writes: 0
slowest read : 0.032560 second
slowest write: 0.000000 second
reads
> 1ms: 18253
>10ms: 17058
>20ms: 17045
>30ms: 780
writes
> 1ms: 0
>10ms: 0
>20ms: 0
>30ms: 0
block size: Read Count
256: 93756
64: 98084
56: 7475
8: 101218
48: 15889
40: 21693
24: 37787
128: 97382
16: 399850
可以很方便地看到I/O請(qǐng)求耗時(shí)分布、I/O請(qǐng)求大小分布。服務(wù)器使用有疑問可以咨詢創(chuàng)新互聯(lián)客服。
當(dāng)前文章:Linux系統(tǒng)使用blktrace分析io情況
文章網(wǎng)址:http://fisionsoft.com.cn/article/djjhphp.html


咨詢
建站咨詢
