java性能监控常用的几个命令

假如想象 提交于 2020-01-07 17:48:18

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

     找到性能问题的第一步是监控应用的行为,通过监控提供的线索,我们可以将性能问题进行归类并分析。

     1、CPU使用率:大多数操作系统的CPU使用率分为用户态CPU使用率和系统态CPU使用率。用户态CPU使用率是指执行应用程序代码的时间占总CPU时间的百分比,相比而言,系统态CPU使用率是指应用执行操作系统调用的时间占总CPU时间的百分比。系统态CPU使用率高意味着共享资源有竞争或者I/O设备之间有大量的交互。理想情况下,应用达到最高性能和扩展时,它的系统态CPU使用率为0%,所以提高应用性能和扩展性的一个目标是尽可能降低系统态CPU使用率。

        CPU停滞通常会浪费几百个时钟周期,因此提高计算密集型应用性能的策略是减少停滞或者改善CPU高速缓存使用率,从而减少CPU在等待内存数据时浪费的时钟周期。

         Linux命令行监控CPU使用率的有vmstat或者top(或者htop,需要自行安装,但查看效果更好):

vmstat  采集间隔(秒)   采集次数

当一直监控时,可以省去采集次数,即 vmstat 2,每隔2秒采集一次,一直持续。

命令介绍完毕,现在开始实战讲解每个参数的意思,后面还会使用到:

r        表示运行队列的长度,值是运行队列中轻量级进程的实际数量,即当内核线程已经准备好运行只是还没有可用的处理器执行时,运行队列就会有值。

b         表示阻塞队列,当内核线程等待诸如I/O,内存页等资源时,阻塞队列就会有值。

swpd    虚拟内存已使用的大小,如果大于0,表示你的机器物理内存不足了,如果不是程序内存泄露的原因,那么你该升级内存了或者把耗内存的任务迁移到其他机器。

free   空闲的物理内存的大小。

buff   Linux/Unix系统是用来存储,目录里面有什么内容,权限等的缓存。

cache cache直接用来记忆我们打开的文件,给文件做缓冲(这里是Linux/Unix的聪明之处,把空闲的物理内存的一部分拿来做文件和目录的缓存,是为了提高 程序执行的性能,当程序使用内存时,buffer/cached会很快地被使用。)

si  每秒从磁盘读入虚拟内存的大小,如果这个值大于0,表示物理内存不够用或者内存泄露了,要查找耗内存进程解决掉。我的机器内存充裕,一切正常。

so  每秒虚拟内存写入磁盘的大小,如果这个值大于0,同上。

bi  块设备每秒接收的块数量,这里的块设备是指系统上所有的磁盘和其他块设备,默认块大小是1024byte,我本机上没什么IO操作,所以一直是0,但是我曾在处理拷贝大量数据(2-3T)的机器上看过可以达到140000/s,磁盘写入速度差不多140M每秒

bo 块设备每秒发送的块数量,例如我们读取文件,bo就要大于0。bi和bo一般都要接近0,不然就是IO过于频繁,需要调整。

in 每秒CPU的中断次数,包括时间中断

cs 每秒上下文切换次数,例如我们调用系统函数,就要进行上下文切换,线程的切换,也要进程上下文切换,这个值要越小越好,太大了,要考虑调低线程或者进程的数目,例如在apache和nginx这种web服务器中,我们一般做性能测试时会进行几千并发甚至几万并发的测试,选择web服务器的进程可以由进程或者线程的峰值一直下调,压测,直到cs到一个比较小的值,这个进程和线程数就是比较合适的值了。系统调用也是,每次调用系统函数,我们的代码就会进入内核空间,导致上下文切换,这个是很耗资源,也要尽量避免频繁调用系统函数。上下文切换次数过多表示你的CPU大部分浪费在上下文切换,导致CPU干正经事的时间少了,CPU没有充分利用,是不可取的。

us 用户态CPU使用率,我曾经在一个做加密解密很频繁的服务器上,可以看到us接近100,r运行队列达到80(机器在做压力测试,性能表现不佳)。

sy 系统态CPU使用率,如果太高,表示系统调用时间长,例如是IO操作频繁。

id  空闲态 CPU使用率,一般来说,id + us + sy = 100,一般我认为id是空闲CPU使用率,us是用户CPU使用率,sy是系统CPU使用率。

wa 等待IO CPU使用率。

vmstat和top不一样的地方就是vmstat统计的是所有的cpu,而top是单独统计每个cpu的。

