监控io性能(磁盘性能监控)

在日常运维的工作中,我们不仅要关注cpu,内存之外,磁盘的io也是重要指标之一。有时候cpu和内存都有剩余,但是系统的负载还是很高,用vmstat查看发现b列或者wa列比较大,那说明系统磁盘有瓶颈,那我们就要更详细的去查看磁盘的状态。

我们可以用iostat -x来看硬盘的状态,这里面有一个非常重要的选项,%util

^C [root@localhost ~]# iostat -x 1 3 Linux 3.10.0-693.el7.x86_64 (localhost.localdomain) 2018年03月07日 x86_64 (1 CPU)

avg-cpu: %user %nice %system %iowait %steal %idle 0.14 0.00 0.28 0.25 0.00 99.32

Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util sda 0.00 0.10 0.95 0.42 35.04 10.54 66.73 0.05 40.20 12.07 103.35 4.07 0.56

这个指标首先是一个百分比,它的含义是io等待,磁盘使用有多少时间占用cpu的,那我们的cup有一部分时间是交给进程进行处理的,计算的,那也有一部分是等待磁盘读写的,磁盘要读写数据,cpu是需要时间等待的,那么的时间比就是%util。
如果这个百分比很大,已经达到了50%~60%,这说明磁盘io很差了,说明它非常的忙,这个数值很大,说明磁盘的读(rkB/s)和写(wkB/s)这两列也很大,如果这两列不大,但是%util很大,就说明我们的硬盘有问题,有些故障,如果硬盘很慢,肯定会影响系统的性能。 

如果我们发现磁盘io很忙,我很想知道是哪一个进程在频繁读写呢?这时候我们输入命令iotop,如果没有这条命令,那我们就直接安装iotop。

这条命令和top命令相似,也是动态显示 [root@localhost ~]# iotop

Total DISK READ : 0.00 B/s | Total DISK WRITE : 0.00 B/s Actual DISK READ: 0.00 B/s | Actual DISK WRITE: 0.00 B/s TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND
1715 be/4 root 0.00 B/s 0.00 B/s 0.00 % 0.02 % [kworker/0:1] 1 be/4 root 0.00 B/s 0.00 B/s 0.00 % 0.00 % systemd --switched-root --system --deserialize 21 2 be/4 root 0.00 B/s 0.00 B/s 0.00 % 0.00 % [kthreadd] 在io列中,排位靠前的就是使用io频繁的进程。

free:查看内存使用情况的命令 [root@localhost ~]# free -h total used free shared buff/cache available Mem: 988M 130M 715M 6.7M 142M 700M Swap: 2.0G 0B 2.0G 它是由三行组成,第一行是说明。第二行是内存使用情况,第三行是交换分区使用情况。我们也可以使用参数-h,给他加上合适的单位。我们关注的是第二行,内存的使用情况。 第一列 total内存总大小。 第二列 used:使用了多少。 第三列 free:空闲了多少。 第四列 shared:共享了多少。 第五列 buff/cache :缓冲和缓存。 这里有一个问题,我们的used(使用)和free(空闲)之和不等于total(总和),这是为什么呢?这是因为linux系统他会把你的内存先预分配一部分出来给buff(缓冲)/cache(缓存),这两个词看似相近,但是他俩是不同的概念。

cache:我们现在有一个数据,要从磁盘中读出来,交给cpu去运算,磁盘到cpu要经过内存,由于磁盘和cpu的速度差距很大,所以我们中间有一个内存设备,为了就是让这两者的速度有一个缓和,所以中间要经过一个内存到cpu,这个内存就是cache。         磁盘-->内存(cache)-->cpu

buff:cpu将数据计算完后要想把它存到磁盘中去,由于cpu速度快而磁盘速度慢,入股想直接写到磁盘中去速度会很慢,这样会拖慢cpu的工作效率,所以cpu就先将数据放到内存中去(buff),然后再放入磁盘中去。                                                         cpu-->内存(buff)-->磁盘

