前端传入大字符串 进行加密 导致字符串常量池中内存占用过大 频繁gc 导致系统挂掉怎么解决
1条回答 默认 最新
- 小P聊技术 2021-06-28 16:50关注
java大对象引发的频繁full gc及cpu飙高的调优历程
问题描述
linux系统,执行top命令
-bash-4.2# top top - 08:57:47 up 147 days, 23:08, 2 users, load average: 67.32, 60.83, 58.97 Tasks: 1310 total, 2 running, 1307 sleeping, 0 stopped, 1 zombie %Cpu(s): 48.9 us, 1.2 sy, 0.0 ni, 49.6 id, 0.2 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem : 56109344+total, 1076992 free, 49768768 used, 51024771+buff/cache KiB Swap: 0 total, 0 free, 0 used. 50798355+avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 70853 root 20 0 71.947g 0.031t 20088 S 6978 6.0 11566:28 java 30632 root 20 0 43.589g 1.229g 12108 S 68.9 0.2 9335:55 java 2135 root 20 0 160600 46492 832 R 13.7 0.0 4648:46 statmon 4219 root 20 0 99.287g 2.030g 11576 S 2.9 0.4 747:32.73 java 59325 root 20 0 158752 3552 1588 R 2.5 0.0 0:00.70 top 57806 root 0 -20 0 0 0 S 1.9 0.0 0:01.70 kworker/18:2H 10 root 20 0 0 0 0 S 0.6 0.0 313:00.57 rcu_sched 129997 root 20 0 44.030g 3.102g 11992 S 0.6 0.6 2840:59 java
上述70853这个进程,占用过高的cpu,而且程序运行缓慢,重启之后就正常了,运行一段时间之后又是这样。
问题排查
线程使用cpu排查
首先遇到cpu彪高的问题,我们要先定位是哪些线程在持有这些cpu,采用top -Hp pid命令可以查看线程的cpu使用情况
bash-4.2# top -Hp 70853 top - 09:03:01 up 147 days, 23:13, 2 users, load average: 39.88, 48.75, 54.03 Threads: 601 total, 93 running, 508 sleeping, 0 stopped, 0 zombie %Cpu(s): 43.2 us, 11.3 sy, 0.0 ni, 45.0 id, 0.3 wa, 0.0 hi, 0.1 si, 0.0 st KiB Mem : 56109344+total, 878212 free, 49768532 used, 51044672+buff/cache KiB Swap: 0 total, 0 free, 0 used. 50798249+avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 70866 root 20 0 71.948g 0.032t 20104 R 80.4 6.0 79:06.89 java 70906 root 20 0 71.948g 0.032t 20104 R 80.4 6.0 78:58.43 java 70921 root 20 0 71.948g 0.032t 20104 R 80.4 6.0 78:58.79 java 70856 root 20 0 71.948g 0.032t 20104 R 80.1 6.0 79:01.84 java 70859 root 20 0 71.948g 0.032t 20104 R 80.1 6.0 78:57.72 java 70863 root 20 0 71.948g 0.032t 20104 R 80.1 6.0 79:06.32 java 70865 root 20 0 71.948g 0.032t 20104 R 80.1 6.0 79:09.23 java 70872 root 20 0 71.948g 0.032t 20104 R 80.1 6.0 78:52.49 java 70875 root 20 0 71.948g 0.032t 20104 R 80.1 6.0 79:02.85 java 70877 root 20 0 71.948g 0.032t 20104 R 80.1 6.0 79:04.04 java 70879 root 20 0 71.948g 0.032t 20104 R 80.1 6.0 79:07.52 java 70881 root 20 0 71.948g 0.032t 20104 R 80.1 6.0 79:00.38 java
上述是一系列的该进程下的线程使用cpu的情况,并且省略了一部分,将上述pid下面的十进制的线程id转成16进制,如下:
-bash-4.2# printf "%x\n" 70856 114c8
线程堆栈排查
上述排查到了哪些线程使用cpu率高,那么这些cpu到底在干什么呢?可以使用jstack pid命令查看jvm的线程堆栈
gc动态监控
上述线程堆栈查看,发现线程大部分在执行gc回收,这就奇怪了,为什么一直在gc,具体查看gc的情况,可以使用jstat -gcutil pid
-bash-4.2# jstat -gcutil 70853 1000 S0 S1 E O M CCS YGC YGCT FGC FGCT GCT 0.00 0.00 99.90 99.98 92.68 88.47 11534 1351.766 2466 4811.444 6163.210 0.00 0.00 99.99 100.00 92.68 88.47 11534 1351.766 2467 4813.394 6165.160 0.00 0.00 99.99 100.00 92.68 88.47 11534 1351.766 2467 4813.394 6165.160 0.00 0.00 99.96 100.00 92.68 88.47 11534 1351.766 2468 4815.426 6167.192 0.00 0.00 99.96 100.00 92.68 88.47 11534 1351.766 2468 4815.426 6167.192 0.00 0.00 100.00 99.99 92.68 88.47 11534 1351.766 2469 4817.455 6169.221 0.00 0.00 100.00 99.99 92.68 88.47 11534 1351.766 2469 4817.455 6169.221 0.00 0.00 99.96 99.99 92.68 88.47 11534 1351.766 2470 4819.330 6171.096 0.00 0.00 99.96 99.99 92.68 88.47 11534 1351.766 2470 4819.330 6171.096 0.00 0.00 100.00 100.00 92.68 88.47 11534 1351.766 2471 4821.328 6173.094 0.00 0.00 100.00 100.00 92.68 88.47 11534 1351.766 2471 4821.328 6173.094 0.00 0.00 99.99 100.00 92.68 88.47 11534 1351.766 2472 4823.229 6174.995 0.00 0.00 99.99 100.00 92.68 88.47 11534 1351.766 2472 4823.229 6174.995 0.00 0.00 99.97 99.97 92.68 88.47 11534 1351.766 2473 4825.121 6176.888 0.00 0.00 99.97 99.97 92.68 88.47 11534 1351.766 2473 4825.121 6176.888 0.00 0.00 100.00 99.99 92.68 88.47 11534 1351.766 2474 4827.092 6178.859 0.00 0.00 100.00 99.99 92.68 88.47 11534 1351.766 2474 4827.092 6178.859 0.00 0.00 99.96 99.99 92.68 88.47 11534 1351.766 2475 4829.041 6180.807 0.00 0.00 99.96 99.99 92.68 88.47 11534 1351.766 2475 4829.041 6180.807 S0,S1:新生代的两个幸存者区 E:新生代的伊甸园区 O:老年代 YGC:新生代gc FGC:full gc
上述主要指标解释
S0,S1:新生代的两个幸存者区
E:新生代的伊甸园区
O:老年代
YGC:新生代gc
FGC:full gc
通过上述排查,可以发现,一直在full gc,并且老年代内存并没有回收,致此,内存泄露了。
堆内存查看占用内存的对象
采用jvisiual命令查看heap dump
上图所示被ScheduledThreadPoolExecutor中的优先级队列持有。
代码分析
逻辑是这样的,视图库接收前端实卡传来的图片,高清图片,大概有几百kb到十几M不等,采用1400标准接口,内部采用线程池来异步处理传来的图片及结构化数据,线程池代码如下所示:
private ScheduledExecutorService threadPool ; private BasicService basicService; @PostConstruct public void vcnLogin(){ BasicService basicService = new BasicServiceImpl(); basicService.setLogPath("/opt/"); int result = basicService.initial(); int result1 = basicService.login("vcnesdk02", "Huawei12#$", "34.8.20.132", 9900); logger.info("vcn login result: "+result1); threadPool = Executors.newScheduledThreadPool(50); }
来的图ScheduledThreadPoolExecutor线程池默认采用DelayedWorkQueue,是一种延时的优先级队列,在这里需要关注的是无界队列。
项目刚开始运行没什么问题,在早高峰和晚高峰的时候,数据突然多了起来,full gc发生频繁,因为采用的并行GC算法,占用资源过多,导致线程池处理越来越慢,队列积压的任务越来越多,老年代空间越来越小,造成full gc越来越频繁,gc越频繁,任务处理越慢,最终导致上图所示的老年代都满了,但是full gc之后,空间一直不下降。数据接入曲线图如下:
图中显示早高峰7点半的时候,达到了数据洪峰,系统扛不住了,于是老年代满了,頻繁full gc,导致系统越来越慢,吞吐量下降。
解决方案
解决 无用评论 打赏 举报
悬赏问题
- ¥15 react-diff-viewer组件,如何解决数据量过大卡顿问题
- ¥20 遥感植被物候指数空间分布图制作
- ¥15 安装了xlrd库但是import不了…
- ¥20 Github上传代码没有contribution和activity记录
- ¥20 SNETCracker
- ¥15 数学建模大赛交通流量控制
- ¥15 为什么我安装了open3d但是在调用的时候没有报错但是什么都没有发生呢
- ¥50 paddleocr最下面一行似乎无法识别
- ¥15 求某类社交网络数据集
- ¥15 靶向捕获探针方法/参考文献