在之前的常见的Java问题排查方法一文中,没有写cpu iowait时的排查方法,主要的原因是自己之前也没碰到过什么cpu iowait高的case,很不幸的是在最近一周连续碰到了两起cpu iowait的case,通过这两起case让自己学习到了很多系统层面的知识,也许这些知识对于熟悉系统的人来说没什么,不过对于写Java的同学我觉得还是值得分享下(由于Java基本不用于存储类型的场景,所以通常来说碰到iowait高的机会会比其他几类问题更低很多)。

当出现iowait高时,最重要的是要先找出到底哪个进程在消耗io,以最快的速度解决问题,但linux默认的一些工具例如像top、iostat等都只能看到io的消耗状况,但对应不到是哪个进程在消耗,比较好用的用来定位的工具是iotop,不过有些环境要装上可能不太容易,装上了后直接执行iotop,就可以看到到底是哪个进程消耗了比较多的io,对应解决问题而言,通常在找到进程后杀掉基本就算解决了(还有一种方法是通过打开syslog以及blk_dump来看一段时间内消耗io的进程,但在我的两个case里试过效果不太理想)。

但通常而言,上面的方法只能算勉强解决了问题,但还是没有定位到程序里哪个地方有问题,甚至有可能重启仍然iowait很高,于是需要借助其他工具来进一步排查,所幸系统层面是有这样的工具,主要可通过blktrace/debugfs来定位到到底是读或写哪个(或哪些)文件造成了iowait高(这个方法主要学习自阿里集团内核组的伯瑜的一篇blog)。

在装上了blktrace后,先mount -t debugfs none /sys/kernel/debug下,然后可通过iostat查看到底是哪个设备在消耗io,例如假设看到是sda在消耗,那么即可执行blktrace /dev/sda,在执行时将会自动在执行的目录下生成一些sda.blktrace.*的文件,当觉得采集的差不多后,即可ctrl+c停掉。

之后执行blkparse sda.blktrace.* > result.log,再生成了result.log后执行grep ‘A’ result.log | head -n 5看看在采集的这段过程中,消耗io比较多的地方在哪,例如在我碰到的case中执行后看到的为:
8,0 11 1 0.000071219 248366 A R 218990140 + 16 <- (8,9) 148994872
8,0 11 1 0.000071219 248366 A R 218990140 + 16 <- (8,9) 148994872
8,0 11 1 0.000071219 248366 A R 218990140 + 16 <- (8,9) 148994872
8,0 11 1 0.000071219 248366 A R 218990140 + 16 <- (8,9) 148994872
8,0 11 1 0.000071219 248366 A R 218990140 + 16 <- (8,9) 148994872
这里A后面的R到底的意思是读(如果是写则为WS),和之前iostat看到的是一样的,io主要是大量的读造成的。

通过上面的信息8,0和(8,9)可以看到主要的消耗是在sda9(这个通过iostat也可以看到),(8,9)后的148994872代表读的扇区号。

再通过debugfs -R ‘stats’ /dev/sda9 | grep ‘Block size’可以找到sda9的block size,在我碰到的case中block size是4096,也是通常ext2/ext3文件系统默认的。

每个扇区的大小为512,148994872/(4096/512) = 18624359即可找到文件系统上对应的block号,之后通过debugfs -R ‘icheck 18624359′ /dev/sda9可找到对应的inode,在我碰到的case中,执行后的结果为:
Block Inode number
18624359 18284971
而debugfs还提供了通过inode number找到具体的文件的功能,于是就好办了,继续执行debugfs -R ‘ncheck 18284971′,执行后看到类似如下的信息:
Inode Pathname
18284971 [相应的文件名]
在找到了文件名后就好办了,可结合之前的iotop或直接lsof找出对应的进程id,然后就可以看看从代码上层面怎么避免对此文件的大量读。

除了上面的这种case外,还有些情况的iowait其实是比较简单的,例如读写了巨大的文件(通常在大量出现异常时可能会出现)…

在解决上周碰到的两个cpu iowait高的case中,其中一个是如上面的业务代码造成,但另一个则是和raid卡配置相关,因为从iostat来看,当时写的量也不是很大,但iowait却比较高,请系统的人帮忙看了后,告诉我是因为raid卡写策略配置的问题,我之前对raid卡的这些配置完全不懂。

通过服务器上会带有raid卡,而现在的raid卡基本是带有cache的,为了保障cache里的数据的安全性,通常raid卡会带有电池或电容,相对而言电容的故障率比较低,raid卡会提供写策略的配置,写策略通常是Write Back和Write Through两种,Wirte Back是指写到cache后即认为写成功,Write Through是指写到磁盘上才算成功,通常Raid卡的写策略会分为正常时,以及电池或电容出问题时两种来配置,而在碰到的case中是因为配置了当电池/电容出问题时采用Write Through,当时机器的Raid卡的电池出故障了,所以导致策略切换为了Write Through,能够支撑的iops自然是大幅度下降了,而在我们的场景中,本地数据丢掉是无所谓的,所以Raid卡的策略可以配置为即使电池出故障了也仍然采用Write Back。

通常各种Raid卡都会提供工具来配置写策略,例如HP卡的hpacucli,可通过cat /proc/scsi/scsi查看硬盘和Raid卡的信息(可以先用cat /proc/mdstat来查看raid信息),有助于确认raid卡的cache/cache容量/电池以及硬盘本身能支撑的iops等。

因为建议在碰到iowait高的场景时,可以先看看raid卡的写策略,如果没问题的话再通过iotop、blktrace、debugfs、lsof等来定位到具体的根源。

