前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >全栈软件测试工程师宝典连载(10)

全栈软件测试工程师宝典连载(10)

作者头像
顾翔
发布2021-02-02 10:58:16
4290
发布2021-02-02 10:58:16
举报
文章被收录于专栏:啄木鸟软件测试

顾老师新书《全栈软件测试工程师宝典》

https://item.m.jd.com/product/10023427978355.html

以前两本书的网上购买地址:

《软件测试技术实战设计、工具及管理》:

https://item.jd.com/34295655089.html

《基于Django的电子商务网站》:

https://item.jd.com/12082665.html

3. 磁盘和文件
1)文件存储结构[29]

Linux的文件存储结构如图3-29所示。

图3-29 Linux的文件结构

索引节点(inode)是持久化存储到磁盘中的,而目录项(dentry)是由内核维护(目录项缓存)的。

在讨论文件存储结构之前需要了解一下扇区(Sector)和块(block),一个扇区为512B,操作系统读取硬盘的时候,不会一个个扇区地去读取,这样效率非常的低,而是一次性连续读取多个扇区,即一次性读取一个“块”(block)。每8个扇区为一个块,块的大小为(512B×8=4098B,即4KB)。文件数据都存储在“块”中,必须找到一个地方存储文件的元信息,比如文件的创建者、文件的创建日期、文件的大小等等。这种储存文件的元信息区域就叫做索引节点(inode)。

①inode的内容

inode包含文件的元信息,具体来说有以下内容。

•文件的字节数。

•文件拥有者的User ID。

•文件的Group ID。

•文件的读、写、执行权限。

•文件的时间戳。

时间戳共有三个。

Øctime指inode上一次变动的时间。

Ømtime指文件内容上一次变动的时间。

Øatime指文件上一次打开的时间。

•链接数,即有多少文件名指向当前inode。

•文件数据block的位置。

可以用stat命令,查看某个文件的inode信息。

代码语言:javascript
复制
# stat runserver.bat
File: runserver.bat
Size: 52       Blocks: 8          io Block:4096   regular file
Device: 801h/2049d Inode: 554863      Links: 1
Access: (0777/-rwxrwxrwx)  stat runserver.bat
Access: 2019-12-06 01:38:13.895735646 -0800
Modify: 2019-01-30 01:40:25.009354932 -0800
Change: 2019-01-30 01:40:25.021354285 -0800
Birth: -
②inode的大小

由于inode也要消耗硬盘,所以硬盘格式化的时候,操作系统会自动把硬盘分成两个区域:数据区,用于存放文件数据inode区(inode table),用于存放inode信息。

作为一个单独的inode节点,一般是128个字节或者256个字节。inode节点的总数,在格式化的时就给定了,一般是每1KB或每2KB设置一个inode节点。假定2GB的硬盘中,每个inode节点的大小为128个字节,每1KB设置一个inode节点,这样inode table的大小就会达到256MB,占整块硬盘的12.8%。

可以通过df -i命令来查看每个硬盘分区的inode总数和已经使用的数量。

代码语言:javascript
复制
# df -i
Filesystem     Inodes    IUsed  IFree     IUse%Mounted on
udev            531381    493     530888   1%     /dev
tmpfs           539081    1016    538065   1%     /run
/dev/sda1      1310720   364285 946435     28%  /
tmpfs           539081      1      539080   1%     /dev/shm
tmpfs           539081      5      539076   1%     /run/lock
tmpfs           539081     18      539063   1%     /sys/fs/cgroup
/dev/loop0     354        354      0        100%   /snap/gnome-logs/81
/dev/loop1      25385    25385    0        100%    /snap/gtk-common-themes/1198
…

还可以利用df来查看某个Filesystem磁盘详细情况。

代码语言:javascript
复制
# df /dev/sda1
Filesystem    1K-blocks  Used Available Use%Mounted on
udev           373728      124  373604    1%      /dev

使用-h参数更便于阅读。

代码语言:javascript
复制
# df -h /dev/sda1
Filesystem     Size      Used  Avail   Use% Mounted on
udev            365M      124K 365M     1%     /dev

