一、磁盘空间不足问题

1、先用 df -h 从总体查看磁盘状态

文件系统                 容量  已用  可用 已用% 挂载点
devtmpfs 1.6G 0 1.6G 0% /dev
tmpfs 1.7G 0 1.7G 0% /dev/shm
tmpfs 1.7G 170M 1.5G 11% /run
tmpfs 1.7G 0 1.7G 0% /sys/fs/cgroup
/dev/mapper/centos-root 50G 16G 35G 32% /
/dev/sda2 1014M 198M 817M 20% /boot
/dev/mapper/centos-home 877G 32G 846G 4% /home
tmpfs 329M 0 329M 0% /run/user/0

 tmpfs 类型的是 linux 的内存型文件系统,里面的数据是放在内存中的

一般就是看挂载点为根目录的 / 的容量,这里我只用了 32%、20%、4%,显然还没有达到瓶颈,但如果这里太大了,还要进一步看看是哪个目录大了。

2、此时用du -sh * 命令,查看 / 路径下的各个文件和目录的大小

7.6G    CentOS-7-aarch64-Everything-2009.iso
12K construn
du: 无法访问"data/docker/overlay2/6a14da0db0e3802e98fb82e44ce6f66a93506ebfb195a7e8d2b72f33d2ab9353/merged": 没有那个文件或目录
8.9G data
0 docker
28K elk
337M ESXi-6.7.0-集成网卡镜像.iso
0 ftp
16K git
28K install.sh
298M jenkins
13G ll
0 log
21M node-v14.15.3-linux-x64.tar.xz
213M Python
90M Python-3.8.3
23M Python-3.8.3.tgz
0 tomcat
4.5M wget-log
4.5G work
0 wukong_data
12K www
496M yapi

找到最大的那个目录,进去,再次执行这个命令,直到找到最终占地面积特别大的文件或目录为止。

如果里面全都是普通文件,也可以用 ls -lh 命令,它的输出会更丰满一些

二、CPU 与内存使用率过高问题

1、top命令

top - 09:33:23 up 47 days, 19:29,  1 user,  load average: 0.32, 0.21, 0.20
Tasks: 178 total, 1 running, 175 sleeping, 0 stopped, 2 zombie
%Cpu(s): 3.7 us, 0.7 sy, 0.0 ni, 95.6 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 3362012 total, 392352 free, 2012588 used, 957072 buff/cache
KiB Swap: 3538940 total, 2668284 free, 870656 used. 869176 avail Mem

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
600 polkitd 20 0 1597308 40592 4704 S 1.0 1.2 254:39.36 mongod
685 readonly 20 0 1505348 235176 5528 S 0.3 7.0 83:07.98 node
842 readonly 20 0 4824484 398444 6252 S 0.3 11.9 258:15.66 java
922 root 20 0 4407232 499548 6284 S 0.3 14.9 49:55.13 java
19070 root 20 0 878028 5812 2432 S 0.3 0.2 46:13.79 BT-Task
26451 root 20 0 162152 2304 1528 R 0.3 0.1 0:00.08 top

下面的列表表示不同进程(PID)所占用的资源情况

PID 表示容器ID

VIRT 表示使用的虚拟内存数量,RES 表示使用的物理内存数量,SHR

S 表示进程的状态,下面的值 S 表示睡眠,D 表示不可中断睡眠,R

%CPU 表示CPU使用率,%MEM 自然就是内存使用率,看这俩值可以一目了然看谁占用的资源过高了。

TIME

COMMAND

如果专门看 Java 进程的情况,可以先 jps

19063 jar
1575 Bootstrap
21263 Jps

然后再 top -p 19063 专门看这个 Java 进程的情况

如果再细化到线程,可以加个 -H 参数,top -p 19063 -H

当然,top 命令已经可以分析内存了,如果想单独分析下内存,可以用小而美的命令,free -h

total        used        free      shared  buff/cache   available
Mem: 3.2G 1.9G 365M 189M 940M 836M
Swap: 3.4G 839M 2.6G

这些参数的含义是:

total:内存总数

used:已经使用内存数

free:完全空闲内存

shared:多个进程共享的内存

buffers:用于块设备数据缓冲,记录文件系统 metadata(目录,权限,属性等)

cached:用于文件内容的缓冲

available:真正剩余的可被程序应用的内存数

一共有两行,mem 和 swap,mem 就是内存大小,swap 是交换区,是在物理磁盘上的一块区域,当内存不够用时,可以用这部分区域当内存。

可以用 swapon

NAME      TYPE      SIZE USED PRIO
/dev/dm-1 partition 3.4G 839M -2

三、网络延迟

