
后端必备:如何排查问题以及jvm调优思路(一)
大家好,我是田螺。今天跟大家就CPU、磁盘、网络及内存方面的问题,聊聊如何排查和调优。
• CPU过高,怎么排查问题
• linux内存
• 磁盘IO
• 网络IO
• java 应用内存泄漏和频繁 GC
• java 线程问题排查
• 常用 jvm 启动参数调优
linux CPU 过高,怎么排查问题
CPU 指标解析
• 平均负载
◆ 平均负载等于逻辑 CPU 个数,表示每个 CPU 都恰好被充分利用。如果平均负载大于逻辑 CPU 个数,则负载比较重
• 进程上下文切换
◆ 无法获取资源而导致的自愿上下文切换
◆ 被系统强制调度导致的非自愿上下文切换
• CPU 使用率
◆ 用户 CPU 使用率,包括用户态 CPU 使用率(user)和低优先级用户态 CPU 使用率(nice),表示 CPU 在用户态运行的时间百分比。用户 CPU 使用率高,通常说明有应用程序比较繁忙
◆ 系统 CPU 使用率,表示 CPU 在内核态运行的时间百分比(不包括中断),系统 CPU 使用率高,说明内核比较繁忙
◆ 等待 I/O 的 CPU 使用率,通常也称为 iowait,表示等待 I/O 的时间百分比。iowait 高,说明系统与硬件设备的 I/O 交互时间比较长
◆ 软中断和硬中断的 CPU 使用率,分别表示内核调用软中断处理程序、硬中断处理程序的时间百分比。它们的使用率高,表明系统发生了大量的中断
查看系统的平均负载
•10:54:52 是当前时间;up 1124 days, 16:31 是系统运行时间;6 users 则是正在登录用户数。而最后三个数字依次是过去 1 分钟、5 分钟、15 分钟的平均负载(Load Average)。平均负载是指单位时间内,系统处于可运行状态和不可中断状态的平均进程数
•当平均负载高于 CPU 数量 70% 的时候,就应该分析排查负载高的问题。一旦负载过高,就可能导致进程响应变慢,进而影响服务的正常功能
•平均负载与 CPU 使用率关系
◆CPU 密集型进程,使用大量 CPU 会导致平均负载升高,此时这两者是一致的
◆I/O 密集型进程,等待 I/O 也会导致平均负载升高,但 CPU 使用率不一定很高
◆大量等待 CPU 的进程调度也会导致平均负载升高,此时的 CPU 使用率也会比较高
CPU 上下文切换
•进程上下文切换:
◆进程的运行空间可以分为内核空间和用户空间,当代码发生系统调用时(访问受限制的资源),CPU 会发生上下文切换,系统调用结束时,CPU 则再从内核空间 ◆换回用户空间。一次系统调用,两次 CPU 上下文切换
◆系统平时会按一定的策略调用进程,会导致进程上下文切换
◆进程在阻塞等到访问资源时,也会发生上下文切换
◆进程通过睡眠函数挂起,会发生上下文切换
◆当有优先级更高的进程运行时,为了保证高优先级进程的运行,当前进程会被挂起
•线程上下文切换:
◆同一进程里的线程,它们共享相同的虚拟内存和全局变量资源,线程上下文切换时,这些资源不变
◆线程自己的私有数据,比如栈和寄存器等,需要在上下文切换时保存切换
•中断上下文切换:
◆为了快速响应硬件的事件,中断处理会打断进程的正常调度和执行,转而调用中断处理程序,响应设备事件
查看系统的上下文切换情况:
vmstat 和 pidstat。vmvmstat 可查看系统总体的指标,pidstat则详细到每一个进程服务的指标
怎么排查 CPU 过高问题
•先使用 top 命令,查看系统相关指标。如需要按某指标排序则 使用 top -o 字段名 如:top -o %CPU。 -o 可以指定排序字段,顺序从大到小
• 找到相关进程后,我们则可以使用 top -Hp pid 或 pidstat -t -p pid 命令查看进程具体线程使用 CPU 情况,从而找到具体的导致 CPU 高的线程
◆ %us 过高,则可以在对应 java 服务根据线程ID查看具体详情,是否存在死循环,或者长时间的阻塞调用。java 服务可以使用 jstack
◆ 如果是 %sy 过高,则先使用 strace 定位具体的系统调用,再定位是哪里的应用代码导致的
◆ 如果是 %si 过高,则可能是网络问题导致软中断频率飙高
◆ %wa 过高,则是频繁读写磁盘导致的。
linux 内存
查看内存使用情况
• 使用 top 或者 free、vmstat 命令
• bcc-tools 软件包里的 cachestat 和 cachetop、memleak
◆ achestat 可查看整个系统缓存的读写命中情况
◆ cachetop 可查看每个进程的缓存命中情况
◆ memleak 可以用检查 C、C++ 程序的内存泄漏问题
free 命令内存指标
• shared 是共享内存的大小, 一般系统不会用到,总是0
• buffers/cache 是缓存和缓冲区的大小,buffers 是对原始磁盘块的缓存,cache 是从磁盘读取文件系统里文件的页缓存
• available 是新进程可用内存的大小
内存 swap 过高
Swap 其实就是把一块磁盘空间或者一个本地文件,当成内存来使用。swap 换出,把进程暂时不用的内存数据存储到磁盘中,并释放这些数据占用的内存。swap 换入,在进程再次访问这些内存的时候,把它们从磁盘读到内存中来
• swap 和 内存回收的机制
◆ 内存的回收既包括了文件页(内存映射获取磁盘文件的页)又包括了匿名页(进程动态分配的内存)
◆ 对文件页的回收,可以直接回收缓存,或者把脏页写回磁盘后再回收
◆ 而对匿名页的回收,其实就是通过 Swap 机制,把它们写入磁盘后再释放内存
• swap 过高会造成严重的性能问题,页失效会导致频繁的页面在内存和磁盘之间交换
◆ 一般线上的服务器的内存都很大,可以禁用 swap
◆ 可以设置 /proc/sys/vm/min_free_kbytes,来调整系统定期回收内存的阈值,也可以设置 /proc/sys/vm/swappiness,来调整文件页和匿名页的回收倾向
linux 磁盘I/O 问题
文件系统和磁盘
• 磁盘是一个存储设备(确切地说是块设备),可以被划分为不同的磁盘分区。而在磁盘或者磁盘分区上,还可以再创建文件系统,并挂载到系统的某个目录中。系统就可以通过这个挂载目录来读写文件
• 磁盘是存储数据的块设备,也是文件系统的载体。所以,文件系统确实还是要通过磁盘,来保证数据的持久化存储
• 系统在读写普通文件时,I/O 请求会首先经过文件系统,然后由文件系统负责,来与磁盘进行交互。而在读写块设备文件时,会跳过文件系统,直接与磁盘交互
• linux 内存里的 Buffers 是对原始磁盘块的临时存储,也就是用来缓存磁盘的数据,通常不会特别大(20MB 左右)。内核就可以把分散的写集中起来(优化磁盘的写入)
• linux 内存里的 Cached 是从磁盘读取文件的页缓存,也就是用来缓存从文件读写的数据。下次访问这些文件数据时,则直接从内存中快速获取,而不再次访问磁盘
磁盘性能指标
• 使用率,是指磁盘处理 I/O 的时间百分比。过高的使用率(比如超过 80%),通常意味着磁盘 I/O 存在性能瓶颈。
• 饱和度,是指磁盘处理 I/O 的繁忙程度。过高的饱和度,意味着磁盘存在严重的性能瓶颈。当饱和度为 100% 时,磁盘无法接受新的 I/O 请求。
• IOPS(Input/Output Per Second),是指每秒的 I/O 请求数
• 吞吐量,是指每秒的 I/O 请求大小
• 响应时间,是指 I/O 请求从发出到收到响应的间隔时间
IO 过高怎么找问题,怎么调优
• 查看系统磁盘整体 I/O
• 查看进程级别 I/O
• 当使用 pidstat -d 定位到哪个应用服务时,接下来则需要使用 strace 和 lsof 定位是哪些代码在读写磁盘里的哪些文件,导致IO高的原因
• strace 命令输出可以看到进程18940 正在往文件 /tmp/logtest.txt.1 写入300m
• lsof 也可以看出进程18940 以每次 300MB 的速度往 /tmp/logtest.txt 写入
