在演示环境中,服务运行一段时间后,出现“没有子进程”的错误,ssh也无法登录,服务奔溃,演示环境不可用。
-bash: fork: retry: 没有子进程
-bash: fork: retry: 资源暂时不可用
出现该问题肯定是线程数量被占满了,导致服务器没有资源可用了,应该分析每个进程所占用的线程数,以及线程增长速度。
1.使用“ulimit -a
”命令查看本机的线程数有多少,其中“max user processes”表示最大线程数;
root@linx:~# ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 257234
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 65536
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 257234
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
2.查看当前总的的线程数,发现跟线程的总限额数很接近;
root@linx:/platform# ps -xH | wc -l
257230
3.使用命令查看线程数总量在前五的进程,发现进程“3055”的线程数量明显不合理;
root@linx:/platform# ps -xH | awk '{x[$1]++;} END{for(i in x) print(i ":" x[i])}' | sort -n -k 2 -t : -r | head -n 5
3055:80393
1469:2860
12305:1511
12306:1395
20126:1368
4.确认PID为“3055”的线程数量;
root@linx:/platform# pstree -p 3055 | wc -l
80392
5.确认PID为“3055”是Docker运行的的网关服务;
root@linx:/platform# docker inspect -f "{{.Id}} {{.State.Pid}} {{.Name}}" $(docker ps -q) | grep 3055
dc8ce63a2457ab2090ead648aea0939573a6b10bccd785341058bd2e8bb43c17 3055 /gateserver-gateserver-1
6.确认是统一网关日志模块有线程泄露。
docker中全部服务启动时,10多分钟的时间内,CPU占用都是100%
多发于在机器刚启动时,全部服务都因为docker自启动的原因同时启动,导致CPU占用100%。
原因是因为服务存在一条较长的依赖链,MySQL->Nacos->众多应用服务
在服务器刚启动时,因为大量服务同时启动,共同挤占了CPU资源,因此所有服务启动的都很缓慢
但一般情况下MySQL都能成功启动,但Nacos却不会,这是因为为了保证Nacos健康状态,通常会对Nacos设置健康检查,但又由于众多服务同时与Nacos抢资源,导致Nacos无法在健康检查期限内成功启动,Nacos无法启动又导致众多服务无法正常启动,从而不断重启,从而形成了死循环
Nacos设置健康检查时长加长一点,避免还没给够时长正常启动就又重启了;
为每个应用服务设置启动状态检测,即等待Nacos正常后才启动。
系统内存使用情况很高,如下命令输出所示:
# uptime
23:42:48 up 34 days, 13:21, 12 users, load average: 0.52, 0.75, 0.85
# free -h
total used free shared buff/cache available
Mem: 15Gi 12Gi 541Mi 1.1Gi 2.6Gi 1.7Gi
Swap: 29Gi 11Gi 18Gi
# top
top - 23:45:16 up 34 days, 13:24, 12 users, load average: 0.59, 0.68, 0.81
Tasks: 638 total, 2 running, 634 sleeping, 0 stopped, 2 zombie
%Cpu0 : 10.8 us, 3.3 sy, 0.0 ni, 83.0 id, 0.3 wa, 0.0 hi, 2.6 si, 0.0 st
%Cpu1 : 8.9 us, 4.0 sy, 0.0 ni, 85.5 id, 0.3 wa, 0.0 hi, 1.3 si, 0.0 st
%Cpu2 : 13.1 us, 2.9 sy, 0.0 ni, 82.7 id, 0.3 wa, 0.0 hi, 1.0 si, 0.0 st
%Cpu3 : 8.2 us, 3.6 sy, 0.0 ni, 87.3 id, 0.0 wa, 0.0 hi, 1.0 si, 0.0 st
MiB Mem : 15731.1 total, 529.8 free, 12563.0 used, 2638.3 buff/cache
MiB Swap: 30720.0 total, 19096.5 free, 11623.5 used. 1740.3 avail Mem
...
物理内存 16G 占用,SWAP 额外占用 11G 空间,排查内存系统使用情况,分析各个进程的内存占用情况。
查找进程id:top -d 2 -c
,按Shift+M 来按照 %MEM 排序 以快速定位使用内存较多的进程
1.查看JVM堆内存分配情况:jmap -heap pid(进程号)
2.查看占用内存比较多的对象: jmap -histo pid(进程号) | head -n 100
3.查看占用内存比较多的存活对象: jmap -histo:live pid(进程号) | head -n 100
使用Docker运行服务相当长的一段时间后,出现硬盘占用超高,接近100%;
root@linx:~# df -h
文件系统 容量 已用 可用 已用% 挂载点
udev 10M 0 10M 0% /dev
tmpfs 3.2G 9.2M 3.2G 1% /run
/dev/sda2 901G 841G 14G 98% /
tmpfs 7.8G 0 7.8G 0% /dev/shm
tmpfs 5.0M 4.0K 5.0M 1% /run/lock
tmpfs 7.8G 0 7.8G 0% /sys/fs/cgroup
/dev/sda1 511M 132K 511M 1% /boot/efi
tmpfs 1.6G 4.0K 1.6G 1% /run/user/119
overlay 901G 841G 14G 98% /var/lib/docker/overlay2/27076d0555ead7c7abd5bb45f058cc90af445bb8a95382ab61da5f6385729be3/merged
overlay 901G 841G 14G 98% /var/lib/docker/overlay2/691497cefac43dd117ec0e15c29cbf50de409244f70381978536f509f6169503/merged
overlay 901G 841G 14G 98% /var/lib/docker/overlay2/25d353358b213494c82a6bb7a5e179240b7804671755e3104c6093dd6dea0c31/merged
overlay 901G 841G 14G 98% /var/lib/docker/overlay2/8b775567d3ed5ab15282cd5f4b679bca400fa08c8f02728be761935eb4fb9c5b/merged
出现这种问题一般是Docker日志或者业务日志未加限制、Docker镜像或者Exited状态的容器太多、业务数据量占用过大这几种情况。
根据原因不同可以分为以下几种方式:
1.Docker的日志限制问题;
yuntu@node-01:~$ cat /etc/docker/daemon.json
{
"registry-mirrors": ["https://tjjv3zyc.mirror.aliyuncs.com"],
"exec-opts": ["native.cgroupdriver=systemd"],
"insecure-registries":["https://docker.ut.cn","https://docker.utpf.cn"],
"graph":"/yuntu/docker",
"log-driver":"json-file",
"log-opts": {"max-size":"500m", "max-file":"3"}
}
如果以上输出中没有”log-driver”、”log-opts”选项,则需要补充到daemon.json文件中,且需要重启Docker生效;
yuntu@node-01:~$ sudo systemctl daemon-reload
yuntu@node-01:~$ sudo systemctl restart docker
2.业务日志限制问题;
在Nacos中找到logback-common.properties配置,并且添加相应的限制配置。
3.Docker镜像或者Exited状态的容器太多
使用命令清理无用的镜像或容器;
root@linx:~# docker system prune -a
WARNING! This will remove:
- all stopped containers
- all networks not used by at least one container
- all images without at least one container associated to them
- all build cache
Are you sure you want to continue? [y/N] y
4.业务数据量过大;
在业务数据必须保留的情况下,只能通过增加硬盘来解决。
参考文章:
CPU、内存打满排查流程、JVMGC调优