课程咨询 :18487146383

  • java中的Linux系统资源的监控

    发布:昆明Java培训      来源:达内新闻      时间:2016-12-14

  • 昆明达内Java培训的老师这一期给大家讲Linux系统资源的监控。

    CPU使用率

    CPU使用时间分为两类:用户时间(User Time)和系统时间(System Time),系统时间在Windows系统中被称为特权时间(Privileged Time)。用户时间为CPU执行应用程序代码的时间,而系统时间则为CPU执行操作系统内核代码的时间比例。系统时间与应用程序本身有关,例如当应用程序执行I/O操作时,操作系统内核将会执行从硬盘读取文件的代码,或者执行向网络数据缓存中写入数据的代码。应用程序中任何需要使用操作系统底层资源的行为都会导致应用程序占用更多的系统时间。

    性能调优的终极目标是在单位时间内最大限度提高CPU使用率。CPU使用率是在一个特定时间间隔内的平均值,这个时间间隔可以是30秒,也可以是1秒。比如,一个程序需要10分钟执行完成,在此期间该程序的CPU使用率为50%。当对程序代码优化之后,CPU使用率提高为100%,那么该程序的性能将提升一倍,只需要5分钟执行完成。当该程序再次优化代码使用2个CPU,CPU的使用率依然为100%,那么该程序将只需要2.5分钟执行结束。从这个例子可以看出,CPU使用率能够反应程序使用CPU的效率,CPU使用率越高程序性能越好,反之亦然。

    在Linux操作系统中执行vmstat 5命令,将会得到如清单1中的数据(每5秒增加一行)。为了易于理解,此例中的程序只使用单线程运行,在多线程环境中同样适用。从示例数据中第一行数据可以知道,在5秒内,CPU一共被使用了2.25秒(5*(37%+8%)),其中37%的时间用于执行用户代码,8%的时间用户执行系统代码。剩余的2.75秒CPU处于闲置状态(idle)。

    清单1. vmstat 5命令结果

    procs -----------memory--------------- ----swap---- ---io--- -----system------ ----------CPU-------

    r b swpd free buff cache si so bi bo in cs us sy id wa st

    2 0 236456 2259632 200052 730348 0 0 1 6 1 1 37 8 55 0 0

    2 0 236456 2259624 200052 730348 0 0 0 10 179 332 40 7 53 0 0

    2 0 236456 2259624 200052 730348 0 0 0 20 180 356 56 7 37 0 0

    以下三点原因会造成CPU闲置:

    应用程序被线程的同步操作阻塞,直到锁被释放;

    应用程在等待某些请求的响应,例如等待数据查询请求的响应;

    应用程序无事可做;

    前两种情况比较容易理解,也有对应的调优方式。针对原因一,如果能够减少锁的竞争,或者调整数据库返回请求资源的性能,那么应用程序会运行的更快;对于原因二,优化请求响应方,提高响应速度;那么在其他条件不变的情况下,应用程序会运行的更快,CPU使用率也会提高。

    第三种情况当应用程序有事去做时,CPU将利用CPU周期去执行应用程序的代码。这是一条通用的规则。当执行一段无限循环的代码(如下所示)时,它将会再消耗一个CPU 100%的时间。如果CPU的使用率并没有达到100%,意味着操作系统应该执行无限循环,但它并没有去做而是处于闲置状态。这种情况对于无限循环并没有多少影响,但是如果我们的程序是用来计算一个表达式的结果,那么这种情况将会导致计算的速度变慢。

    清单2.无限循环示例

    #!/bin/bash

    while true

    do

    echo“In the loop…”

    done

    当在一台单核机器上运行清单2中的代码,绝大多数时间我们不会注意到它在运行。但是如果启动另一个程序或者监控另一个程序的性能时,这种影响就会体现出来。操作系统善于利用时间切片程序来竞争CPU周期,但是最新启动的程序只能获得极少的的可用CPU周期。有一种解决问题的方案,那就是留出一定比例的闲置CPU周期以防有其他程序需要使用CPU。但是这种方案暴露出来的问题就是操作系统无法知晓下一步操作,操作系统只能去执行当前所有的操作而不会留出闲置的CPU周期。

    Java和单CPU使用率

    我们回到Java应用程序,周期性的CPU闲置意味着什么呢?这取决于应用程序的类型。对于有固定作业量的批处理程序,除非全部作业完成,否则CPU不会有闲置时间。提高CPU的使用率可以使批处理程序更快地完成。如果CPU使用率已经达到100%,我们可以在保持CPU使用率100%的前提下从其他方面进行优化使程序完成地更快。

    对于接收请求的服务器类型的应用程序,在没有请求到来的时候,CPU会处于闲置状态。举例来说,当Web服务器处理完当前所有HTTP请求处于等待下一个请求的状态时,CPU为闲置状态。从这里可以理解CPU使用率为何为一定时间间隔内的平均数值。上文vmstat示例中的数据采集自一个应用服务器的运行过程中,这个服务器每5秒接收到一个请求,花费2.25秒处理,这意味着在这2.25秒内CPU的使用率为100%,而在剩下的2.75内使用率为0。由此计算得出CPU使用率为45%。

    这种情况总是发生在非常短的时间间隔内,因此很难被发现,但是这种类似应用服务器的程序总是按照此方式运行。当我们降低时间间隔,上述应用服务每2.5秒接受一个请求同时花费1.125秒处理请求,剩余的1.375秒CPU处于闲置状态。平均下来,CPU平均使用率依然为45%,55%的时间处于闲置状态。

    优化应用服务器之后,处理每个请求只需要2秒,CPU使用率将降至40%。降低CPU使用率是我们优化程序代码的目标。只有在单位时间内,没有外部资源约束的应用程序负载固定。从另一方面来讲,优化这种应用程序可以适当增加程序负载来提升CPU使用率。这样一来,可以看出这种优化策略依然遵循前文的规则,即在尽可能短的时间内使CPU使用率尽可能高。

    Java和多CPU使用率

    调优多线程程序的目标依然是尽可能的提高每个CPU的使用率,使CPU尽可能少的被阻塞。在多核多线程环境中,当CPU处于闲置状态时需要多考虑的是即使应用程序有作业未完成,CPU依然会处于闲置状态,因为该应用程序中没有可用的线程来处理作业。最典型的例子为一个拥有固定大小线程池的应用程序运行数量变化的任务。每个线程每次只能处理一个任务,如果此线程被某些操作阻塞,这个线程不能转而去处理另一个任务。在这种情况下就会出现没有可用线程来处理未完成的任务。因此会导致CPU处于闲置状态。对于此种情形应该考虑如何增加线程池的大小来完成更多的任务。

    监控CPU使用率只是理解应用程序性能的第一步,这只能确定代码的CPU使用率是否达到开发人员的期望,或者找到代码中存在的同步问题和资源问题。

    CPU Run Queue

    在Windows和UNIX系统中都可以监控当前可以执行任务的线程数。UNIX系统中称为Run Queue,有很多工具可以查到此数据。例如前文中的vmstat,每行的第一个数字即是Run Queue的长度。Windows系统中称之为Processor Queue,可以通过typeperf命令查到。

    Windows与UNIX的区别是:在UNIX中,Run Queue长度为当前正在运行和可以运行的线程数,所以这个长度最小为1;而在Windows中,Processor Queue长度并不包括正在运行的线程数,因此Processor Queue长度最小值为0。

    当可用线程数大于可用CPU数量,性能就会下降。所以在Windows中Processor Queue长度为0,在UNIX中Run Queue长度等于CPU数的情况性能达到最好。但这并不绝对,因为系统程序中会周期性运行导致此数值增大,单对应用程序的影响不大。如果Run Queue长度长时间远远大于CPU数,表示机器负载过大,应该适当减少当前机器的作业量。

    硬盘使用率

    监控硬盘使用率有两个重要的目标,一是应用程序本身,如果应用程序进行了非常多的硬盘I/O操作,很容易推断出应用程序的性能瓶颈在于I/O。

    需要进行详细的监控才能发现应用程序的性能瓶颈在于I/O。当应用程序没有高效地使用缓存来进行硬盘写操作时,硬盘I/O的数据将会非常低。但是当应用程序进行的I/O操作数超出了硬盘能够处理的数量,硬盘I/O数据将会非常高。这两种情况都需要进行调优。

    在Linux系统中执行iostat -xm 5命令可以得到清单3中的数据:

    清单3. iostat–xm 5命令结果一

    avg-CPU: %user %nice %system %iowait %steal %idle

    18.20 0.00 40.20 0.00 0.00 51.60

    Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s

    sda 0.00 0.20 0.00 34.60 0.10 0.23

    avgrq-sz avgqu-sz await svctm %util

    8.35 0.00 5.04 0.04 2.02

    应用程序在向硬盘sda中写入数据,看上去硬盘写入的时间情况还不错,每次写入等待时间(await)为5.04毫秒,硬盘使用率也仅为2.02%。但仔细来看,系统执行内核代码用掉40.2%的时间,这是意味着应用程序中存在低效的写操作。系统每秒进行34.60(w/s)次写操作,但是只写入了0.23MB(wMB/s)数据。可以判断I/O是应用程序的性能瓶颈所在。下一步将分析应用程序如何进行写操作。

    再看另一组数据(清单4),硬盘使用率(%util)达到100%,等待硬盘的时间占到了49.81%(%iowait),应用程序每秒写入60.45mb数据,这些数据共同证明I/O是应用程序的性能瓶颈所在,必须减少如此大量的I/O操作。

    清单4. iostat–xm 5命令结果二

    avg-CPU: %user %nice %system %iowait %steal %idle

    40.20 0.00 5.70 49.81 0.00 54.10

    Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s

    sda 0.00 0.20 0.00 134.60 0.10 60.45

    avgrq-sz avgqu-sz await svctm %util

    727.24 68.46 798.04 5.67 100

    监控硬盘使用率的另一个作用是得知系统是否在进行交换(swapping),计算机拥有固定数量的物理内存,但是它可以运行使用内存远远大于其物理内存的一些应用程序。应用程序占有的内存往往多于它们真正需要的内存,在这种情况下,操作系统将这些没有被用到内存挪入硬盘,当需要的时候将它们通过换页换进物理内存中。对于大多数应用程序,这种内存管理方式是不错的,但是对于服务器类型的应用程序而言,这种方式就显得尤为糟糕,因为由于Java内存堆的存在,服务器类型的应用往往需要用到非常多的物理内存。

    由于需要将硬盘中的数据与物理内存中的数据进行交换,会严重影响系统性能。vmstat命令的结果中si,so两列数据表示了换入物理内存和换出物理内存的数据量。通过这些数据可以知道系统是否在进行交换。

    网络使用率

    如果应用程序运行过程中使用了网络,在进行性能监控时必须监控系统网络传输使用率。网络传输类似于硬盘传输,低效地使用网络传输会造成网络带宽不足;如果网络传输的数据量超过了其所能负载的上限同样会造成网络传输性能瓶颈。

    操作系统内置的网络监控工具只能获得某个网络接口接收和发送的包数和字节数。通过这些信息还不足以确定网络负载正常还是负载过大。

    在UNIX系统中,基本的网络监控工具是netstat。

    当然,还有非常多的第三方网络监控工具,nicstat就是UNIX系统中使用很广泛的一个命令行工具,通过这个工具可以得到指定网络接口的使用率。

    执行nicstat 5命令,得到清单5中的数据,从数据中可以看到,网络接口e1000g1为1000MB接口,该接口使用率只有2.98%(%Util),每秒钟通过此接口读入156.4Kb数据,写入256.9Kb数据,通过这些数据,可以明确得出网络接口的带宽以及使用率。

    清单5. nicstat 5命令结果

    Time Int rKB/s wKB/s rPk/s wPk/s rAvs wAvs %Util Sat

    17:05:17 e1000g1 156.4 256.9 875.0 909.5 215.4 175.3 2.98 0.00

    如果只用netstat命令,可以获得每秒读写的数据量,但是必须知道网络带宽并且通过额外的脚本才能计算得出网络接口的使用率。在计算过程中需要注意,带宽单位为位每秒(bps),因此1000Mb带宽每秒可以传输125MB数据。而在nicstat已经帮我们做了类似的计算。

    网络传输无法支撑100%的使用率,在本地以太网网络,超过40%的使用率就被认为接口饱和。使用其他媒介进行网络传输的饱和使用率需要咨询网络架构师。Java程序只是使用操作系统的网络接口进行传输,并不能决定网络使用率的饱和值。

    了解详情请登陆昆明达内Java培训官网(km.Java.tedu.cn)!

上一篇:java开发助手Spring Boot与Docker

下一篇:Java类加载基本过程

最新开班日期  |  更多

Java--零基础全日制班

Java--零基础全日制班

开班日期:7月31日

Java--零基础业余班

Java--零基础业余班

开班日期:7月31日

Java--周末提升班

Java--周末提升班

开班日期:7月31日

Java--零基础周末班

Java--零基础周末班

开班日期:7月31日

  • 网址:http://km .java.tedu.cn      地址:昆明市官渡区春城路62号证券大厦附楼6楼
  • 课程培训电话:18487146383    全国服务监督电话:400-111-8989
  • 服务邮箱 tousu@tedu.cn
  • 2001-2016 达内时代科技集团有限公司 版权所有 京ICP证8000853号-56