第六列 available:可得到的剩余物理内存。它是free和buff/cache 剩余部分之和。我们真正要查看的就是这项。

ps:监控系统状态 ps aux:静态的列出系统所以进程 [root@localhost ~]# ps aux |head -4 USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.6 128164 6820 ? Ss 20:34 0:02 /usr/lib/systemd/systemd --switched-root --system --deserialize root 2 0.0 0.0 0 0 ? S 20:34 0:00 [kthreadd] root 3 0.0 0.0 0 0 ? S 20:34 0:00 [ksoftirqd/0]

第一列 user:进程的运行用户 第二列 pid:进程id。这个在我们杀死进程的时候可以用到,kill+pid。 第三列 %CPU:cpu百分比 第四列 %MEM :内存百分比 第五列 VSZ:虚拟内存 第六列 RSS :物理内存 第七列 TTY:在哪个TTY上。 第八列 STAT:进程状态。这也是我们需要关注的一项。 进程的状态有如下几种: D :不能中断的进程,这样会造成系统负载很高,这说明D进程会不断使用cpu。这个很少见。 R:正在跑的进程。 S:休眠的进程,但是有一种情况,一个程序正在运行,但是我们查看的时候他还在处S的状态,这时因为他虽然在运行,但是不是不停的运行、而是某一个时刻抓一下,所以他占用cpu的时间很短,它运行完的会后就处于S的状态,这种进程基本不会耗费cpu的资源。 S+:前台进程。 T:暂停的进程。 [root@localhost ~]# ps aux |grep vmstat root 1501 0.0 0.1 148316 1348 pts/0 T 23:08 0:00 vmstat 1 这就说明进程被暂停了,这时候他就没有在运行。 Z:僵尸进程。如果有僵尸进程,我们就要想办法杀死它。 <:高优先级进程。cpu优先运行这个进程。 N:低优先级进程。cpu会延后运行这个进程。 L:内存中被锁了内存分页的。 s:主进程。 |:多线程进程。

第九列 START:什么时候启动的 第十列 TIME:启动多久了 第十一列COMMAND:命令

如果我们想产看系统中某一个程序是否运行,可以用管道符加grep,比如我们先要看nginx这个程序是否运行 [root@localhost ~]# ps aux |grep nginx root 1462 0.0 0.0 112676 984 pts/0 R+ 22:47 0:00 grep --color=auto nginx 这样就可以实现了。

netstat:查看网络状态 linux作为服务器的一种操作系统,这个服务器会有很多的服务,服务他往往是和客户端相互通信的,所以也就意味着他有监听端口,要有对外通信端口,netstat这个命令就是监听TCP/IP通信的状态,比如说我们要安装一个服务,有了服务,我们就要监听一个端口。

监听端口:正常情况下一台机器是没有端口监听的,没有端口监听,他就没法和其他机器通信,如果想提服务,如果让其他人访问你的服务器,你的网站,就需要监听一个端口,他把端口放开,打开一个洞,就好比在网卡打开一个洞,你的远程设备想办法和我们的这个小洞相连,你的数据从这个小洞进入到我们的网卡,我们的服务器中,相互的去通信。

netstat -lnp:查看监听端口 [root@localhost ~]# netstat -lnp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 889/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 991/master
tcp6 0 0 :::22 :::* LISTEN 889/sshd
tcp6 0 0 ::1:25 :::* LISTEN 991/master
udp 0 0 0.0.0.0:68 0.0.0.0:* 694/dhclient
udp 0 0 0.0.0.0:47393 0.0.0.0:* 694/dhclient
udp 0 0 127.0.0.1:323 0.0.0.0:* 547/chronyd
udp6 0 0 :::10353 :::* 694/dhclient
udp6 0 0 ::1:323 :::* 547/chronyd
raw6 0 0 :::58 :::* 7 570/NetworkManager 我们着重要注意以上这些内容,因为我们以后要添加的一些服务,如果想看这些服务是否正常启动,就会用到条命令,也可以用ps查看进程。

netstat -an:查看TCP/IP状态 查看所有的连接的状态,这里面会牵扯到TCP/IP的三次握手和四次挥手。

