月度归档:2019年02月

Linux性能监测:IO篇


2019年2月28日 17:26:00   1,362 次浏览

说到IO性能,就不得不说我曾经干过的一件傻事,这件事情让我记忆犹新。那还是我在xxx干活的时候,有一次需要进行全量上线,说到上线,那肯定就要对当前应用进行备份了。这个备份的活我都干了好久了,每次都是那么几个命令,先tar,然后再gzip,每次都是一个接一个的备份,而备份一个又要好久;然后我就想偷懒,耍个小聪明,写了一个脚本,一次同时并行备份所有的文件,然后启动脚本就OK了,也不需要人值守。我就这么干了,没过多久,前台使用人员就反馈系统反应慢,我一听,慌了,立马看了下,备份脚本占用了大量的IO,导致IO急剧飙升,导致系统整体性能下降。我都佩服我这个小机灵鬼,立马发现了问题,解决了问题。如何发现问题,请各位继续往下看。

说到IO,就得先说说存储系统。我们知道,在存储系统里面,越靠近CPU的(比如CPU的缓存),价格越贵、容量越小、速度越快;越远离CPU的(比如磁盘),价格越便宜、容量越大、速度越慢。而磁盘通常是计算机最慢的子系统,也是最容易出现性能瓶颈的地方,因为磁盘离CPU距离最远而且CPU访问磁盘要涉及到机械操作,比如转轴、寻轨等。访问硬盘和访问内存之间的速度差别是以数量级来计算的,就像1天和1分钟的差别一样。要监测IO性能,就有必要了解一下基本原理和Linux是如何处理硬盘和内存之间的IO的。

先说理论

而要说IO性能,就不得不先说说缺页中断了。Linux利用虚拟内存极大的扩展了程序地址空间,使得原来物理内存不能容下的程序也可以通过内存和硬盘之间的不断交换(把暂时不用的内存页交换到硬盘,把需要的内存页从硬盘读到内存)来赢得更多的内存,看起来就像物理内存被扩大了一样。事实上这个过程对程序是完全透明的,程序完全不用理会自己哪一部分、什么时候被交换进内存,一切都有内核的虚拟内存管理来完成。当程序启动的时候,Linux内核首先检查CPU的缓存和物理内存,如果数据已经在内存里就忽略,如果数据不在内存里就引起一个缺页中断(Page Fault),然后从硬盘读取缺页,并把缺页缓存到物理内存里。缺页中断可分为主缺页中断(Major Page Fault)和次缺页中断(Minor Page Fault),要从磁盘读取数据而产生的中断是主缺页中断;数据已经被读入内存并被缓存起来,从内存缓存区中而不是直接从硬盘中读取数据而产生的中断是次缺页中断。

上面的内存缓存区起到了预读硬盘的作用,内核先在物理内存里寻找缺页,没有的话产生次缺页中断从内存缓存里找,如果还没有发现的话就从硬盘读取。很显然,把多余的内存拿出来做成内存缓存区提高了访问速度,这里还有一个命中率的问题,运气好的话如果每次缺页都能从内存缓存区读取的话将会极大提高性能。要提高命中率的一个简单方法就是增大内存缓存区面积,缓存区越大预存的页面就越多,命中率也会越高。

内存缓存区(也叫文件缓存区File Buffer Cache)读取页比从硬盘读取页要快得多,所以Linux内核希望能尽可能产生次缺页中断(从文件缓存区读),并且能尽可能避免主缺页中断(从硬盘读),这样随着次缺页中断的增多,文件缓存区也逐步增大,直到系统只有少量可用物理内存的时候Linux才开始释放一些不用的页。我们运行Linux一段时间后会发现虽然系统上运行的程序不多,但是可用内存总是很少,这样给大家造成了Linux对内存管理很低效的假象,事实上Linux把那些暂时不用的物理内存高效的利用起来做预存(内存缓存区)了。

比如,以下这样的一个输出:

[root@Test_Server ~]# cat /proc/meminfo

MemTotal:        1883496 kB
MemFree:          137236 kB
MemAvailable:     286512 kB
Buffers:          107028 kB
Cached:           150352 kB

可以看到内存一共大概2G(MemTotal),其中大概130M可用(MemFree),100多M用来做磁盘缓存(Buffers),150多M用来做文件缓存(Cached)。

好了,有了这些基本知识,我们再来看IO性能的分析。