df如果不加-i参数,不会统计inode大小的。有时候剩余空间很充足,但是系统提示磁盘空间不足,可以确定是否索引过大需要占的磁盘空间,需要通过df -i来查看。

③ 目录项

目录项(dentry)是用来记录文件的名字、索引节点指针以及与其他目录项的关联关系。多个关联的目录项,就构成了文件系统的目录结构。

2)虚拟文件系统 VFS(Virtual File System)

在Windows95、Windows98中使用的是FAT格式的文件系统,到WindowNT以后Window改用NTFS文件格式。在Linux中文件格式就多了,包括。

•基于磁盘的文件系统。Ext4、XFS、OverlayFS等。

•基于内存的文件系统(虚拟文件系统)。不需要任何磁盘分配存储空间,但会占用内存。比如:/proc 、/sys。

•基于网络文件系统。NFS、SMB、iSCSI 等。

为了兼容以上各种不同的文件格式,Linux提出虚拟文件系统 VFS的概念,Viritual Filesystem给用户空间程序提供统一的文件和文件系统访问接口的内核子系统。借助VFS,即使文件系统的类型不同,也可以实现文件系统之间的交互,比如:移动、复制等。VFS所处位置如图3-30所示。

图3-30 Viritual File system所处位置

3)Linux I/O分类

Linux I/O分类请参见表3-12所示,

表3-12 Linux I/O分类

分类标准

分类名

解释

缩写

是否利用操作系统的页缓存

直接I/O

读写操作<—>文件系统来访问文件

非直接I/O

读写操作<—>系统的页缓存<—>写入磁盘

是否等待响应结果

裸I/O

跳过文件系统,直接访问磁盘

O_DIRECT

同步I/O

等到整个I/O完成后才获得I/O响应

O_SYNC

异步I/O

不用等待完成和完成后的响应,完成后以通知的方式告知

O_ASYNC

是否利用标准库缓存

缓冲I/O

用标准库(数据<—>流缓存区<—>内核缓存区<—>磁盘)

Buffered I/O

非缓冲I/O

不用标准库(数据<—>内核缓存区<—>磁盘)

NoBuffered I/O

是否阻塞自身的运行

阻塞I/O

没有获得响应,就会阻塞当前的进程

O_BLOCK

非阻塞I/O

没有获得响应,不会阻塞当前的进程,通过轮询

O_NONBLOCK

下面对这几种分类。

•缓冲I/O。

缓冲I/O是指通过标准库缓存来加速文件的访问,而标准库内部再通过系统调度访问文件。带缓存I/O也叫标准I/O,它符合ANSI C的标准I/O处理,是不依赖系统内核的,所以移植性是比较强的,在使用标准I/O操作的时候为了减少对read()、write()系统调用次数,带缓存I/O就是在用户层再建立一个缓存区,这个缓存区的分配和优化长度等细节都是标准I/O库处理好的,用户不用去关心。

•非缓冲 I/O。

非缓冲 I/O是指直接通过系统调用来访问文件,不再经过标准库缓存。它不是直接对磁盘文件进行读取操作,比如read()、write()函数,都属于系统调用,在用户层是没有缓存的,所以称作无缓存I/O。但对于内核而言,还是进行了缓存,只是用户层看不到。

•阻塞I/O。

阻塞I/O进程发起请求后,如果内核没有准备好数据,进程就会被block住,进入等待阶段,一旦等待内核将数据准备好,返回数据,解除阻塞。

•非阻塞I/O。

非阻塞I/O进程发起请求后,如果内核没有准备好数据,直接返回一个error信息,进程不需要阻塞等待,然后进程会轮询发送请求,如此往复,一直等到内核准备好数据,才把数据拷贝并返回给进程,结束到此轮询。非阻塞I/O只有是检查无数据的时候是非阻塞的,在数据到达的时候依然要等待复制数据到用户空间。

非阻塞又分为异步非阻塞(I/O复用)和异步非阻塞(信号驱动式I/O)。

Ø异步非阻塞(I/O复用)。