netstat-lntp:只查看tcp,不包含socket

查看所有状态数字的小技巧 [root@localhost ~]# netstat -an | awk '/^tcp/ {++sta[$NF]} END {for(key in sta) print key,"\t",sta[key]}' LISTEN 4 (监听) ESTABLISHED 2(保持连接)这个数字如果很大,说明你的系统很忙,网站并发连接数(并发连接数的概念就是同一时间有多少个客户端在连接你)。这有这个数字是在真正通信的。通常情况下,这个数字在1千以内。

ss -an:它和netstat类似,都可以查看TCP/IP状态,如果只想产看被监听的端口,我们可以接grep。

[root@localhost ~]# ss -an | grep -i listen |head -5 u_str LISTEN 0 128 /var/run/dbus/system_bus_socket 13578 * 0
u_str LISTEN 0 100 private/rewrite 17480 * 0
u_str LISTEN 0 100 private/bounce 17483 * 0
u_str LISTEN 0 100 private/defer 17486 * 0
u_str LISTEN 0 100 private/trace 17489 * 0
但是这个有一个缺点,他不会显示进程名字,但是netstat -lntp可以显示进程名字。

linux下抓包 有时候我们的网站会受到攻击,网卡流量异常,进入的包会有很多。这时候我们想知道都有哪些包进来,这时候我们就用tcpdump这个抓包工具来查看。 这个命令如果没有,我们就用yum来安装一下。

简单的抓包命令:tcpdump -nn -i ens33(由于我们设备名字特殊,所以我们要指定网卡名。) [root@localhost ~]# tcpdump -nn -i ens33 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes 时间 IP 源IP .源端口 >是到哪里去 目标源.目标端口 数据包信息 20:47:43.162758 IP 192.168.1.103.50895 > 192.168.1.105.22: Flags [.], ack 196, win 16246, length 0 20:47:43.163198 IP 192.168.1.105.22 > 192.168.1.103.50895: Flags [P.], seq 196:472, ack 1, win 255, length 276 20:47:43.163556 IP 192.168.1.105.22 > 192.168.1.103.50895: Flags [P.], seq 472:636, ack 1, win 255, length 164 20:47:43.163735 IP 192.168.1.103.50895 > 192.168.1.105.22: Flags [.], ack 636, win 16136, length 0 20:47:43.163914 IP 192.168.1.105.22 > 192.168.1.103.50895: Flags [P.], seq 636:896, ack 1, win 255, length 260 20:47:43.164169 IP 192.168.1.105.22 > 192.168.1.103.50895: Flags [P.], seq 896:1060, ack 1, win 255, length 164 我们重点关注的是源IP.源端口到目标源.目标端口。数据流向。

21:52:03.147158 IP 192.168.1.103.50895 > 192.168.1.105.22: Flags [.], ack 196, win 16147, length 0。 有时候我们也要注意length。有时候我们会看到一些奇怪的数据包,默认很多都是tcp的,有时候我们也有可能看到udp的包,如果出现udp的包很有可能你就被攻击了。有一种DDOS攻击,叫udp flood洪水攻击。如果遇到这种洪水攻击,我们只能借助于专业的防攻击设备或者是服务。

其中-nn中的第一个n代表你的IP,用数字的形式显示出来,如果不显示,则会显示主机名。 [root@localhost ~]# tcpdump -i ens33
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes 20:51:19.244423 IP localhost.localdomain.ssh > 192.168.1.103.50895: Flags [P.], seq 504196553:504196749, ack 3367907909, win 255, length 196 20:51:19.244725 IP 192.168.1.103.50895 > localhost.localdomain.ssh: Flags [.], ack 196, win 16207, length 0 20:51:19.246481 IP localhost.localdomain.43235 > cache4-dlcity.domain: 13573+ PTR? 103.1.168.192.in-addr.arpa. (44) 20:51:19.248896 IP cache4-dlcity.domain > localhost.localdomain.43235: 13573 NXDomain* 0/1/0 (99) 20:51:19.250229 IP localhost.localdomain.58113 > cache4-dlcity.domain: 50792+ PTR? 105.1.168.192.in-addr.arpa. (44) 20:51:19.251873 IP cache4-dlcity.domain > localhost.localdomain.58113: 50792 NXDomain* 0/1/0 (99) 20:51:19.252153 IP localhost.localdomain.57475 > cache4-dlcity.domain: 15278+ PTR? 38.69.96.202.in-addr.arpa. (43)