再说实干

说到实际的,那就要说说实际运维工作中,我们如何发现IO性能瓶颈。

我们进行IO分析,第一步还是需要祭出我们的神器vmstat,关于vmstat如何使用可以参见这篇《Linux vmstat命令详解》,通过vmstat的输出,重点关注bbibowa字段。这几个值变大,都意味着IO的消耗增加。对于读请求大的服务器,一般bbiwa都会比较大,而对于写入量大的服务器,一般bbowa都会比较大。

接下来就是使用第二个神器iostat。通过这个神器,我们就可以监视具体的磁盘性能了。对于iostat这个命令的具体教程,可以参见这篇《Linux iostat命令详解》。

但是,在实际运维工作中,我们都希望找到是哪个进程消耗了IO,所以我们的终极目的是找到这个进程ID。可是通过vmstatiostat都没法达到我们的目的。所以,神器pidstat命令就登场了,通过这个命令,我们就可以知道是谁在后台偷用IO了。我想我整理的这篇《Linux pidstat命令详解》对你应该有一些帮助。

现在定位到进程级别了,很多时候,我们需要知道这个进程到底打开了哪些文件,这个进程到底和哪些进程关联,这个时候就不得不提到lsof命令了。

Linux ip命令详解


2019年2月28日 16:41:00   1,458 次浏览

我之前一直都使用ifconfig命令,觉的这个命令挺好用的,后来有次安装Linux发型版本,发现没有了ifconfig这个工具了,无奈之下,到处百度,发现了ip这个命令,一顿学习后,发现ip命令完全可以替代ifconfig命令,而且功能还比ifconfig命令强大,所以,还等什么,借用现在的一个网络流行词:盘它。

命令简介

作为每个Linux网络管理员和所有的Linux使用者们,ip命令是必备工具,这个命令完美的取代了ifconfig命令,所以这篇文章就将全面的总结ip命令,希望通过我的这篇总结,让大家可以更熟悉ip命令。

命令详解

ip常用命令格式如下:

  1. ip [ OPTIONS ] OBJECT { COMMAND | help }

对象OBJECT={ link | addr | addrlabel | route | rule | neigh | ntable | tunnel | maddr | mroute | mrule | monitor | xfrm | token }

选项OPTIONS={ -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] | -h[uman-readable] | -iec | -f[amily] { inet | inet6 | ipx | dnet | link } | -o[neline] | -t[imestamp] | -b[atch] [filename] | -rc[vbuf] [size] }

常用对象的取值含义如下:

  • link:网络设备
  • address:设备上的协议(IP或IPv6)地址
  • addrlabel:协议地址选择的标签配置
  • route:路由表条目
  • rule:路由策略数据库中的规则

常用选项的取值含义如下:

  • -V,-Version:显示指令版本信息
  • -s,-stats,statistics:输出详细信息
  • -h,-human,-human-readable:输出人类可读的统计信息和后缀
  • -o,-oneline:将每条记录输出到一行,用‘\’字符替换换行符
使用实例-检查网卡信息

说实话这个ip命令真的好复杂,选项参数有那么多,所以吧,我们不可能每个功能面面俱到。所以呢,我这里就对我们日常工作中经常用到的一些用法进行总结。

  • 命令:ip addr show
    说明:显示网卡及配置的地址信息
    输出:
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
   link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
   inet 127.0.0.1/8 scope host lo
      valid_lft forever preferred_lft forever

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
   link/ether 00:1e:4f:c8:43:fc brd ff:ff:ff:ff:ff:ff
   inet 192.168.0.24/24 brd 192.168.0.255 scope global eth0
      valid_lft forever preferred_lft forever

输出内容详解:
首先这个系统有两个接口:loeth0lo是环回接口,而我们重点关注的则是eth0这个普通网络接口;下面在看看每个子项的含义:

  • <BROADCAST,MULTICAST,UP,LOWER_UP>BROADCAST表示该接口支持广播;MULTICAST表示该接口支持多播;UP表示该网络接口已启用;LOWER_UP表示网络电缆已插入,设备已连接至网络
  • mtu 1500:最大传输单位(数据包大小)为1,500字节
  • qdisc pfifo_fast:用于数据包排队
  • state UP:网络接口已启用
  • qlen 1000:传输队列长度
  • link/ether 00:1e:4f:c8:43:fc:接口的MAC(硬件)地址
  • brd ff:ff:ff:ff:ff:ff:广播地址
  • inet 192.168.0.24/24:IPv4地址
  • brd 192.168.0.255:广播地址
  • scope global:全局有效
  • dynamic enp0s25:地址是动态分配的
  • valid_lft forever:IPv4地址的有效使用期限
  • preferred_lft forever:IPv4地址的首选生存期
  • inet6 fe80::2c8e:1de0:a862:14fd/64:IPv6地址
  • scope link:仅在此设备上有效
  • valid_lft forever:IPv6地址的有效使用期限
  • preferred_lft forever:IPv6地址的首选生存期