异步非阻塞(I/O复用)由Linux提供select/poll,进程通过将一个或多个fd传递给select或poll系统调用,阻塞在select;这样select/poll可以帮助侦测多个fd是否就绪。但是select/poll是顺序扫描fd是否就绪,并且支持的fd数量是有限的。Linux还提供了一个epoll系统调用,epoll是基于事件驱动方式的,而不是顺序扫描,当有fd就绪时,立即调用函数rollback。

Ø异步非阻塞(信号驱动式I/O)。

异步非阻塞(信号驱动式I/O)是指在内核在描述符就绪时发送SIGIO信号通知进程,进程通过信号处理函数接收数据。

•同步I/O。

同步I/O是指I/O请求导致请求进程阻塞,直到I/O操作完成。阻塞I/O模型、非阻塞I/O模型、异步非阻塞(I/O复用)、异步非阻塞(信号驱动式I/O)都属于同步I/O

•异步I/O。

异步I/O进程是指I/O请求发生,发起请求,内核数据已经准备好,并且复制到用户进程空间后执行事先指定好的函数。异步I/O不会导致请求进程阻塞。只有异步I/O模型是才是真正意义上的非阻塞I/O。

•裸I/O。

裸I/O是指不通过文件系统,直接访问磁盘。

•直接 I/O。

直接 I/O是指不通过操作系统的页缓存,直接跟文件系统的交互来访问文件。

•非直接 I/O。

非直接 I/O是指文件读写的时候,先要经过系统的页缓存,然后再由内核或额外的系统调用,真正写入磁盘。

4)磁盘的性能指标

Linux的磁盘性能指标包括以下内容。

使用率。

是指磁盘处理 I/O 的时间百分比。过高的使用率(比如超过 80%),通常意味着磁盘 I/O 存在性能瓶颈。

•饱和度。

是指磁盘处理 I/O 的繁忙程度。过高的饱和度,意味着磁盘存在严重的性能瓶颈。当饱和度为 100% 时,磁盘无法接受新的 I/O 请求。

•IOPS。(Input/Output Per Second)。

是指每秒的 I/O 请求数。多用于数据库、大量小文件等这类随机读写。

•吞吐率。

是指每秒的 I/O 请求大小。多用于多媒体等顺序读写。

•响应时间。

是指 I/O 请求从发出到收到响应的间隔时间。

① 磁盘操作活动进行监视

对系统的磁盘操作活动进行监视需要使用iostat工具(需要安装sysstat插件)。它的特点是汇报磁盘活动统计情况,同时也会汇报出CPU使用情况。iostat指标实际上来自/proc/diskstats。经常结合-x -d参数使用,表示显示所有磁盘的I/O的指标。

代码语言:javascript
复制
# iostat -d -x 1
Linux 4.15.0-66-generic (ubuntu) 12/10/2019_x86_64_(4 CPU)

Device           r/s     w/s     rkB/s    wkB/s   rrqm/s   wrqm/s %rrqm  %wrqm r_await w_awaitaqu-sz rareq-sz wareq-sz  svctm  %util
loop0           0.00    0.00      0.00     0.00     0.00     0.00  0.00   0.00    2.80   0.00   0.00     2.35    0.00   0.00   0.00
loop1           0.01    0.00      0.02     0.00     0.00     0.00  0.00   0.00    1.08   0.00   0.00     1.80    0.00   0.08   0.00
loop2           0.00    0.00      0.00     0.00     0.00     0.00  0.00   0.00    5.37   0.00   0.00     2.76    0.00   0.00   0.00
loop3           0.00    0.00      0.00     0.00     0.00     0.00  0.00   0.00    4.60   0.00   0.00     2.42    0.00   0.08   0.00
loop4           0.01    0.00      0.08     0.00     0.00     0.00  0.00   0.00    2.28   0.00   0.00     7.57    0.00   0.36   0.00
loop5           0.42    0.00      0.46     0.00     0.00     0.00  0.00   0.00    0.54   0.00   0.00     1.11    0.00   0.02   0.00
loop6           0.02    0.00      0.03     0.00     0.00     0.00  0.00   0.00    0.44   0.00   0.00     1.59    0.00   0.04   0.00
loop7           0.00    0.00      0.00     0.00     0.00     0.00  0.00   0.00    5.17   0.00   0.00     2.83    0.00   0.00   0.00