ocalhost.localdomain这就是主机名,但是在网上我们并不知道他是谁,所以还是要加上-nn比较直观。 .ssh这时ssh服务的端口,22,如果我们知道还好,如果我们不知道,那么我们就不知道这个端口是哪个数字。 所以我们加上nn,就会以数字的形式显示端口号。(第二个n是端口号) 这台设备没有跑什么服务,只是ssh远程连接的,所以在我们抓包的时候看到的很多包都是从22端口出去的。

tcpdmup -nn prot 端口:指定端口 因为我们在抓包的时候会抓到很多的端口,因为有些端口我们不需要看,所以我们既要查看指定端口。 tcpdump -nn -i ens33 port 22:指网卡和端口 tcpdump -nn -i ens33 port 22 and host 192.168.1.105:我们还可以加条件,指定IP的包。比如我们指定了192.168.1.105这个IP的包。

还有一种情况,我们指定数据包,只抓100个,而且我想把它存到一个文件中去 [root@localhost ~]# tcpdump -nn -i ens33 -c 100 -w /tmp/llt.cap tcpdump: listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes 100 packets captured 100 packets received by filter 0 packets dropped by kernel 这样100个包就抓完了。

.cap这个文件实际上是就是从网卡里捕获的数据包,这个包中含有源IP,目标IP,通讯的数据包,数据内容等很多的信息。所以不能用cat去查看。如果要查看,我们要用tcpdump -r(read读)+文件的路径+文件名。他显示的也是数据流。而我-w写入的是真真正正的数据包,这是我们要区分的。

然后我们查看一下抓好的包 [root@localhost ~]# tcpdump -r /tmp/llt1.cap reading from file /tmp/llt1.cap, link-type EN10MB (Ethernet) 22:43:46.835843 IP localhost.localdomain.ssh > 192.168.1.103.50895: Flags [P.], seq 511436009:511436141, ack 3367974121, win 255, length 132 22:43:46.836126 IP 192.168.1.103.50895 > localhost.localdomain.ssh: Flags [.], ack 132, win 16314, length 0 22:43:47.292696 IP 192.168.1.100.39909 > 239.255.255.250.ssdp: UDP, length 268 22:43:47.344078 IP 192.168.1.100.39909 > 239.255.255.250.ssdp: UDP, length 277 22:43:47.400646 IP 192.168.1.100.39909 > 239.255.255.250.ssdp: UDP, length 324 22:43:47.442222 IP 192.168.1.100.39909 > 239.255.255.250.ssdp: UDP, length 322 22:43:47.492553 IP 192.168.1.100.39909 > 239.255.255.250.ssdp: UDP, length 334 22:43:47.542970 IP 192.168.1.100.39909 > 239.255.255.250.ssdp: UDP, length 332 22:43:47.795308 IP 192.168.1.103.53665 > 61.135.169.125.https: Flags [R.], seq 672714496, ack 3686534326, win 0, length 0 22:43:47.796094 IP 192.168.1.100.39909 > 239.255.255.250.ssdp: UDP, length 268

wireshark:抓包工具,它的作用和tcpdmup类似。wireshark这个包有一个命名,tshark。他有一个很实用的用法,用这个命令可以查看你指定网卡80端口的一个wed访问情况。 [root@localhost ~]# tshark -n -t a -R http.request -T fields -e "frame.time" -e "ip.src" -e "http.host" -e " http.request.metod" -e "http.request.uri" 这个类似于wed的访问日志,我们可以很清晰的发现在这个往卡上,有什么ip来访问网站