第1章 常用工具简介 性能调优是一个涉及面很广的话题,影响性能的因素很多,如网络、CPU、内存、I/O、应用程序等,这些因素都可能影响系统的整体性能。所以对性能的调优也并不是单纯地从一方面入手就能解决的问题, 这如同木桶原理,系统能够运行多快,取决于最短的那一块板,而最短的那一块板就是经常所说的“瓶颈”。一般解决问题的思路是首先发现“瓶颈”,然后想办法解决。在发现的过程中,对系统的监控是十分必要的。本章将介绍一些常用的监控工具和Spark开发过程中辅助的框架。本章主要内容如下:  Linux中的性能监控命令。  Prometheus。  Grafana。  Alluxio的使用。 1.1Linux中的性能监控命令 在生产环境中,大部分应用程序都部署在Linux系统当中。在对Spark性能监控的过程中,对Linux系统本身的各种运行状态的监控也是必不可少的。本节基于Linux发行版CentOS 7介绍Linux中常用的性能监控命令和工具。 1.1.1程序准备 为了更清楚地展示Java应用程序对系统CPU、内存、I/O等各方面的使用情况,突出各种监控命令对系统不同方面的监控情况,本节使用4个不同的Java程序,分别模拟真实业务对系统CPU、内存、磁盘I/O、网络I/O等方面的占用情况。 1. CPU占用 public class CPUConsume { public static void main(String[] args) { int threadNumber=1; if (args.length > 0) { threadNumber=Integer.parseInt(args[0]); } IntStream.range(0, threadNumber).forEach(i-> { new Thread(()-> { while (true) { } }).start(); }); } } 此程序默认开启一个线程,使CPU陷入无限忙循环,大量占用CPU资源; 同时可接收一个整型参数,开启指定的线程数,更大程度地占用CPU资源。 2. 内存占用 public class MemoryConsume { public static void main(String[] args) { List list=new ArrayList<>(); int mbSize=1024*1024; Runtime runtime=Runtime.getRuntime(); while (true) { list.add(new byte[1024*1024]); if (list.size()%10==0) { String format="maxMemory:%sM totalMemory:%sM freeMemory:%sM"; System.out.println(String.format(format,runtime.maxMemory()/mbSize,runtime.totalMemory()/mbSize , runtime.freeMemory()/mbSize)); } } } } 此程序模拟消耗系统内存,其每次创建1MB数组,放入集合中。并且已分配的内存不可进行垃圾回收,直到系统JVM无法再分配更多的内存,将内存消耗殆尽。 3. 磁盘I/O占用 public class DiskIOConsume { public static void main(String[] args) { int threadNumber=1; if (args.length > 0) { threadNumber=Integer.parseInt(args[0]); } byte[] data=new byte[1024*1024]; IntStream.range(0, threadNumber).forEach(i-> { new Thread(()-> { while (true){ OutputStream out=null; try { out=new FileOutputStream(new File("/tmp/"+i)); out.write(data); } catch (Exception e) { e.printStackTrace(); } finally { if(out!=null){ try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } } }).start(); }); } } 此程序默认开启一个线程,循环向磁盘的/tmp目录写入1MB数组; 同时可以接收整型参数,开启更多的线程同时向磁盘写入数据。 4. 网络I/O占用 网络I/O的程序分为服务端程序和客户端程序。程序启动后,客户端将向服务端写入大量数据。  服务端程序。 public class NetConsumeServer { public static void main(String[] args) throws Exception { ServerSocket serverSocket=new ServerSocket(10010); while (true) { Socket socket=serverSocket.accept(); new Thread(()-> { try { byte[] buffer=new byte[2048]; InputStream inputStream=socket.getInputStream(); int i=0; while ((i=inputStream.read(buffer)) !=-1) { } } catch (IOException e) { e.printStackTrace(); } }).start(); } } }  客户端程序。 public class NetConsumeClient { public static void main(String[] args) { int threadNumber=1; if (args.length > 1) { threadNumber=Integer.parseInt(args[1]); } IntStream.range(0, threadNumber).forEach((i)-> { try { Socket socket=new Socket(args[0], 10010); OutputStream outputStream=socket.getOutputStream(); while (true) { outputStream.write(new byte[1024]); } } catch (IOException e) { e.printStackTrace(); } }); } } 注意: 本节中的程序将会严重消耗系统资源,可能会对系统造成不可预知的后果,请在测试环境中执行。 1.1.2top命令 top命令是Linux系统中自带的一个应用程序,用于提供对系统运行状态的实时监控,可以显示系统的概要信息、各个进程或线程运行状态和资源占用情况。top命令还内置了一些交互式命令,用于调整数据输出的方式,如按资源占用排序等。 1. 命令选项 top命令的格式如下: top [选项] top命令中的选项很多,表1.1列出一些常用的选项进行说明。 表1.1top命令常用选项说明 选项说明选项说明 p监控指定的进程d指定两次数据刷新的间隔 i不显示空闲或僵尸进程u按用户过滤进程 c显示启动进程命令的完整路径H显示线程而不是进程 o按照某个字段排序显示 2. 交互式命令说明 在top命令运行的过程中,还可以输入一些简单的交互式命令,以改变程序的输出状态。这些命令都是由一个字母或数字组成,常用的交互式命令如表1.2所示。 表1.2top常用的交互式命令 命 令 名 称说明 h或?显示帮助信息 M按照任务使用内存进行排序输出 P按照任务CPU使用率排序输出 H显示进程和线程的切换 s改变top刷新频率,单位是秒。可以输入小数,如0.5 c显示进程启动命令完整路径 F/O指定某个字段进行排序 1显示所有CPU的运行状态 W将当前设置写入~/.toprc文件 使用交互式命令对输出形式调整好后,可以使用W命令进行保存。下次启动top程序时可自动加载此配置。如果想恢复默认配置,只需将配置文件~/.toprc删除即可。 3. 示例 【例1.1】在命令行中输入不带任何参数的top命令即可启动top程序。 top-14:59:02 up5:47,3 users,load average: 0.01, 0.03, 0.05 Tasks: 297 total, 1 running, 296 sleeping, 0 stopped, 0 zombie %CPU(s):0.0 us,0.0 sy,0.0 ni,100.0 id,0.0 wa,0.0 hi,0.0 si,0.0 st KiB Mem :26356841+total, 26121228+free,2104036 used, 252104 buff/cache KiB Swap:4194300 total,4194300 free,0 used. 26064505+avail Mem PID USERPRNIVIRTRESSHR S%CPU %MEM TIME+COMMAND 1825 ceph200 1136408 43672819100 S0.30.219:34.29 ceph-osd 1 root200192488 5460 2456 S0.00.0 0:07.85 systemd 5 root 0-20 000 S0.00.00:00.00 kworker/0:0H top命令的输出中共包含两部分,由空行隔开。中间的空行为交互式命令的命令提示栏,可输入交互式命令。 上半部分为系统的概要信息,共有5行,每行的具体含义如下。 第一行显示系统启动的时间,当前登录的用户数,在过去1min、5min、15min内系统的负载情况。 第二行显示进程或线程的运行情况,依次为所有进程数量、运行进程数量、休眠进程数量、停止进程数量和僵尸进程数量。这一行显示为进程还是线程取决于当前的运行模式,当为进程模式时, 显示当前正在运行的线程数 ; 当运行为线程模式时,Tasks将变为Threads。使用交互式命令H可以切换进程和线程模式。 第三行显示CPU的运行状态。us表示用户空间程序占用CPU的百分比,sy表示内核空间占用CPU的百分比,ni表示改变过优先级的进程占用CPU的百分比,id表示CPU空闲的百分比,wa表示I/O等待占用CPU的百分比,hi表示硬件中断占用CPU的百分比,si表示软件中断占用CPU的百分比,st表示虚拟化占用前虚拟机的时间。 第四行显示内存的使用情况,分别为总内存、空闲内存、已使用内存、缓冲和缓存占用的内存。这部分显示默认以KB为单位 ,可通过交互式命令E切换显示的单位。 第五行显示交换分区使用的情况,分别为总交换分区内存、空闲交换分区内存、已使用交换分区的内存 。最后一个为系统总的可用内存,会在空闲内存的基础上加上缓冲和缓存占用的内存等可以回收的内存。 下半部分显示系统中各个进程的详细情况。在显示的列表中,每一列的含义如下。  PID: 进程的ID。  USER: 运行程序的用户。  PR: 进程的优先级,内核空间使用。  NI: 进程的nice值,用户空间使用。nice值会影响进程的PR优先级。nice值的范围为-20~19,数值越小,优先级越高。程序运行过程中可对进程的nice值进行调节。  VIRT: 进程使用的总的虚拟内存。  RES: 进程实际占用的物理内存。  SHR: 进程占用的共享内存。  S: 进程的运行状况,R表示正在运行,S表示休眠,Z表示僵死状态。  %CPU: 进程CPU使用率。  %MEM: 进程占用的物理内存和总内存的百分比。  TIME+: 该进程启动后占用CPU的总时间。  COMMAND: 启动进程的命令。 【例1.2】在系统中运行CPU占用程序,使用top命令查看系统运行状态。 使用java CPUConsume 6启动程序,开启6个线程同时进入无限循环。启动top后,使用P交互指令按CPU使用率降序排序,使用c指令显示程序启动的完整命令。使用top命令查看输出如下: Tasks: 224 total, 1 running, 223 sleeping, 0 stopped, 0 zombie %CPU(s): 25.0 us,0.0 sy,0.0 ni, 75.0 id,0.0 wa,0.0 hi,0.0 si,0.0 st KiB Mem : 13186345+total, 13057746+free, 854732 used, 431264 buff/cache KiB Swap:0 total,0 free,0 used. 13023400+avail Mem PID USERPRNIVIRTRESSHR S%CPU %MEM TIME+COMMAND 4070 root20 0 35.269g4543211304 S599.3 0.0 1:39.30 java 4023 root20 0157820 2332 1552 R0.30.0 0:00.07 top 1 root20 0192324 5360 2508 S0.00.0 0:01.90 systemd 由以上输出的第3行可知,当前系统CPU用户空间占用25%,空闲75%。运行的 Java进程PID为4070,其虚拟内存为35.269GB,实际占用物理内存为45432KB,使用共享内存为11304KB,占用CPU为599.3%,因为程序内部启动了6个线程,因此CPU的6个核心可以同时并行处理这6个线程,进而将6个核心跑满。 【例1.3】在系统中运行磁盘I/O占用程序,使用top命令查看系统运行状态。 使用java DiskIOConsume 100启动程序,该程序开启了100个线程同时向磁盘写入数据。使用top命令查看输出如下: top-10:38:15 up 12:33,2 users,load average: 51.92, 15.71, 5.73 Tasks: 224 total, 1 running, 223 sleeping, 0 stopped, 0 zombie %CPU(s):0.5 us,2.4 sy,0.0 ni,0.7 id, 95.4 wa,0.0 hi,0.0 si,0.9 st KiB Mem : 13186345+total, 13019052+free,1149112 used, 523824 buff/cache KiB Swap:0 total,0 free,0 used. 12993879+avail Mem PID USERPRNIVIRTRESSHR S%CPU %MEM TIME+COMMAND 4115 root20 0 41.236g 32874811832 S91.70.2 0:37.04 java 707 root20 0214248 3640 2920 S 0.30.0 0:01.91 rsyslogd 4253 root20 0157820 2328 1548 R 0.30.0 0:00.06 top 1 root20 0192324 5360 2508 S 0.00.0 0:01.90 systemd 由以上输出的第三行可知,当前系统用户空间CPU占用0.5%,内核空间CPU占用2.4%,wa中参数显示I/O等待的CPU占比达到95.4%。一般I/O等待CPU占比过高说明当前系统I/O特别频繁,当前状态下磁盘I/O压力过大。 1.1.3htop命令 htop命令与top命令功能类似,是一个交互式的进程查看工具。htop与top相比其界面显示更加友好,操作更加人性化。htop与top的不同之处主要有以下几点。  htop界面显示更加直观,支持个性定制化。  htop支持鼠标操作。  htop支持彩色显示、主题选择等。  htop有滚动列表,可滚动查看完整内容。  htop直接通过界面结束某个进程。 1. 软件安装 htop并不是Linux系统中自带的命令,使用htop需要进行安装。在EPEL源中包含htop的安装包及依赖包信息,可通过EPEL源安装htop。 安装EPEL源命令如下: yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm-y 安装htop命令如下: yum install htop-y 安装完成后,输入htop命令,若显示htop主界面,则为安装成功。htop的主界面如图1.1所示。 图1.1htop的主界面 2. 命令选项 htop命令的格式如下: htop [选项] htop命令中的选项不太常用,一般直接输入htop命令即可。其各种选项功能在进入htop命令后,使用交互式操作都可以实现。htop命令的常用选项如表1.3所示。 表1.3htop命令的常用选项 选项说明选项说明 C以黑白色彩显示t指定两次数据刷新的间隔 d设置两次刷新时间间隔,单位为0.1su按用户过滤进程 h显示启动进程命令的完整路径p显示指定的进程 s按照某个字段排序显示v显示htop版本号 3. 主界面介绍 htop的主界面包括3部分,如图1.1所示。 其中顶部又分为左、右两部分,左边显示CPU的使用情况、内存的使用率、交换分区的使用率, 右边显示CPU的使用情况、运行的任务的总进程数、线程数以及正在运行的任务数。细心的读者可能会发现htop显示的进程数与top显示的进程数是不同的,这是因为htop默认隐藏了系统内核的进程,使得htop显示的进程数较少。 中间部分显示的是系统中各个进程的详细情况,这部分和top命令显示的基本相同。但是在htop中,这一部分中每一列的名称是可以用鼠标单击的,以实现对某一列数值的排序显示; 也可以单击某一行,从而选中某一个进程,实现对该进程进一步操作。 底部显示的是交互式命令的快捷键,分别为F1~F10及对应的功能。 4. 交互式命令 在主界面底部的交互式命令中,其功能都是自解释的。这些功能除了可以按相应的按键完成,还可以通过单击鼠标完成。 F1可查看帮助信息。在帮助信息中可知,除了自带的交互式命令,常用的命令还有M、P,可按照内存和CPU使用率进行排序。 F2键可对主界面显示的内容进行设置,其界面如图1.2所示。如在Meters选项中,可设置在主界面的 顶部需要显示的内容,还可以分别设置左边 和右边显示的内容。在Display options选项中,可以设置主界面显示的方式,如是否显示系统进程、是否以进程树模式显示、是否显示程序的路径等。在Colors选项中,可以设置系统的主题颜色。在Columns选项中,可以设置进程列表中每一列具体显示的内容,从而修改系统默认显示的内容。 图1.2htop设置界面 F3键可实现对某个进程按照名称进行搜索,使搜索出的结果处于选中状态,方便对该进程进行再次操作。 F4键为过滤功能,可通过该功能按照名称过滤出需要查看的进程。按Esc键可取消过滤操作。 F5键可实现进程树模式和排序模式的切换。在进程树模式中,各个进程之间的关系可通过树状结构显示。在排序模式中可按F6键选择排序的字段,将进程列表按照指定的字段排序后进行显示。此外还可以直接通过鼠标单击对应的字段名称实现排序。 F7/F8键可以加/减进程对应的nice值,通过修改进程的nice值,进而改变进程的优先级。 F9键可直接终止当前选中的进程,而不用像kill一样需要指定对应的进程id。 1.1.4vmstat命令 vmstat也是Linux自带的一个性能监控工具,vmstat为virtual memory statistics的缩写。虽然其名称为虚拟内存统计,但它也可以完成CPU、I/O等方面的监控。vmstat监控的是系统整体各个方面的指标,不能监控每个进程的具体情况。 1. 命令选项 vmstat的命令格式如下: vmstat [options] [delay [count]] vmstat命令在不加任何参数的情况下,默认输出的值为从系统启动到现在为止各个参数的平均值。count参数为输出的次数,delay参数为两次输出之间的间隔,单位为秒。如果只指定了delay参数而没有指定count参数,则会按照指定的延时时间一直输出。vmstat命令常用的选项如表1.4所示。 表1.4vmstat命令常用的选项 选项说明选项说明 a显示active/inactive 内存w每列的宽度加宽 m显示slabinfo信息p partition显示指定磁盘分区的统计数据 d显示磁盘统计数据S 指定输出的单位(k,K,m,M) 2. 示例 【例1.4】在命令行中输入不带任何参数的vmstat命令即可启动vmstat程序。其输出如下: [root@localhost test]# vmstat procs----------memory-------------swap-------io-----system--------CPU----- rbswpdfreebuffcachesisobiboincs us sy id wa st 1001277521220000101053 100 9000 vmstat的输出共分为 6部分,分别为procs、memory、swap、io、system、CPU,每部分的含义如表1.5所示。 表1.5vmstat输出每部分的含义 分组字段含义 procs r等待运行的进程数 b阻塞的进程数 memroy swpd已经使用虚拟内存的大小 free剩余的空闲内存 buff缓冲区占用内存大小 cache缓存占用内存大小 swap si每秒从swap分区交换到内存的大小,单位为KB so每秒从内存写入swap分区的大小,单位为KB io bi每秒从块设备接收到的块数 bo每秒发送到块设备的块数 system in系统每秒的中断,包含时钟中断 cs每秒上下文切换的次数 CPU us用户空间占用CPU的百分比 sy内核空间占用CPU的百分比 id空闲CPU的百分比 wa等待I/O的CPU占用百分比 st虚拟化消耗的CPU占比 【例1.5】运行CPU占用程序,使用vmstat进行监控。 使用命令java CPUConsume 100启动程序,同时运行100个线程占用CPU。使用vmstat进行监控,以MB为单位显示,每秒采样一次,共采样5次。 [root@localhost ~]# vmstat-S M 1 5 procs-----------memory-------------swap-------io-----system--------CPU----- rbswpdfreebuffcachesisobiboincs us sy id wa st 10800 127498184050001060430 951 0 10100 1274981840500020 21715 2127 86000 14 10000 127498184050000 23079 2183 91000 9 10000 127498184050000 21530 1974 83000 17 10000 127498184050000 21577 1956 85000 15 以上Java程序启动了100个线程同时运行,通过对vmstat的结果分析得到如下结论。 r列: 5s内当前系统等待运行的任务的数量为100左右,如果该值的输出长期大于系统的逻辑CPU的数量,则表示等待的进程或线程数比较多,CPU非常繁忙,此时CPU可能存在瓶颈。 b列: 系统当前阻塞的进程数为0,当此值较大时,需要具体分析阻塞的进程,查看系统是否处于正常状态。 swpd列: 系统使用虚拟内存数为0,如果swpd不为0,则表示可能物理内存不足,但是也需要一并观察si和so两列是否同时有内存页面进行交换。如果系统虚拟内存使用大于0,但是内存交换为0,则可能是在某一时间系统内存不足,后期有占用内存较大的进程结束,释放内存后,依然有部分其他进程数据在交换分区中。如果swpd使用较大,同时si、so交换频繁,则表示系统当前状态内存不足。 free列: 系统当前剩余的物理内存大小为127GB左右,如果系统频繁地使用交换分区,往往其free的值也剩余无几。 in列: 系统每秒中断的数量为22000左右。 cs列: 系统每秒上下文切换的次数为2000左右,如果此值过高,则说明系统上下文切换浪费了很多CPU资源,同时往往伴随着r列等待运行的进程数较多。因此这个数值应越小越好。 us列: 用户空间CPU时间占比为90%左右,用户空间占比越大说明CPU在用户进程消耗的时间越多,因此此值应较大为宜。 sy列: 内核空间CPU时间占比为0,一般情况下,该值不宜过大。 【例1.6】运行磁盘I/O占用程序,使用vmstat进行监控。 使用命令java DiskIOConsume 100启动程序,同时运行100个线程向磁盘写入数据。使用vmstat进行监控,以MB为单位显示,每秒采样一次,共采样5次。 [root@localhost ~]# vmstat-S M 1 5 procs-----------memory-------------swap-------io-----system--------CPU----- rbswpdfreebuffcachesisobiboincs us sy id wa st 1 1010 127138184960001086440 9510 0 1010 12713918494000 199208 5354 1926140 950 0 1010 12713918493000 168896 4771 1791130 960 0 1010 12713818493000 191488 4903 1655140 950 0 1010 12713218501000 193408 4744 1629142 931 以上Java程序启动了100个线程向磁盘写入数据,通过对vmstat的结果分析可知: b列显示当前系统阻塞任务数为101,同时bo列显示磁盘写入速率为190MB/s左右,wa显示当前CPU在I/O等待上消耗为95%左右。由此可见,当前系统正在大量写入数据,100多个任务阻塞,大量CPU资源浪费在等待I/O的操作上,此时可判定系统当前状态磁盘压力过大。 1.1.5iostat命令 虽然vmstat可以查看到磁盘的I/O情况,但是其显示的信息 ,如系统的哪块磁盘读写较高、等待I/O队列长度等却不是很详细。iostat是一个专门分析磁盘I/O的工具,可以查看 各种磁盘I/O的详细参数。 1. 软件安装 默认CentOS 7发行版中没有安装此工具,使用以下命令进行安装: yum install sysstat-y 安装完成后,输入iostat命令,检查是否安装成功。 [root@localhost ~]# iostat Linux 3.10.0-693.el7.x86_64 (localhost)12/05/2018_x86_64_(24 CPU) avg-CPU:%user%nice %system %iowait%steal%idle 3.770.000.051.510.1694.51 Device:tpskB_read/skB_wrtn/skB_readkB_wrtn vda9.116.052987.73289989143290900 2. 命令选项 iostat命令格式如下: iostat [options] [delay [count]] iostat命令在不加任何参数的情况下,默认输出的值为从系统启动到现在为止各个参数的平均值。count参数为输出的次数,delay参数为两次输出之间的间隔,单位为秒。如果只指定了delay参数而没有指定count参数,则会按照指定的延时时间一直输出。此用法与vmstat类似。iostat命令常用的选项如表1.6所示。 表1.6iostat命令常用的选项 选项说明 c只显示CPU状态信息 d只显示磁盘状态信息 k强制使用KB为单位 x显示更详细的信息 p device显示指定设备的信息 y如果多次显示,不显示第一次而显示从系统启动后的平均值 3. 示例 【例1.7】在命令行中输入iostat x命令启动iostat程序。其输出如下: [root@localhost ~]# iostat-x Linux 3.10.0-693.el7.x86_64 (localhost)12/05/2018_x86_64_(24 CPU) avg-CPU:%user%nice %system %iowait%steal%idle 3.720.000.051.490.1694.58 Device:rrqm/swrqm/sr/sw/srkB/swkB/s avgrq-sz avgqu-sz awaitr_awaitw_awaitsvctm%util vda0.000.150.148.845.962946.38657.492.01 222.452.35225.842.031.83 在输出中avgCPU一行输出的为多核CPU的平均信息,其内容与top中的CPU输出信息类似。 下半部分显示每一个块设备或分区的详细的读写信息。每一列的含义如下。  Device: 设备名称或分区名称。  rrqm/s: 发送到设备队列每秒合并的读请求数。  wrqm/s: 发送到设备队列每秒合并的写请求数。  r/s: 每秒完成的合并后的读请求数。  w/s: 每秒完成的合并后的写请求数。  rkB/s: 每秒读取的数据量。  wkB/s: 每秒写入的数据量。  avgrqsz: 每个请求的平均扇区数。  avgqusz: 平均请求队列长度。  await: 平均每次读写所需的时间。  r_await: 平均每次读需要的时间。  w_await: 平均每次写需要的时间。  svctm: 废弃指标。  util: 读写时间占总时间的百分比。 【例1.8】运行磁盘I/O占用程序,使用iostat进行监控。 使用命令java DiskIOConsume 100启动程序,同时运行100个线程向磁盘写入数据。使用iostat进行监控,以MB为单位显示,每秒采样一次,共采样3次。 [root@localhost ~]# iostat-myx 1 3 Linux 3.10.0-693.el7.x86_64 (localhost)12/20/2018_x86_64_(24 CPU) avg-CPU:%user%nice %system %iowait%steal%idle 0.540.004.1495.070.250.00 Device:rrqm/swrqm/sr/sw/srMB/swMB/s avgrq-sz avgqu-sz awaitr_await w_awaitsvctm%util vda0.000.000.00555.000.00184.52680.91127.92 258.400.00258.401.80 100.10 ... 以上Java程序启动了100个线程向磁盘写入数据,通过对iostat的结果分析可知: 当前系统CPU的I/O等待占比为95.07%,大量时间浪费在等待I/O的操作上。此时对系统的性能影响比较严重。系统当前vda设备每秒处理555次合并后的写请求,写入速度为184.52MB/s,平均队列长度为127.92,I/O等待时间为258.40ms,I/O时间占比为100.10%,由此可见系统当前I/O特别繁忙,I/O队列长度较长,每次I/O等待时间也较长。如果系统长期处于这种状态,则可能需要考虑提高I/O设备性能或优化程序性能。 1.1.6iftop命令 iftop是一个网卡流量的实时监控工具。通过iftop可以查看到当前系统网卡的实时流入流出流量。 iftop还可以监控当前系统与外界系统通信的流量情况,清晰直观地显示每一个外界系统流入流出的速率、IP地址等信息。使用iftop命令对于定位系统中的异常流量问题是十分简单有效的。 1. 软件安装 默认CentOS 7发行版本中没有安装此工具,安装iftop需要使用EPEL源,使用以下命令进行安装: yum install iftop-y 安装完成后,输入iftop命令,检查是否安装成功。 2. 命令选项 iftop命令格式如下: iftop [options] iftop命令在不加任何参数的情况下,默认显示第一块网卡的流量信息。iftop命令常用的选项如表1.7所示。 表1.7iftop命令常用的选项 选项说明选项说明 i指定需要监控的网卡 B以B为单位显示,默认显示的单位为b F显示特定网段的网卡流量信息 m调节顶部刻度的最大值,如iftop m 100m P显示端口号 n显示IP地址,不进行DNS反向解析 N只显示端口号,而不显示服务名。如ssh显示为22 3. 示例 【例1.9】在命令行中输入iftop nNP m 20m命令启动iftop程序。其输出如图1.3所示。 图1.3iftop输出界面 输出共分为3部分。顶部为刻度条,是中间部分和底部图形部分的参考刻度。 中间部分为系统与外界连接的信息,包括IP地址、端口和系统在2s、10s、40s内的数据传输速率。其中 =>为发送数据,<=为接收数据。 底部内容分为3行,即TX、RX、TOTAL,分别表示数据的发送、接收和全部的流量数据。cum列为从运行iftop以后 总共的流量数据。如在TX行中,cum列运行iftop以后,总共发送数据 329KB。peak为传输速率的峰值。rates为2s、10s、40s内的数据传输速率。 1.2Prometheus 1.1节中介绍了Linux中常见的性能监控工具,但是这些工具都是监控单台机器的某些特定的指标,无法从整体看到某 台机器的运行状态,也无法直观地以图表形式进行展示。本节介绍Prometheus监控系统,实现对机器的各项指标的监测,并以丰富的图形界面形式进行展示。 1.2.1Prometheus简介 Prometheus是一个开源的系统监控及报警工具,自2012年推出以来,许多公司都采用它搭建监控和报警系统。 它拥有非常活跃的开发人员和用户社区,在2016年加入了云原生计算基金会(CNCF),成为继Kubernetes之后的第二个托管项目。 1. Prometheus的特点  使用一系列由键值对组成的时间序列多维数据模型。  使用灵活的PromQL查询语言。  不依赖分布式存储系统,单节点自治。  通过HTTP的方式拉取时间序列数据。  支持向中间网关主动推送数据。  可通过服务发现或配置方式发现监控目标。  以多种图形方式或仪表盘的形式进行展现。 2. 适用场景 Prometheus适用于任何纯数字的时间序列数据,既适用于以机器为中心的监控,也适用于动态的面向服务的监控。Prometheus可以对各种服务进行监控,如SpringBoot、Spark。在微服务的监控中,其多维数据 的收集和查询成为一种特殊的优势。Prometheus不适合要求数据100%准确的场景,如作为计费系统使用,因为它收集的数据可能不够完整。 1.2.2Prometheus的组成 Prometheus生态系统由很多组件组成,最核心的组件为Prometheus server,其架构如图1.4所示。 图1.4Prometheus架构 Prometheus server负责定时的拉取时间序列数据,并将数据进行保存,对外提供HTTP接口供其他程序查询。 Exproter为一个应用程序,它将采集到的信息转换为Prometheus支持的格式,并对外提供接口,供Prometheus server拉取数据。监控不同类型的数据需要使用不同的Exporter,如监控服务器性能指标可以使用node_exporter,监控Java程序可以使用JMX exporter。Prometheus官方维护了部分常用的Exporter,同时有很多大量的第三方Exporter用于监控各种不同的应用程序。常用的Exporter列表可以参考官方文档,地址为https://prometheus.io/docs/instrumenting/exporters/。 Prometheus不仅可以主动拉取监控数据,还允许应用程序主动将监控数据进行推送,但是应用程序并不是直接将数据推送至Prometheus server中,而是推送至中间的网关称为Pushgateway。有些服务级别的应用程序可能运行时间很短,还没等Prometheus server来拉取数据,程序就结束了。在这种情况下,应用程序在结束的时候可以将数据推送至Pushgateway,Prometheus server再从Pushgateway中拉取数据,进而获取短时间运行任务的统计数据。 Prometheus将采集后的数据,使用一些可视化工具通过PromQL便可以对数据进行查询。如Prometheus自带的Web UI,还可以使用更强大的Grafana等对数据进行可视化的展示。 Prometheus除了可以对各种指标进行监测外,还可以实现报警的功能。通过编写特定的规则,当Prometheus采集到的数据满足规则时,便可以触发报警。Prometheus server本身并不提供报警的实现,其报警功能由Altermanager组件实现。Prometheus server把满足规则的报警事件推送给Altermanager,Altermanager将报警事件做后续处理,如发送邮件、推送至其他平台等。 1.2.3Prometheus的安装及配置 1. 安装 Prometheus安装比较简单,官方提供了已发布的二进制程序包,直接解压即可使用。下载地址为https://prometheus.io/download/。 将下载的安装包解压,并切换至软件目录: wget https://github.com/.../prometheus-2.6.0.linux-amd64.tar.gz tar xvfz prometheus-*.tar.gz cd prometheus-* 其目录下的prometheus即为可执行的二进制程序,prometheus.yml为配置文件。使用./prometheus即可加载当前目录下的配置文件,启动Prometheus。 2. 配置 打开prometheus.yml文件,其内容结构如下: global: scrape_interval: 15s evaluation_interval: 15s alerting: alertmanagers: -static_configs: -targets: #-alertmanager:9093 rule_files: #-"first_rules.yml" scrape_configs: -job_name: 'prometheus' static_configs: -targets: ['localhost:9090'] prometheus.yml文件整体分为4部分内容。global为全局配置,为其他的配置部分提供了默认值。如scrape_interval表示每隔多长时间拉取一次数据; evaluation_interval表示每隔多长时间对数据按照rules进行一次校验,查看是否有报警事件发生。 alerting配置部分为报警的配置,配置Altermanager的地址,当Prometheus server检查到有报警事件时,会根据alterting的配置,将事件推送到相应的Altermanager中。 rule_files配置相应的报警规则,每个规则可以指定一个单独的文件,其报警检查可以检查多个规则,一旦事件符合某个规则,则将事件推送至Altermanager中。 scrape_configs为最重要的部分,是拉取数据的配置部分。一个Prometheus server可以配置多个拉取的任务,每个任务被称为一个Job。通常一个Job由一组功能相同的target组成。如一个Job为监控所有的服务器指标,另一个Job为监控所有的Spark任务的指标。每个Job在配置文件中通过job_name区分,job_name必须是唯一的。static_configs用于配置当前Job的固定值,如拉取数据的地址、附加的标签等。targets 配置可以指定一组需要拉取数据的地址,这些地址都是exporter对外提供的接口的地址。 3. 启动 使用./prometheus命令启动Prometheus server。Prometheus server启动后,使用9090端口作为Web UI的HTTP服务的端口。如果该机器地址为192.168.99.6,则使用浏览器访问地址http://192.168.99.6:9090查看Prometheus server是否正常启动。 1.2.4监测服务器 1. 安装node_exporter 实现对服务器指标的监测需要使用采集服务器指标的Exporter,这个Exporter被称为node_exporter。官方的下载地址为https://prometheus.io/download/。下载完成后,将文件解压,直接运行其二进制文件node_exporter即可启动,其命令如下: wget https://... /download/v0.17.0/node_exporter-0.17.0.linux-amd64.tar.gz tar-zxvf node_exporter-0.17.0.linux-amd64.tar.gz cd node_exporter-0.17.0.linux-amd64 ./node_exporter 假如该机器的IP地址为192.168.99.6,node_exporter启动以后,默认使用本机的9100端口提供HTTP服务。使用浏览器访问地址http://192.168.99.6:9100/metrics,可查看启动是否正常,是否返回数据。使用curl访问该地址返回数据如下: [root@locahost]# curl http://localhost:9100/metrics |head-20 # TYPE go_gc_duration_seconds summary go_gc_duration_seconds{quantile="0"} 0.000188284 go_gc_duration_seconds{quantile="0.25"} 0.000188284 go_gc_duration_seconds{quantile="0.5"} 0.000305924 ... 2. 配置Prometheus server node_exporter安装完成后以后,即可配置Prometheus server,将targets配置为node_exporter的地址。其部分配置如下: scrape_configs: -job_name: 'node-status' static_configs: -targets: -192.168.99.6:9100 按照以上配置完成后,启动Prometheus server,Prometheus即可定时地到http://192.168.6.9100/metrics地址中拉取node_exporter采集到的数据。此外如果同一个Job中不同的机器拥有不同的属性,也可以使用labels添加自定义的属性。如在一个Job中都是监控的服务器的状态,而在服务器中有的为测试环境机器,有的为生产环境机器,使用labels标签可以进行区分。其实例配置如下: scrape_configs: -job_name: 'node-status' static_configs: -targets: -192.168.99.6:9100 labels: env: test -targets: -192.168.100.6:9100 labels: env: product 3. 查看监测指标 Prometheus server的Web UI界面提供了简单的指标查询功能,访问地址http://192.168.99.6:9090,选择指标为process_CPU_seconds_total,打开Graph选项卡,查看显示是否正常。其界面如图1.5所示。 图1.5Prometheus Web UI 1.3Grafana Prometheus完成了监测数据的采集、存储、报警等功能,但其对于采集到的指标在可视化方面显得有些单调,只能以表格或图标的形式进行简单的展示,对于重要的指标也不能够自定义面板显示。本节介绍Grafana的使用,通过Grafana实现后续的可视化展示。 1.3.1Grafana简介 Grafana是一个开源的度量分析和可视化的工具。其主要特点如下。 1. 可视化 Grafana拥有快速灵活的多选项的图表,可通过面板插件使用不同的方式实现对各种统计数据或日志进行可视化。 2. 报警 Grafana可以通过可视化的方式为重要的指标配置报警规则,它将自动地监控这些指标并在指标异常的时候发送通知。 3. 数据源统一 Grafana支持数十种数据库数据源,可以将各种数据整合在同一个平台中,在同一个面板中进行展示。 4. 扩展性 Grafana拥有数百个面板和插件库。这些插件库几乎可以完成各种常见数据的展示,并且该插件库还在不断地更新,添加新的功能。 Grafana通过接入不同类型的数据源,在其界面中 可以配置可视化面板,通过编写相应的查询语句,配置不同的面板,实现不同类型的数据展示,如折线图、饼状图、表格等方式。Grafana实现的功能如图1.6所示。 图1.6Grafana功能示意图 1.3.2Grafana的安装 1. 网络安装 Grafana官方提供rpm包,可以直接在CentOS中安装使用。可使用以下命令直接通过网络进行安装: yum install https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-5.1.4-1.x86_64.rpm 2. yum源安装 官方也提供了yum源,可通过yum源进行安装。在系统中创建文件/etc/yum.repos.d/grafana.repo,文件中写入yum源的地址,内容如下: [grafana] name=grafana baseurl=https://packagecloud.io/grafana/stable/el/7/$basearch repo_gpgcheck=0