其中参数解读如表3-13所示。

表3-13 iostat参数

性能指标

含义

注释

r/s

每秒发送给磁盘的读请求数

合并后的请求数

w/s

每秒发送给磁盘的写请求数

合并后的请求数

rkB/s

每秒从磁盘读取的数量

单位(kB)

wkB/s

每秒从磁盘写入的数量

单位(kB)

rrqm/s

每秒合并的读请求数

%rrqm表示合并的读请求数的百分比

wrqm/s

每秒合并的写请求数

%wrqm表示合并的写请求数的百分比

r_await

读请求处理完成的等待时间

包括队列中的等待时间和设备实际处理的时间,单位(毫秒)

w_await

写请求处理完成的等待时间

包括队列中的等待时间和设备实际处理的时间,单位(毫秒)

apu-sz

平均请求队列的长度

旧版中为angqu-sz

rareq-sz

平均读请求大小

单位(kB)

wareq-sz

平均写请求大小

单位(kB)

svctm

处理I/O请求所需要的平均时间

不包含等待时间,单位(毫秒),估算值,不保证完全准确

%util

磁盘处理I/O的时间百分比

即使用率,由于并行I/O的存在,100%不一定表明磁盘I/O饱和

在这里,对应上面提到的性能指标与这里的参数如下。

•IOPS 。即r/s+ w/s。

•吞吐量。即rkB/s+wkB/s。

•响应时间。r_await+w_await。

•使用率。%util。

代码语言:javascript
复制
iostat
Linux 4.15.0-66-generic (ubuntu) 12/10/2019 _x86_64_(4CPU)

avg-cpu: %user   %nice %system %iowait  %steal  %idle
0.93    0.25   0.72    0.07     0.00     98.03

Device             tps    kB_read/s   kB_wrtn/s    kB_read    kB_wrtn
loop0            0.00         0.00         0.00        47          0
…

•如果%iowait的值过高,表示硬盘存在I/O瓶颈。

•如果%idle值高但系统响应慢时,可能是CPU等待分配内存,应加大内存容量。

•如果%idle值持续低于10,表明CPU处理能力相对较低,系统中最需要解决的资源是CPU。

•%util接近100%,说明产生的I/O请求太多,I/O系统已经满负荷。

② 查看inode和目录项缓存

[28]slab是Linux操作系统的一种内存分配机制,slab分配算法采用cache存储内核对象。slab缓存、从缓存中分配和释放对象然后销毁缓存的过程必须要定义一个kmem_cache对象,然后对其进行初始化这个特定的缓存包含32字节的对象。可以通过运行cat /proc/slabinfo |grep -E '^#|dentry|inode'命令来查看所有目录项和各种文件系统索引节点的缓存情况。