那么在监控时查看us、sy、id就可以监控到CPU的使用情况了。另外通过top和java的jstack可以找到占用CPU过高的线程以及导致线程占用CPU过高的方法(参见转载的另外一篇文章http://my.oschina.net/u/128568/blog/198345)。

2、CPU调度程序运行队列:除CPU使用率之外,监控CPU调度程序运行队列对于分辨系统是否满负荷也有重要意义。

       解决运行队列长有2中办法:一种是增加CPU以分担负载或减少处理器的负载量,另一种是分析应用,改进CPU使用率。

     同样是使用vmstat,查看第一项的输出,就是  r .    如果在很长一段时间内,运行队列的长度一直都超过虚拟处理器个数的一倍,就需要关注了。只是暂时还不需要采取行动。如果长度达到虚拟处理器个数的3-4倍或更高,此时系统的响应将会非常迟缓,就需要立即引起注意或采取行动。

3、内存使用率:当页面调度或者页面交换、加锁、线程迁移中的让步式和抢占式上下文切换都会导致内存使用率很高,并且还伴随着大量的swap(页面交换)发生。

     为什么内存使用率高并且大量交换发生时就是性能差的表现,而单独的内存使用率高是不能判定性能差的呢?当访问应用中被置换出去的部分时(置换出去的部分是比较少使用的),就必须将它从磁盘置换进内存,而这种置换活动会对应用的响应性和吞吐量造成很大影响。比如JVM垃圾回收,垃圾收集器为了回收不可达对象所占用的空间,就需要访问大量内存,如果java堆的一部分被置换出去,就必须装进来,并且垃圾收集是会发生Stop-The-World,这样会引起JVM长时间的停顿。

      如上所说,使用vmstat,查看free、si、so三列来判定内存使用状况。当系统空闲内存恨少时,free列会保持在一个比较稳定的值,因为si和so的置换速度已经几乎一样快。

4、监控锁竞争:挂起和唤醒线程会导致操作系统的让步式上下文切换。因此锁竞争严重的应用会表现出大量的让步式上下文切换。让步式上下文切换耗费的时钟周期代价非常高,通常高达80000个时钟周期。

       可以遵循的一般性准则,对于任何java应用来说,如果让步式上下文切换占去它3%-5%或者更多时钟周期,说明遇到了锁竞争。Linux上可以使用sysstat包中的pidstat监控锁竞争。pidstat -w 输出结果中的cswch/s是让步式上下文切换。注意它统计的所有处理器的让步式上下文切换。

计算公式: (让步式上下文切换 / 虚拟处理器数目)  *  80000   /  该处理器的时钟周期

hadoop@slave1:~$ pidstat -w -I -p 9391 5
Linux 3.2.0-23-generic (slave1) 	03/16/2014 	_x86_64_	(1 CPU)
03:14:36 PM       PID   cswch/s nvcswch/s  Command
03:14:41 PM      1034      3645      322    java
03:14:46 PM      1034      3512      292    java
03:14:51 PM      1034      3499      310     java

比如机器是处理器个数是2(查看命令,grep processor /proc/cpuinfo | wc -l),3GHZ的CPU,计算如下:

(3500/2)* 80000 / 3 000 000 000 = 4.7%。根据一般准则(3%~5%),说明java应用正面临竞争。

5、监控抢占式上下文切换:让步式上下文切换是指执行线程主动释放锁,抢占式上下文切换是指线程因为分配的时间片用尽而被迫放弃CPU或者被其他优先级更高的线程所抢占。同样如上面第四个所言,cswch/s是每秒的让步式上下文切换,nvccswch/s是抢占式上下文切换。

6、监控网络IO:在分布式java应用中,网络也成为性能的一个重要因素。监控网络主要是监控网卡接收和发送数据的情况,因此不能使用netstat。采用nicstat,安装参考http://xuclv.blog.51cto.com/5503169/1157208

列名的含义如下:

Int  网络接口设备名
rKB/s, InKB   每秒读取的KB数
wKB/s, OutKB   每秒写入的KB数
rPk/s, InSeg, InDG  每秒读取的包数
wPk/s, OutSeg, OutDG  每秒写入的包数
rAvs  每秒读取的平均字节
wAvs  每秒写入的平均字节
%Util 网络接口使用率 
Sat   饱和度

7、监控磁盘IO:磁盘IO使用systat保重的iostat来监控。

     监控IO的意义何在呢,主要是由于磁盘的读写速度发展完全跟不上CPU的发展速度,很多时候不是CPU慢,而是硬盘读写数据太慢。那么有哪些办法改进磁盘的IO使用率呢:

     1)、更快的存储设备。举例来说,在hadoop生态系统中,hbase是使用hdfs作为底层存储,而hbase的高效是以大量的写入和读取来换取的,此时磁盘读写就是一个很大的瓶颈,那么多增加几个磁盘(可同时想多个磁盘进行IO读写),或者使用SSD来缓存热数据,冷数据放在一般的磁盘中(参考facebook的HBase优化案例:http://www.infoq.com/cn/articles/hbase-casestudy-facebook-messages/  )。   

     2)、文件系统扩展到多个磁盘。如上一条所说,hadoop其中一个优化就是允许配置多个磁盘作为hdfs的写入和读取,这么做的原因就是一个磁盘的寻道速度有限,那么多几个磁盘可以同时寻道,速度自然就增快。

     3)、操作系统调优使得可以缓存大量的文件系统数据结构

任何减少磁盘活动的策略都有帮助,比如java中使用缓冲流进行读写,或者对于重复读取同一文件的,可以一次读取这个文件,缓存后便于后面的读取,等等。

命令展示了对每个盘的io统计。其中%system表示系统态CPU使用率,%util下的值显示的每个盘的io使用情况。

这些命令自己也不怎么熟悉,欢迎有更多经验的人分享自己心得,欢迎拍砖,后续还有更多的有关性能方面的博客。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!