内容简介:Linux性能问题定位总结
当一个系统出现前台响应慢、接口返回慢等情况时,可以考虑分析是否存在性能瓶颈了,性能瓶颈可以分为2种:
-
CPU高(这里指长期使用率超过75%),包括用户态CPU+内核态CPU,这类问题比较常见,通过结合TOP命令和抓取线程堆栈可以找到耗资源最多的线程,然后分析调用堆栈进行优化
-
CPU使用率不高,但是系统还是响应慢
这里主要介绍第二种场景,分析步骤如下:
排查 Java 进程是否在Full GC
对于Java进程响应慢,先要排查系统是否在频繁Full GC,Full GC时JVM暂停时间较长,所有线程会被挂起。一般来讲如果是这种场景,通过top -Hp Java进程ID 命令可以发现某个线程的CPU使用率一直处于99%左右(线程名称vm thread),从GC日志可以看到JVM一直在执行CMS GC(JVM老年代GC)。
首先在GC日志中搜索 CMS-concurrent-mark-start
关键字,查看相邻两次CMS GC的时间间隔,如下所示:
CMC GC基本上每分钟一次,GC频率太高,会导致JVM大部分时间都处理停顿状态, 每小时发生一次CMS GC就已经算频率高了,再来看GC停顿时间:
从GC日志来看, GC发生时新生代的eden区和from区基本上已经满了,正常场景要执行Minor GC了,但是可以看到老年代CMS区总大小6291456K,使用了6291455K,基本上用完了。JVM有一个线程每隔2秒钟去检查老年代的大小,如果超过指定的阈值(阈值可以通过jvm参数指定: -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=75
),那就会触发一次CMS GC,从GC日志来看,在CMS GC期间又有新的在老年代创建对象的请求,此时又没有空间容纳新对象,就出现了 concurrent mode failure
这个错误,这个错误发生后JVM会放弃当前的CMS GC转而执行一次Full GC,Full GC会对新生代和老年代进行内存回收,大部分过程都是stop-the-world的,由GC日志可以看到整个JVM停顿了36.40秒。每隔一分钟执行一次Full GC,每次停顿36.4秒,可以想到JVM几乎一直不可用。GC回收之后新生代和老年代的内存使用率还是非常高,因此JVM一直在执行GC,如果JVM花费98%的时间都在GC并且回收的内存小于2%,那就会抛出Out-Of-Memort Error并退出jvm进程。
出现上图中的场景一般是有线程一直在创建对象,并且对象的创建速度高于回收速度,因此要分析这样子创建对象是否是合理的,如果是合理的,那要考虑调整JVM参数扩充内存。合不合理要根据业务场景来分析,一般是通过jmap命令获取当前jvm对象的直方图,找到哪些对象占了大部分的内存,并分析是否合理.
分析内存和磁盘
如果排除了JVM Full GC的可能性,那要分析是否是内存和磁盘的问题了:
一般都是首先通过top命令查看当前系统的负载,系统的负载代表的时在队列中等待执行的任务数量,对于单核CPU,负载为1表示已经达到了系统的负荷,对于多核CPU如果负载高于CPU核心数量也是达到了负荷,但是一般到达0.5 * CPU核心数时就要关注了。
比如下面的场景,load average 在1分钟、5分钟和15分钟平均值分别是5.92 5.58 5.48,CPU核心数为12. CPU使用率不高,正常场景25%的CPU使用率负载不会这么高,这个时候很可能是内存和磁盘有性能瓶颈。
需要注意的是,通过Top命令看到的只是表象,具体深层次的原因要通过vmstat和iostat两个命令来分析,分析过程如下:
使用 vmstat 1
观察系统的负载情况,这个命令每隔1秒钟输出一次:
-
r列表示当前运行的任务数,如果超过cpu核心数那就会有任务要等待
-
b列表示当前正在阻塞等待的任务数,如果这个数量长期较大,表示执行的任务太多,cpu调度不过来
-
swapd列是分析内存的关键指标,swapd表示从内存交换的磁盘的空间大小,单位是Kb,当内存不时使操作系统会把一部分不使用的内存交换到交换空间(这个空间使用的是磁盘),正常场景这个值应该是0,当前是交换了6.7G内存左右,说明内存已经严重不足了;
-
si指标表示swap in,内存交换到磁盘的次数,当前交换次数较多.
-
so指标表示swap out,从磁盘交换回内存次数,从图中可以看出系统一直在swap in 和swap out,说明内存一直不够
(这里需要注意的是,如果swapd小于100M并且swap in 和swap out一直为0,那系统也算正常) -
free列表示空闲内存的数量。
再看一个正常环境的vmstat命令输出,swapd为79M, si和so一直为0,并且free内存充足。
使用iostat -x 命令观察io的使用情况:
每列指标的含义如下:
- rrqm/s: 每秒进行 merge 的读操作数目
- wrqm/s: 每秒进行 merge 的写操作数目
- r/s: 每秒完成的读 I/O 设备次数
- w/s: 每秒完成的写 I/O 设备次数
- rsec/s: 每秒读扇区数
- wsec/s: 每秒写扇区数
- rkB/s: 每秒读K字节数,是 rsect/s 的一半,因为每扇区大小为512字节。(需要计算)
- wkB/s: 每秒写K字节数,是 wsect/s 的一半。(需要计算)
- avgrq-sz: 平均每次设备I/O操作的数据大小 (扇区)
- avgqu-sz: 平均I/O队列长度
- await: 平均每次设备I/O操作的等待时间 (毫秒)
- svctm: 平均每次设备I/O操作的服务时间 (毫秒)(这个指标没有参考价值,可以忽略)
- %util: 一秒中有百分之多少的时间用于 I/O 操作,或者说一秒中有多少时间 I/O 队列是非空的。如果 %util 接近 100%,说明产生的I/O请求太多,I/O系统已经满负荷,该磁盘可能存在瓶颈。idle小于70% IO压力就较大了,一般读取速度有较多的wait.
从上面的图片来看,io不算忙碌,但是await高达86.67毫秒,也就是平均每个io请求要等待87毫米才处理完,从avgqu-sz来看队列中平均任务数才0.57,说明IO任务并不多,但是单个任务处理慢,一般就是磁盘处理速度慢。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 记一次网页性能问题定位
- 利用jstack定位典型性能问题实例
- 容器化 RDS:借助火焰图定位Kubernetes性能问题
- 90% 的人会遇到性能问题,如何用 1 行代码快速定位?
- 认识绝对定位,相对定位
- 移动端页面头部固定定位的绝对定位实现
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。