代码语言:javascript
复制
#  cat/proc/slabinfo | grep -E '^#|dentry|inode'
# name           <active_objs> <num_objs> <objsize> <objperslab><pagesperslab> : tunables <limit> <batchcount><sharedfactor> : slabdata <active_slabs> <num_slabs><sharedavail>
btrfs_inode            0      0  1144   28    8 : tunables    0   0    0 : slabdata      0     0      0
ufs_inode_cache        0     0    808  40    8 : tunables    0   0    0 : slabdata      0     0      0
qnx4_inode_cache       0     0    680   48   8 : tunables    0    0   0 : slabdata      0      0     0
hfs_inode_cache        0     0    832   39   8 : tunables    0    0   0 : slabdata      0      0     0
minix_inode_cache      0     0    672   48   8 : tunables    0    0   0 : slabdata      0      0     0
ntfs_big_inode_cache      0     0    960   34   8 : tunables    0    0   0 : slabdata      0      0     0
ntfs_inode_cache       0     0    296   55   4 : tunables    0    0   0 : slabdata      0      0     0
xfs_inode              0      0   960   34    8 : tunables    0   0    0 : slabdata      0     0      0
mqueue_inode_cache     34    34    960   34   8 : tunables    0    0   0 : slabdata      1      1     0
fuse_inode           117    117   832   39    8 : tunables    0   0    0 : slabdata      3     3      0
ecryptfs_inode_cache      0     0   1024   32   8 : tunables    0    0   0 : slabdata      0      0     0
fat_inode_cache        0     0    744   44   8 : tunables    0    0   0 : slabdata      0      0     0
squashfs_inode_cache  22954 22954    704   46   8 : tunables    0    0   0 : slabdata    499    499     0
ext4_inode_cache 105930 105930   1088   30   8 : tunables    0    0   0 : slabdata   3531   3531     0
hugetlbfs_inode_cache    104   104    624   52   8 : tunables    0    0   0 : slabdata      2      2     0
sock_inode_cache    2313  2484    704   46   8 : tunables    0    0   0 : slabdata     54     54     0
shmem_inode_cache   1840  1840    712   46   8 : tunables    0    0   0 : slabdata     40     40     0
proc_inode_cache    7315 10944    680   48   8 : tunables    0    0   0 : slabdata    228    228     0
inode_cache        40236 40439    608   53   8 : tunables    0    0   0 : slabdata    763    763     0
dentry           214030 214242    192   42   2 : tunables    0    0   0 : slabdata   5101   5101     0

其中dentry行表示目录项缓存,inode_cache行表示VFS索引节点缓存,而其他的是各种文件系统的索引节点缓存。除了使用slabinfo命令查看slab信息,也可以使用slabtop命令来查看。

代码语言:javascript
复制
# slabtop
Active / Total Objects (% used)   : 539715 / 542626 (99.5%)
Active /Total Slabs (% used)      : 11100 / 11100(100.0%)
Active /Total Caches (% used)     : 81 / 109(74.3%)
Active /Total Size (% used)       : 142659.64K /143801.37K (99.2%)
Minimum /Average / Maximum Object : 0.01K / 0.26K / 8.00K

OBJS ACTIVE USE OBJ SIZE  SLABS OBJ/SLAB CACHESIZE NAME                   
444405 4422740%  0.10K  11395     39    45580K buffer_head
155820 1444690%  0.19K   3710      42     29680K dentry
70230 691050%   1.06K   2341     30    74912K ext4_inode_cache
60900 60900100% 0.13K   1015      60     8120K kernfs_node_cache
…
40439     40286    0%    0.59K   763        53        24416K          inode_cache
…

在这里,目录项(dentry)占用了29680K的Cache,inode(inode_cache)的Cache为24416K。

③ 查看进程的I/O

查看进程的I/O情况,使用pidstat -d参数。

代码语言:javascript
复制
#pidstat -d 1
Average:     UID       PID      kB_rd/s  kB_wr/s kB_ccwr/s iodelay  Command
Average:     0         331       0.00      0.57     0.00           2    jbd2/sda1-8
Average:     0         6353     0.00      3066.10   0.00         0      snapd

其中参数含义如下。

•UID/PID。

用户ID/进程ID。

•kB_rd/s。

每秒读取的数据大小,单位是 KB。

•kB_wr/s。

每秒写请求数据大小,单位是 KB。

•kB_ccwr/s。

每秒取消的写请求数据大小,单位是 KB。

•块 I/O 延迟(iodelay)。

包括等待同步块 I/O 和换入块 I/O 结束的时间,单位是时钟周期。

③ 磁盘top工具

iotop命令是一个用来监视磁盘I/O使用状况的top类工具。使用iotop需要在unbutu下另行安装,命令为apt-get install iotop。图3-31为iotop的执行情况。

图3-31 iotop命令

