线上docker服务cpu100%的处理经历

前两天上线一个springboot服务(docker容器部署),服务启动成功后,cpu负载瞬间上来直接100%。这样的表现显然是程序某个地方有问题。

1.第一反应就是某个地方的逻辑形成了死循环。当时通过shell命令

top

显示


线上docker服务cpu100%的处理经历_第1张图片
image-20201122203110060.png

可以得到的信息是pid是340,但是有一个疑问就是无法确定对应的是哪个docker容器启动的服务。

2.通过docker命令

docker stats

打印出每一个容器对应的指标参数。类似下面这种:
image-20201122210429567.png

那么通过以上两个命令,就可以定位到底是哪个docker容器所承载的服务导致了cpu负载100%了。

既然已经定位到了具体哪个服务导致的问题,那么下一步就要定位具体是哪个线程导致的问题?

3.通过shell命令打印进程下所有线程的占用情况

top -H -p340

其中340就是第一步获得的pid--->340

类似下面这种:
线上docker服务cpu100%的处理经历_第2张图片
image-20201122211133339.png

查看cpu那一列,找到异常数据为100%的那一行,并记录。

4.通过docker命令

docker exec -it {容器id} /bin/bash

进入容器内部。因为是tomcat容器,也就意味着安装了JDK,那么可以使用jvm命令。

通过

jps

查看容器内正在运行的java服务。一般是只有一个服务:
线上docker服务cpu100%的处理经历_第3张图片
image-20201122212622415.png

那么咱们就可以直接通过以下命令打印线程堆栈

jstack -l 1 > pid.dump

1就是指的当前运行java服务的pid。

5.把以上pid.dump下载到本地,通过文本工具打开,结合【第三步】获取的信息,结果定位到具体的线程堆栈:
线上docker服务cpu100%的处理经历_第4张图片
image-20201122213226437.png

(实际上【第三步】可以明确是“pool-4-thread-3”这个线程导致cpu负载100%)

看以上截图可知,问题出在TagHeartbeatCheckThread这个类的第55行。

6.根据提示,查看代码:
线上docker服务cpu100%的处理经历_第5张图片
image-20201122213651686.png

RfidDataCache这个是一个本地缓存,如果本地缓存为空,那么便会导致死循环。问题定位已经完成。

7.根据上面一系列的操作及问题定位,已经可以定位到问题产生的具体原因。想要解决这个问题,可以在判断本地缓存为空的时候,让线程睡眠2秒,降低cpu的负载;或者使用阻塞队列的方式,让线程等待直至本地缓存数据不为空。

你可能感兴趣的:(线上docker服务cpu100%的处理经历)