1、netstat -a 查看所有连接中的 socket。

Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:ddi-tcp-1 0.0.0.0:* LISTEN
tcp 0 0 localhost:smtp 0.0.0.0:* LISTEN
tcp 0 0 localhos:opsession-prxy 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:ssh 0.0.0.0:* LISTEN
tcp 0 0 c1:ddi-tcp-1 192.168.0.196:6652 ESTABLISHED
tcp 0 0 c1:ddi-tcp-1 192.168.0.196:13867 ESTABLISHED
tcp 0 0 localhost:50356 localhos:opsession-prxy ESTABLISHED
tcp 0 0 localhos:opsession-prxy localhost:50356 ESTABLISHED
tcp 0 256 c1:ssh 192.168.0.90:55549 ESTABLISHED
tcp 0 0 c1:ddi-tcp-1 192.168.0.196:2194 ESTABLISHED
tcp 0 0 c1:ddi-tcp-1 192.168.0.196:14426 ESTABLISHED
tcp 0 0 c1:ddi-tcp-1 192.168.0.196:scenidm ESTABLISHED

2、用 netstat -tnpa

Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:8888 0.0.0.0:* LISTEN 19085/python
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 490/master
tcp 0 0 127.0.0.1:3307 0.0.0.0:* LISTEN 21686/mysqld
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1057/sshd
tcp 0 0 192.168.0.70:8888 192.168.0.196:6652 ESTABLISHED 19085/python
tcp 0 0 127.0.0.1:50526 127.0.0.1:3307 TIME_WAIT -
tcp 0 0 192.168.0.70:8888 192.168.0.196:13867 ESTABLISHED 19085/python
tcp 0 0 127.0.0.1:50356 127.0.0.1:3307 ESTABLISHED 21347/httpd
tcp 0 0 127.0.0.1:3307 127.0.0.1:50356 ESTABLISHED 21686/mysqld
tcp 0 208 192.168.0.70:22 192.168.0.90:55549 ESTABLISHED 20707/sshd: root@pt
tcp 0 0 192.168.0.70:8888 192.168.0.196:2194 ESTABLISHED 19085/python
tcp 0 0 192.168.0.70:8888 192.168.0.196:14426 ESTABLISHED 19085/python
tcp 0 0 192.168.0.70:8888 192.168.0.196:7128 ESTABLISHED 19085/python

得到进程号后就好说了配合 top 命令,ps -ef 命令,查看相关进程信息。

不过这些自带的网络命令,都不太灵活,一般我们有直观查看实时流量,然后进行一波统计分析的需求,这里介绍一个酷酷的命令。

输入 iftop -P

系统线上问题排查_linux

中间的 <= => 这两个左右箭头,表示的是流量的方向。

TX:发送流量

RX:接收流量

TOTAL:总流量

Cumm:运行 iftop 到目前时间的总流量

peak:流量峰值

rates:分别表示过去 2s 10s 40s 的平均流量

当然这些是从机器上的,如果是一个接口响应耗时过长,一方面可能是由于机器本身所在的网络有问题。

一般这种问题也就是运维同学去解决,或者我们单节点重启一下,换台机器,就搞定了。

还有可能是服务提供方业务耗时严重,这个就需要去排查服务提供方的日志,机器负载,连接池占用情况等,分析问题,这也是我们平时开发碰到的主要问题。

四、Java 程序的问题分析

1、用 jmap -dump 分析堆内存中的快照

2、用 jmap -heap 查看堆内存设置与当前使用情况

3、用 jstack 查看 jvm 线程运行信息,上传到 fastthread.io 这个网站,直观地看一下,

一个线程需要占用大约 1M 的空间吧,而且不是占用 jvm 的内存空间,而是会占用操作系统空闲的内存空间。

我们的机器内存是 8G,堆内存占了 6G,线程数这么多快超过 2G 了,再加上操作系统里其他程序占用的内存,内存告警很正常,甚至可能 OOM。

所以,一方面我们可以减少线程数,另一方面可以把堆内存配置得小一点,使得堆内存加上线程占用的操作系统内存,不要超过 8G。

五、一些无法本地 debug 的调试技巧

有的时候线上忘记在关键节点打日志了,会导致一些问题,比如不知道方法入参的值,不知道某方法中具体某一步的耗时。

我一般用阿里的一款贼牛逼的工具 arthas 来排查。

先申请个线上机器的接近 root 的权限,然后把 arthas 工具下载到机器上,可以直接机器上下载:

wget https://alibaba.github.io/arthas/arthas-boot.jar

使用 watch 命令可以实时观察一个方法的入参和出参。

使用 trace 命令可以跟踪某个方法的耗时,而且可以深入这个方法所调用的方法的各个耗时。

当然我就只用这俩功能,用作忘记打日志时的临时方案了,属于高射炮打蚊子。

实际上人家的功能超级强大,比如 dashboard 全局监控,thread 查看所有线程信息,包括状态和 CPU 使用率,thread -b 甚至可以直接定位到死锁信息,jad 命令进行反编译,ognl 命令查看某一个对象的具体值,大家可以去网上学习下。