扩展阅读:磁盘分类按照存储介质来分,磁盘可以分为机械磁盘与固态磁盘。•机械磁盘(Hard Disk Driver:HDD):机械磁盘是根据磁头寻道和盘片旋转而获取数据的,最小读写单位是扇区,每个扇区为512B。•固态磁盘(Solid State Disk:SSD):固态磁盘采取“先擦除再写入”的原则,速度比机械抽盘快,但是会产生大量的垃圾。最小读写单位是页,通常大小是4KB、8KB等。不管是机械磁盘还是固态磁盘,离散的数据读写比性能连续的要低。按照接口来分类,可以把硬盘分为。•IDE(Integrated Drive Electronics):前缀为hd。•SCSI(Small Computer System Interface):前缀为sd。•SAS(Serial Attached SCSI)。•SATA(Serial ATA):前缀为sd。•FC(Fibre Channel)。多块同类型的磁盘,可以按照 a、b、c…的字母顺序来编号/dev/sda、/dev/sdb。还可以划分为不同的逻辑分区,每个分区再用数字进行编号。比如/dev/sda,可以分成/dev/sda1和/dev/sda2 2个分区。另外也可以把多块磁盘组合成一个逻辑磁盘,构成冗余独立磁盘阵列,也就是 RAID(Redundant Array of Independent Disks),从而可以提高数据访问的性能,并且增强数据存储的可靠性。具体细节可以参考3.2.1-3里面的介绍。

5)案例
案例3-13:狂打日志造成的性能下降
代码语言:javascript
复制
# top
top - 09:29:06 up 3 day,  1:39,  4users,  load average: 2.48, 1.12, 0.47
Tasks: 130 total,   2 running, 74 sleeping,   0 stopped,   0 zombie
%Cpu0 :  0.7 us,  6.5 sy,  0.0 ni,  0.7 id, 93.8 wa,  0.0 hi, 0.0 si,  0.0 st
KiB Mem : 8169308 total,   747684 free,   741336 used, 6680288 buff/cache
KiB Swap:       0 total,        0 free,        0used.  7113124 avail Mem

PID   USER    PR  NI   VIRT     RES    SHR   S   %CPU    %MEM     TIME+ COMMAND
16520  jerry   20 0     656108  355740 5236 R    7.2      4.4      0:12.56 python3
…

由于内核CPU为sy 6.5%并不是很高,而等待I/O的CPU时间为93.8%是比较高的,另外在进程信息中心可以看到Python3的进程CPU占有率为7.2%,也是比较高的,它的PID为16520。可以定位在I/O上出现了瓶颈,可能是Python3引起的。于是用iostat来分析。

代码语言:javascript
复制
# iostat -x -d 1
Device r/s   w/s  rkB/s wkB/s   rrqm/s  wrqm/s %rrqm %wrqm r_await w_await aqu-szrareq-sz wareq-sz  svctm  %util
loop0   0.00 0.00    0.00   0.00 0.00  0.00  0.00 0.00  0.00  0.00 0.00  0.00  0.00 0.00     0.00
sdb     0.00 0.00    0.00   0.00   0.00 0.00 0.00  0.00   0.000.00  0.00  0.00 0.00  0.00    0.00
sda     0.00  67.00   0.00   32768.00    0.00        0.00       0.00 0.00   0.00  9320.58 1236.57 0.00        512.00     15.50 99.18

可以看到磁盘sda的I/O使用率已经高达99.18%,已经接近了I/O的饱和状态。每秒写磁盘请求数是67.00,写数据大小是32768.00(32 MB),写请求的响应时间为(9320.58 ms),也就是9s,而请求队列长度则达到了1236.57。进一步确认了性能瓶颈在I/O。接下来用pidstat来分析。

代码语言:javascript
复制
# pidstat -d 1
Linux 4.15.0-66-generic (ubuntu) 12/10/2019_x86_64_(4 CPU)

09:30:06 AM  UID    PID     kB_rd/s  kB_wr/s kB_ccwr/s iodelay  Command
09:30:07 AM  0      759     11.21     0.00      0.00       0       polkitd
09:30:07 AM  0      16520   0.00      58100.00 0.00       96       python3
09:30:07 AM  1000   2044   1465.42   0.00      0.00       0       gnome-shell
…

可以发现PID为16520的Python3进程正以58100.00 kB/s的速度往系统中写数据。使用strace -p <PID>查询这个进程的详情。

