应用系统性能问题
- 进程消耗cpu,内存利用率暴增如何定位代码
- 数据库连接数被耗尽怎么办
- 各种OOM如何预防
- 线程死锁,锁争用
- 上下文切换太频繁那怎么办
无论多复杂的系统运行在linux上,其实就是一个进程,任何东西在操作系统层面都是以文件的形式存储的,进程也不例外,所以从操作系统的层面只需要关注进程和线程即可
linux上部署一个Tomcat的程序,产生的是一个进程,这个进程所有的东西就会在如下图的一个目录proc/pid下
ll /proc/15208
# 通过ps -ef找到对应的进程id
我们所关注的日常日志输出在哪里,系统加载哪些jar包,系统启动的时候是哪个java版本等等这些问题都会在这张图中找到答案,在复杂的微服务中快速地需要找到这些信息的情况
ll /proc/29242/fd | grpe socket | head -n 20
# head命令可以取出文件的前面几行,语法为:
head [-n number] 文件
还需要找到系统和哪些外部应用在交互,包括使用的哪些中间件服务,比如Elasticsearch、Redis、mq等,这些都可以通过socket的端口能够找到,因为应用底层所有的通信都是通过socket
系统画像的纬度
性能关注维度
一般来说,业务系统系统性能主要关注两件事,一个是吞吐量,一个是系统的响应性
一、CPU
如果cpu的利用率不高,但是系统的吞吐量和响应性却不理想,这时候说明程序并没有忙于计算,可能问题出现在IO上
二、IO
IO和CPU的利用率一般是呈反比,CPU利用率高则IO不大
关于IO,一个是磁盘IO,一个是驱动程序的IO,一个是内存换页率
三、网络带宽
如果CPU利用率不高、IO利用率不高、内存的使用不高、网络带宽使用也不高,但是系统的性能还是上不去,那么程序一定是被阻塞了,可能是因为CPU在等待哪个锁,也可能是因为某个资源比如接口返回,连接在等待(包括上下文的切换)等
影响应用程序的因素
一、磁盘IO
内存、CPU、IO处理速度对比
CPU看成一个时钟周期1秒
一级缓存读取信息好像在桌子上拿起一张纸,比如3秒
二级缓存读取信息则是从身边的书架上取出一本书,可能需要14秒
从主从中读取相当于走到办公楼下面买个零食,需要4分钟
从磁盘中寻道的时间相当于离开办公大楼,并开始长达一年零三个月的环球旅游
可以看出CPU、内存、IO、硬盘的速度比较
二、网络IO
某些场景下,由于网络环境的不确定性,尤其是互联网上的数据读写,网络操作的速度可能比本地的IO要更慢
三、CPU
CPU的资源争夺,将导致性能问题,主要是锁竞争,锁竞争会导致上下文切换频繁,带来严重的系统开销,表现就是内核态的CPU利用率偏高
四、内存
内存做为系统性能指标之一,最大的可能是内存不足,但是对于java程序只需要关注GC情况
五、连接
系统对外部依赖的中间件和接口,比如说数据库连接,如果数据量过大或者连接超时,都是比较消耗性能
六、异常
java异常的捕获和处理非常消耗资源,如果程序高频率地在异常处理,也会影响系统的性能
快速诊断
一、资源诊断
CPU、IO、内存、磁盘、网络
- top命令
最需要关注的是top的load average,显示的是说最近1分钟、5分钟和15分钟之内系统的平均负载。系统的平均负载被定义为在特定的时间间隔内,运行队列中(即CPU上运行或者等待运行多个进程的平均进程数)。比如现在系统有两个正在运行的进程,三个可运行的进程,那么系统的load就是5。CPU核数和Load Average的关系好比高速公路上的多车道,如果车辆过多就会显示拥挤,故load average越高说明系统的性能越差
如果CPU处理的进程数大于5,那这时候性能就比较严重。假如CPU是8核,过去1分钟、5分钟和15分钟的load
average的值为60.58、61.14、61.22,可以计算出平均每核的数据
另外,我们需要关注用户态的CPU和内核态的CPU,也就是us和sy的数值
-
内存问题
如果需要查看某个进程,占用的物理内存和虚拟内存,可以直接使用命令pidstat - r -p pid 1 2来定位
如果要查看某个进程文件的IO情况,可以通过命令pidstat加参数去查看
Vmstat命令中swpd过高,通常是物理内存不够用了,swap的消耗主要关注它的IO,如果IO发生比较频繁,那么也会影响系统的性能 -
网络问题
trace命令可以用来跟踪进程的执行和系统的调用,通过trace -T之间的参数,可以显示具体的进程系统调用的情况
网络的IO也可以通过cat proc interrupts来查看,网络IO消耗需要关注网卡中断,是否不均衡分配到各个CPU -
磁盘问题
一般使用dstat来查看
二、连接
应用往往需要和外部的服务交互,比如数据库、缓存
通过netstat的命令可以查看,可以发现系统正在和哪些外部的应用交互
netstat -anop|grep 3306
3306的端口(数据库的连接端口)显示系统有连接mysql的数据库,并且有40个连接
有时候会报错has already more than最大的连接数,这时候用此命令查看连接数的数量,当连接数非常多的时候,最大的可能是代码在不停地操作数据库,或者有慢SQL导致的连接不释放。当应用连接数大于正常连接数时,需要排查系统代码数据库操作的问题
三、线程异常
线程异常问题排查
四、TCP状态诊断
客户端和服务端TCP建立连接和释放连接的过程,如下图
需要重点关注的是CLOSE-WAIT和TIME-WAIT,TIME-WAIT表示主动关闭,CLOSE-WAIT则表示被动关闭。如果客户端并发量很高,就会出现TIME-WAIT很高,有可能是客户端的连接连不上,可以通过netstat命令来查询定位
五、CPU过载诊断
如何定位代码中哪段导致CPU过载?
cpu过载问题排查
六、OOM
OOM问题排查
七、JVM GC的问题
JVM有很多工具和命令,不过主要需要关注GC的情况。GC会导致系统应用暂时的停顿,如果频繁的GC就会产生系统延迟响应。开启GC日志,可以收集GC的统计和信息,方便观察和定位应用停顿的原因,也可以通过命令jstat收集相关信息
jstat -gccause 1 1000
八、日志诊断
检查日志异常、Error等各种数据库异常等,可以快速地了解系统地运行情况