(小记,排查cpu100%,top 看进程cpu, top -Hp PID 看进程内线程cpu占用, 转成16进制,用jstack查看)
现象描述:
Node模块启动后收到请求却未能响应。 一直在频繁的FGC。新生代内存爆满。老年代内存爆满!
开始分析:
启动Xmx参数为 -Xmx 128M -Xms 128M
初步判断内存不足,第一次修改: -Xmx 256M -Xms 256M
-
num
#instances #bytes class name
-
----------------------------------------------
-
1
:
1001750
155802576
[
B
-
2
:
137954
32307952
[
C
-
3
:
983424
23602176
java
.
util
.
LinkedList$Node
-
4
:
134617
3230808
java
.
lang
.
String
-
5
:
34867
3091056
[
Ljava
.
util
.
HashMap$Node
;
-
6
:
74748
2391936
java
.
util
.
HashMap$Node
-
7
:
34156
1639488
java
.
util
.
HashMap
-
8
:
8932
1523896
[
Ljava
.
lang
.
Object
;
-
9
:
8216
1508664
[
Ljava
.
util
.
concurrent
.
ConcurrentHashMap$Node
;
-
10
:
16393
1311440
org
.
apache
.
zookeeper
.
data
.
Stat
-
11
:
35150
1124800
java
.
util
.
concurrent
.
ConcurrentHashMap$Node
-
12
:
7604
847288
java
.
lang
.
Class
-
13
:
49187
786992
java
.
util
.
concurrent
.
atomic
.
AtomicReference
-
14
:
16393
655720
org
.
apache
.
curator
.
framework
.
recipes
.
cache
.
TreeCache$TreeNode
-
15
:
1704
640704
java
.
lang
.
Thread
-
16
:
8373
535872
java
.
util
.
concurrent
.
ConcurrentHashMap
-
17
:
33135
530160
java
.
util
.
HashSet
这是什么???
1
:
1001750
155802576
[
B
果断看不出这是什么?
回忆一下:
比较明显的现象:
1. O区满的。
2. E区却没有满。
[deploy@dipper_prd_2 ~]$ jstat -gccause 26003 1000
S0 S1 E
O
M CCS YGC YGCT FGC FGCT GCT LGCC GCC
0.00 0.00 58.63
99.93
97.37 96.66 280 6.302 111 37.851 44.153 Allocation Failure No GC
3.FGC 次数增了,YGC倒是没有增长。
E区没满,O却满了。!!有什么奇怪的东西跑进了O区吗???????看了一下代码。最近Node修改的只有日志。读日志!!读日志 生成的对象 E没满 并不会进O区! 排除读日志的影响!
那 到底是什么奇怪的东西进入了O区??
看了一圈代码。发现不了问题。。
只能用终极大法了。dump堆内存分析。
dump堆内存到文件中 通过MAT软件分析。
命令: jmap -
dump:format=b,file=jconsole.dump
26003
安装好eclipse的memory analysis tool (MAT),切换成mat视图。将文件导入到eclipse中。
不分析不知道。 一分析吓一跳!! 看到没有,内存中最大的那块区域!!是一个
concurrentHashMap!!!!!!!!!
原来是有个concurrentHashMap在作怪!!
为什么这个对象会占据如此多的内存!查看代码后发现。这个concurrentHashMap 在NodeContext中。
这个数据结构存储了所有运行的作业的信息。 每新进一个 作业,会在此结构添加一个Code对象。
然而。 从未调用过remove方法!!!!!! 这块又是个单例对象的static对象,从来不会被回收。只进不出,内存溢出!Node跑一两天就完蛋!!
public class NodeContext{
private static NodeContext ourInstance = new NodeContext();
//存储用户的代码
private static Map<String, Code> codesMap;
public static NodeContext singleton() {
return ourInstance;
private NodeContext() {
codesMap = new ConcurrentHashMap<>();
scheduler = SchedulerFactory.singleton().createOrGetParallelScheduler(NodeConfig.PARALLELISM_MAX_NUM);
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT LGCC GCC 0.00 18.29 97.31 50.26 97.42 95.25 41 0.855 2 0.393 1.247 Allocation Failure No GC 0.00 18.29 97.80 50.26 97.42 95.25 41 0.855 2 0.393 1.247 Allocation Failure No GC 0.00 18.29 99.27 50.26 97.42 95.25 41 0.855 2 0.393 1.247 Allocation Failure No GC 21.00 0.00 0.07 50.27 96.99 95.31 42 0.879 2 0.393 1.272 Allocation Failure No GC 21.00 0.00 0.89 50.27 96.99 95.31 42 0.879 2 0.393 1.272 Allocation Failure No GC 21.00 0.00 2.12 50.27 96.99 95.31 42 0.879 2 0.393 1.272 Allocation Failure No GC 21.00 0.00 2.95 50.27 96.99 95.31 42 0.879 2 0.393 1.272 Allocation Failure No GC 21.00 0.00 3.91 50.27 96.99 95.31 42 0.879 2 0.393 1.272 Allocation Failure No GC 21.00 0.00 4.49 50.27 96.99 95.31 42 0.879 2 0.393 1.272 Allocation Failure No GC 21.00 0.00 5.10 50.27 96.99 95.31 42 0.879 2 0.393 1.272 Allocation Failure No GC |
---|
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT LGCC GCC 0.00 97.82 50.26 52.21 97.59 95.44 53 1.012 2 0.393 1.405 Allocation Failure No GC 0.00 97.82 50.26 52.21 97.59 95.44 53 1.012 2 0.393 1.405 Allocation Failure No GC 0.00 97.82 50.26 52.21 97.59 95.44 53 1.012 2 0.393 1.405 Allocation Failure No GC 0.00 97.82 50.26 52.21 97.59 95.44 53 1.012 2 0.393 1.405 Allocation Failure No GC 0.00 97.82 50.26 52.21 97.59 95.44 53 1.012 2 0.393 1.405 Allocation Failure No GC 0.00 97.82 50.26 52.21 97.59 95.44 53 1.012 2 0.393 1.405 Allocation Failure No GC 0.00 97.82 50.27 52.21 97.59 95.44 53 1.012 2 0.393 1.405 Allocation Failure No GC 0.00 97.82 50.27 52.21 97.59 95.44 53 1.012 2 0.393 1.405 Allocation Failure No GC 0.00 97.82 50.27 52.21 97.59 95.44 53 1.012 2 0.393 1.405 Allocation Failure No GC |
---|
若干天后:发生了一次FGC 但是 O区已经降低至 30.18% 到此,成功解决此内存溢出的问题!!!
[deploy@dipper_prd_2 ~]$ jstat -gcutil 3519 1000 S0 S1 E O M CCS YGC YGCT FGC FGCT GCT 0.00 4.45 65.14 30.18 96.89 93.87 671 5.568 3 0.742 6.310 0.00 4.45 65.14 30.18 96.89 93.87 671 5.568 3 0.742 6.310 0.00 4.45 65.14 30.18 96.89 93.87 671 5.568 3 0.742 6.310 0.00 4.45 65.15 30.18 96.89 93.87 671 5.568 3 0.742 6.310 0.00 4.45 65.15 30.18 96.89 93.87 671 5.568 3 0.742 6.310 0.00 4.45 65.15 30.18 96.89 93.87 671 5.568 3 0.742 6.310 0.00 4.45 65.15 30.18 96.89 93.87 671 5.568 3 0.742 6.310 0.00 4.45 65.15 30.18 96.89 93.87 671 5.568 3 0.742 6.310 0.00 4.45 65.18 30.18 96.89 93.87 671 5.568 3 0.742 6.310 0.00 4.45 65.18 30.18 96.89 93.87 671 5.568 3 0.742 6.310 |
---|
问题背景
上周,同事写了一段ConcurrentHashMap的测试代码,说往map里放了32个元素就内存溢出了,我大致看了一下他的代码及运行的jvm参数,觉得很奇怪,于是就自己捣鼓了一下。首先上一段代码:
1 public class MapTest {
3 public static void main(String[] args) {
4 ...
在我们的示例中,解决这个问题的方法是及时释放不再使用的对象。:如果内存溢出是由于过多的并发导致的,那么我们可能需要优化线程池配置,或者限制线程的数量。总的来说,解决内存溢出问题需要我们从多个维度出发,包括优化代码,合理配置JVM参数,使用适当的工具进行诊断和调试,以及理解并发对内存的影响。这时,我们可以使用内存分析工具,如MAT,VisualVM等,这些工具可以帮助我们找到内存使用的热点,从而定位到可能的内存泄漏源头。如果内存溢出是由于大量的线程并发导致的,可能需要优化线程池的配置,或者限制线程的数量。
上周,同事写了一段ConcurrentHashMap的测试代码,说往map里放了32个元素就内存溢出了,我大致看了一下他的代码及运行的jvm参数,觉得很奇怪,于是就自己捣鼓了一下。首先上一段代码:
public class MapTest {
public static void main(String[] args) {
System.out...
另外提一个参数也很有用,正常来说如果程序出现 OOM 之后,就是有代码存在内存泄漏的风险,这个时候即使能对外提供服务,其实也是有风险的,可能造成更多的请求有问题,所以该参数非常有必要,可以让 K8S 快速的再拉起来一个实例。因为 “AaAa” 和 “BBBB” 的 hash 值相同,会定位到用一个 bucket 中,这样就形成了 CAS 嵌套,产生死循环问题。通过 print 命令将线程 PID 转为 16 进制,根据该 16 进制值去打印的堆栈日志内查询,查看该线程所驻留的方法位置。
原因是hibernate会缓存sql语句以减少重复编译,便于直接命中提高效率。这个缓存默认最大值为2G,且在使用in时,只要in后面的参数有任何一个不一样的,就会视为不同的语句而保存下来。
解决这个问题可以将缓存最大值改小。
我看大家都是这样写的:
spring:
properties:
hibernate:
query:
plan_cache_max_size: 64
plan_parameter_metadata_
一、测试背景
项目中需要提供一个单机计算视频相似度的服务,计算的方式是对视频标题进行分词,提取关键词,然后通过word2vec的方式对关键词进行embedding,最后通过向量累加得到视频的词向量,然后通过某种相似度算法(比如欧式距离)得到视频相似度。这个服务要求5ms返回,可行性预研阶段需要估算响应时间能否达到要求,需要多少台机器支撑每天50亿的请求量。这里面有两个关键内容需要
常见原因内存分配过小,与实际业务需要空间不符。对象频繁被创建,却没有被释放,导致内存泄漏。有限系统资源(线程、网络连接)被不断的申请,导致系统资源被耗尽。问题排查查看内存分配空间获取java进程:[root@hostname ~]# ps x | grep java | grep -v grep2248 ? Sl 0:37 /usr/local/java/jdk1.7.0_5...
内存溢出问题排查
1、内存溢出介绍
内存溢出(OOM)指的就是在应用系统中存在无法回收的内存或者使用的内存过多,最后是的程序运行要用到的内存大于能提供的最大内存,有时候需要重启软件甚至重启电脑才可以释放一部分的内存让程序能够正常运行
通常情况下是程序的代码陷入了死循环或者是程序中产生了大量的大对象没有进行及时的回收导致在多次GC后内存资源依然紧张,一般情况下集中在char[],String,HashMap,ConcurrentHashMap这些之中,可能是频繁的使用static表示的字段,或者对String
|