代码语言:javascript
复制
# strace -p 116520
strace: Process 16520 attached
...
mmap(NULL, 419430458, PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x8d5a96754ab0
mmap(NULL, 419430458, PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x8d5a8583a5de
write(5, "2019-12-05 09:30:08,709 - __main"..., 419430458 ) = 419430458
munmap(0x8d5a8583a5de, 419430458)       = 0
write(5, "\n", 1)                       = 1
munmap(0x8d5a8583b5de, 419430458)       = 0
close(3)                                = 0
stat("/tmp/mylog.txt.3",{st_mode=S_IFREG|0644, st_size=96384178, ...}) = 0
…

进程向文件描述符编号为5号的文件中,写入了400MB的数据,该5号文件为: /tmp/logtest.txt.3。

代码语言:javascript
复制
lsof -p 116520
…
COMMAND PID  USER    FD  TYPE DEVICE SIZE/OFF          NODENAME
python3 3785 jerry  cwd  DIR   8,1    4096 554601      /home/ebusiness
…
python3 3785 jerry   5w   REG   8,1   117944320  303   /tmp/mylog.txt.3

这里的5W表示5号文件以写的形式打开。这样就可以分析Python文件来定位问题了。

案例3-14:数据库没有建立有效的索引造成的性能下降
代码语言:javascript
复制
# top
top - 22:06:25 up  9:22, 1 user,  load average: 4.94, 2.05,1.09
Tasks: 316 total,   1 running, 236 sleeping,   0 stopped,  0 zombie
%Cpu0 :  0.7 us,  1.3 sy, 0.0 ni, 35.9 id, 74.4 wa,  0.0 hi,  0.0 si, 0.0 st
%Cpu1 :  0.3 us,  0.7 sy, 0.0 ni, 73.7 id, 20.8 wa,  0.0 hi,  0.0 si, 0.0 st
KiB Mem : 4312648 total,   161796 free,  1820392 used, 2330460 buff/cache
KiB Swap:  969960 total,   963816 free,     6144 used. 2182356 avail Mem

PID   USER    PR NI VIRT     RES     SHR   S  %CPU   %MEM    TIME+    COMMAND
7458 jerry   20  0  833852  57968   13176S   1.7   0.7     0:12.40   mysqld                                                                                                         
3785 jerry   20  0  6171324 100048  10624 S 103.6  2.3     45:11.62  python3                                                                                                                               
1915 jerry   20  0  469516  71432   26120 S  24.1  1.7     3:30.36   Xorg
…

CPU0和CPU1的等待I/O的CPU时间分别为74.4%和20.8%,是比较高的。同样用iostat分析。

代码语言:javascript
复制
iostat -d -x 1
Device r/s       w/s     rkB/s         wkB/s rrqm/s  wrqm/s  %rrqm %wrqm r_await w_await aqu-sz rareq-sz wareq-sz  svctm %util
sda   273.00   0.00  43963.00  0.00   0.00  0.00  0.00  0.00  7.90   0.00  1.16 119.30   0.00  3.56  97.20

磁盘sda的I/O使用率高达97.20%。每秒读磁盘请求数是273.00,读数据的大小是43963.00。再利用pidstat分析。

代码语言:javascript
复制
#pidstat -w 1
22:06:26   UID   PID    kB_rd/s   kB_wr/s kB_ccwr/s iodelay  Command
22:06:26   999   27458  43963.00  0.00     0.00          0        mysqld
22:06:26   0     27617  4.00     4.00     0.00           3       python3
…

可以得知数据库mysql读操作造成的性能瓶颈。需要进入数据库内部来分析具体原因。

代码语言:javascript
复制
# mysql
Type 'help;' or '\h' for help. Type '\c' toclear the current input statement.
mysql> showfull processlist;
+----+------+-----------------+------+---------+------+--------------+-----------------------------------------------------+
| Id | User | Host            | db   | Command | Time | State        | Info                                               |
+----+------+-----------------+------+---------+------+--------------+-----------------------------------------------------+
| 15 | root | localhost       | sec | Query   |    0| init         | show fullprocesslist                              |
| 16 | root | 127.0.0.1:42262| sec | Query   |    1| Sending data | select * from website where Name= '3testing' |
+----+------+-----------------+------+---------+------+--------------+-----------------------------------------------------+

•db。

表示数据库的名字。

•Command。

表示SQL类型(Query、Update、Insert、Delete)。

•Time。

表示执行时长。

•State。

表示状态。

•Info。

则包含了完整的SQL语句。

接下来切换到数据库sec中,执行explain命令,分析查询语句。

代码语言:javascript
复制
mysql> use sec
mysql> explain elect * from website whereName= '3testing';
+----+-------------+----------+------+---------------+------+---------+------+-------+-------------+
| id | select_type | table    | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+----------+------+---------------+------+---------+------+-------+-------------+
|  1 |SIMPLE      | website | ALL  | NULL          | NULL | NULL    | NULL | 15000 | Using where |
+----+-------------+----------+------+---------------+------+---------+------+-------+-------------+
1 row in set (0.00 sec)

从而发现type为ALL,即全表查询,即没有建立索引且牵扯到15000个记录,这里各项含义为。

•select_type。

表示查询类型,SIMPLE表示此查询不包括UNION查询或者子查询。

•table。

表示数据表的名字。

•type。

表示查询类型, ALL表示全表查询,索引查询为index类型。

•possible_keys。

表示可能选用的索引,这里NULL表示没有索引。

•key。

表示索引关键字。

•rows。

表示查询扫描的行数。

6)小结

本节所涉及的概念有文件储结构(包括索引节点和目录项)、虚拟文件系统 VFS、Linux I/O分类和磁盘的性能指标。涉及到的命令有stat、 df、iostat、 cat /proc/slabinfo、slabtop、pidstat和iotop。

—————————————————————————————————

顾老师课程欢迎报名

软件安全测试

https://study.163.com/course/courseMain.htm?courseId=1209779852&share=2&shareId=480000002205486

接口自动化测试

https://study.163.com/course/courseMain.htm?courseId=1209794815&share=2&shareId=480000002205486

DevOps 和Jenkins之DevOps

https://study.163.com/course/courseMain.htm?courseId=1209817844&share=2&shareId=480000002205486

DevOps与Jenkins 2.0之Jenkins

https://study.163.com/course/courseMain.htm?courseId=1209819843&share=2&shareId=480000002205486

Selenium自动化测试

https://study.163.com/course/courseMain.htm?courseId=1209835807&share=2&shareId=480000002205486

性能测试第1季:性能测试基础知识

https://study.163.com/course/courseMain.htm?courseId=1209852815&share=2&shareId=480000002205486

性能测试第2季:LoadRunner12使用

https://study.163.com/course/courseMain.htm?courseId=1209980013&share=2&shareId=480000002205486

性能测试第3季:JMeter工具使用

https://study.163.com/course/courseMain.htm?courseId=1209903814&share=2&shareId=480000002205486

性能测试第4季:监控与调优

https://study.163.com/course/courseMain.htm?courseId=1209959801&share=2&shareId=480000002205486

Django入门

https://study.163.com/course/courseMain.htm?courseId=1210020806&share=2&shareId=480000002205486

啄木鸟顾老师漫谈软件测试

https://study.163.com/course/courseMain.htm?courseId=1209958326&share=2&shareId=480000002205486

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-01-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 软件测试培训 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 3. 磁盘和文件
    • 1)文件存储结构[29]
      • ①inode的内容
      • ②inode的大小
      • ③ 目录项
    • 2)虚拟文件系统 VFS(Virtual File System)
      • 3)Linux I/O分类
        • 4)磁盘的性能指标
          • ① 磁盘操作活动进行监视
          • ② 查看inode和目录项缓存
          • ③ 查看进程的I/O
          • ③ 磁盘top工具
        • 5)案例
          • 案例3-13:狂打日志造成的性能下降
            • 案例3-14:数据库没有建立有效的索引造成的性能下降
              • 6)小结
              相关产品与服务
              文件存储
              文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档