使用实例-IP管理
  • 命令:ip addr add 192.168.0.123/24 dev eth0
    说明:设置IP
  • 命令:ip add del 192.168.0.123/24 dev eth0
    说明:删除配置的IP
使用实例-启用/禁用网卡
  • 命令:ip link set eth0 up
    说明:启用被禁用的网卡
  • 命令:ip link set eth0 down
    说明:禁用网卡
使用实例-路由配置

命令:ip route show
说明:查看路由信息
输出:

default via 172.17.175.253 dev eth0
169.254.0.0/16 dev eth0 scope link metric 1002
172.17.160.0/20 dev eth0 proto kernel scope link src 172.17.169.20
  • 输出内容详解:
    • 输出内容第一条是默认的路由,我们可以根据我们的需要改动它
    • metric 1002:跳跃计数,确定网关的优先级,默认20,数值越小优先级越高
    • proto kernel:该路由的协议,主要有redirectkernelbootstaticra等,其中kernel指的是直接由核心判断自动设定
  • 命令:ip route get 119.75.216.20
    说明:通过IP地址查询路由包从哪条路由来
  • 命令:ip route add default via 192.168.0.150/24
    说明:所有的网络数据包都通过192.168.0.150来转发,而不是以前的默认路由
  • 命令:ip route add 172.16.32.32 via 192.168.0.150/24 dev enp0s3
    说明:修改特定网卡的默认路由
  • 命令:ip route del 172.17.160.0/20
    说明:删除路由
  • 命令:ip route flush cache
    说明:刷新路由表
使用实例-显示网络统计数据

这个显示网络统计数据则是ip命令非常重要的一个功能,很多时候,我们都依靠该功能来进行排除网络故障。

  • 命令:ip -s link
    说明:显示所有网络接口的统计数据
    输出:
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT qlen 1
   link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
   RX: bytes  packets  errors  dropped overrun mcast  
   361849729592 174114258 0       0       0       0      
   TX: bytes  packets  errors  dropped carrier collsns
   361849729592 174114258 0       0       0       0      

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000
   link/ether 00:16:3e:08:08:55 brd ff:ff:ff:ff:ff:ff
   RX: bytes  packets  errors  dropped overrun mcast  
   32345193376 115901261 0       0       0       0      
   TX: bytes  packets  errors  dropped carrier collsns
   139742200499 114451909 0       0       0       0
  • 输出重点内容详解:
    • RX:表示接收
    • TX:表示发送
    • bytes:接收/发送的字节数
    • packets:接收/发送的包数
    • errors:接收/发送的带有错误的包总数
    • dropped:由于处理资源不足导致接收/发送的丢弃的包数
    • overrun:因接收溢出(环形缓冲区)导致丢失的包;通常如果接口溢出,则表示内核中存在严重问题,或者说服务器上该网络设备的处理设备太慢
    • mcast:接收到的多播包数
    • carrier:因数据链路错误导致发送失败的包数
    • collsns:因在网络上发送冲突而导致的失败数
  • 命令:ip -s -s link ls eth0
    说明:获取一个特定网络接口的信息;在网络接口名字后面添加选项ls即可。使用多个选项-s会输出指定接口详细的信息;特别是在排除网络连接故障时,这会非常有用。
    输出:
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000
   link/ether 00:16:3e:08:08:55 brd ff:ff:ff:ff:ff:ff
   RX: bytes  packets  errors  dropped overrun mcast  
   32469801665 116402997 0       0       0       0      
   RX errors: length   crc     frame   fifo    missed
              0        0       0       0       0      
   TX: bytes  packets  errors  dropped carrier collsns
   140235841575 115066014 0       0       0       0      
   TX errors: aborted  fifo   window heartbeat transns
              0        0       0       0       2