可见即使是对于Java的同学,在排查问题时对于各种系统工具、硬件层面的一些知识还是要有些了解,不一定要很深,但至少要知道,对于工具要会用。

cpu iowait高排查的case的更多相关文章

  1. Java进程CPU使用率高排查

    Java进程CPU使用率高排查 生产java应用,CPU使用率一直很高,经常达到100%,通过以下步骤完美解决,分享一下.1.jps 获取Java进程的PID.2.jstack pid >> ...

  2. mysql CPU太高排查办法

    [1]问题描述 首先,查看top,下图来自网络 为什么会有%CPU 375??? 还可以超过100%的? 这是因为,有多核CPU.如图,top后,按数字1,即可出现下图. [2]排查办法(当前CPU爆 ...

  3. erlang 虚机CPU 占用高排查

    -问题起因 近期线上一组服务中,个别节点服务器CPU使用率很低,只有其他1/4.排除业务不均,曾怀疑是系统top统计错误,从Erlang调度器的利用率调查 找到通过erlang:statistics( ...

  4. JAVA服务cpu占用高排查

    最近线上机器偶尔有台cpu达到100%,还居高不下.同样负载的其他机器却正常,我想肯定是代码哪里有问题了 首先我们top看下 可定位到对应占用高的PID 然后=>ps -mp PID -o TH ...

  5. Java线上应用故障之CPU占用高排查与定位

    最近线上频繁报警CPU空闲不足,故紧急排查后分享给大家 1.使用top命令,获取占用CPU最高的进程号 2.查看线程号对应的进程信息 命令:ps -ef|grep 22630 3.查看进程对应的线程信 ...

  6. SQL SERVER占用CPU过高排查和优化

    操作系统是Windows2008R2 ,数据库是SQL2014 64位. 近阶段服务器出现过几次死机,管理员反馈机器内存使用率100%导致机器卡死.于是做了个监测服务器的软件实时记录CPU数据,几日观 ...

  7. JAVA 消耗 CPU过高排查方法

    #找出cpu占用最高的进程top -H#再次确定进程ps aux|grep 17408 #查看进程的线程(tid) ps -mp 17408 -o THREAD,tid,time#将线程转换为十六进制 ...

  8. java程序——CPU过高100%及内存泄露排查

    CPU过高 这类问题可以使用 top 命令观察一些,CPU 是不是都被 Java 程序占用了.比如下面这个截图: 服务器的 CPU 大多都被 Java 占用了.这正是我们之前生产上 CPU 过高的一个 ...

  9. SQLSERVER排查CPU占用高的情况

    SQLSERVER排查CPU占用高的情况 今天中午,有朋友叫我帮他看一下数据库,操作系统是Windows2008R2 ,数据库是SQL2008R2 64位 64G内存,16核CPU 硬件配置还是比较高 ...

随机推荐

  1. asp.net core 系列 6 MVC框架路由(下)

    一.URL 生成 接着上篇讲MVC的路由,MVC 应用程序可以使用路由的 URL 生成功能,生成指向操作的 URL 链接. 生成 URL 可消除硬编码 URL,使代码更稳定.更易维护. 此部分重点介绍 ...

  2. Linux~连接windows的ftp,unzip出现的问题

    在linux进行连接windows下的ftp服务器 ftp://192.168.2.71 输入用户名和密码登陆成功

  3. MySQL系列--1.安装卸载与用户权限管理

    MySQL安装 1.Ubuntu18下安装MySQL sudo apt-get install mysql-server MySQL的版本为5.7.25 2.登录MySQL 采用mysql-serve ...

  4. Asp.Net Core 程序部署到Linux(centos)生产环境(一):普通部署

    运行环境 照例,先亮底 centos:7.2 cpu:1核 2G内存 1M带宽 辅助工具:xshell xftp 搭建.net core运行环境 .net core 的运行环境我单独写了一篇,请看我的 ...

  5. Struts2【UI标签、数据回显、资源国际化】

    Struts2UI标签 Sturts2为了简化我们的开发,也为我们提供了UI标签...也就是显示页面的标签..... 但是呢,Struts2是服务端的框架,因此使用页面的标签是需要在服务器端解析然后再 ...

  6. jmeter 压测常见的几种报错

    一. socket closed 问题原因:在JMeter下,发送http 请求时,一般都是默认选择了use keepAlive,这个是连接协议,JMeter坑就在这里,默认勾选了这个(如果不勾选的话 ...

  7. RESTful杂记

    在网上找了许久的关于REST的资料,发现网上大部分都是说的比较片面,虽然有部分说出了本质,但也没有详细提出,所以在这里记录一下. RESTful是什么 首先,维基百科是这样说的: 表现层状态转换(RE ...

  8. Python批量修改寄存器的值

    在写代码过程中,我们修改代码中寄存器的值,但是有时寄存器的数据较多,手动修改容易出现错误而且花费的时间长 这是一段寄存器的配置值: 0x00, 0x34  0x35, 0x25  0x10, 0xd4 ...

  9. 基于C#&.net2.0的windows服务创建与安装

    起因:一台服务器中部署的程序,停电后未按照计划任务正常启动. 一.创建并配置Windows服务程序 开发工具VS2015 Framework版本2.0 1.新建Windows服务 2.在Service ...

  10. vb.net連接SQL数据库

    '導入命名空間Imports System.Data.SqlClient '定義變量 Dim Sql As String 'SQL字串 Dim Sqlado As SqlConnection '连接数 ...