转载请注明出处:http://blog.csdn.net/gklifg/article/details/50418109
刚刚从java组转岗找数据组,学习大数据的知识,开发语言也从java转到python新奇之外也遇到了诸多问题,其中最令我头疼的就是在hive上的统计任务总是三天两头地报告OutOfMemory一开始因为有别的同事的任务干扰,我以为是计算资源不够导致的,但后来把任务转移到了另一个集群后,问题仍然存在,让我百思不得其解。
问题的具体描述如下:
统计逻辑使用python pyhs2连接hive,执行HQL查询。单独执行时都很顺利,定时执行时,基本上4天中必有一天会挂掉,报OutOfMemory: Java heap space,这时候一般会重启hiveServer2,于是各个问题就又不见了,直到下一个4天。
现在看起来一切都很清晰,但是当身处问题之中的时候,很多噪音是会扰乱视线,比如说不定期的其他任务(spark、mapreduce)插入,因为其他问题引起的其他同事手动重启hiveServer2,这些都会扰乱整个问题的外在表现形式。以至于很难看出内存溢出是有一个明显的周期的。
由于是OutOfMemory,想来想去也没什么好的办法,只能监控一下jvm,看看那时候到底发生了什么。不知什么问题在AWS上没法使用jmap -heap,无奈就先使用jstat
监控语句如下:
jstat -gcutil [进程号] 5000 --每5秒打印一次jvm各个内存区的状态
另外找了一个监控系统内存的语句:
vmstat | sed -n '/[0-9]/p'
设定两个语句将结果输出到文件里后就开始等待问题出现,因为本人也是现学现卖,对于jvm的了解非常浅,当时发现jvm的永久代空间很开变成近100%,但不知道是不是有问题。
过了一个周末,HIVE果然还是挂了,查日志的时候发现当时的jvm内存是这样的:
S0 S1 E O P YGC YGCT FGC FGCT GCT
0.00 0.00 100.00 100.00 99.37 14086 39.094 13348 5176.146 5215.240
0.00 0.00 100.00 100.00 99.37 14086 39.094 13348 5176.146 5215.240
0.00 0.00 100.00 100.00 99.37 14086 39.094 13348 5176.146 5215.240
0.00 0.00 100.00 100.00 99.37 14086 39.094 13348 5176.146 5215.240
0.00 0.00 100.00 100.00 99.37 14086 39.094 13348 5176.146 5215.240
0.00 0.00 100.00 100.00 99.37 14086 39.094 13348 5176.146 5215.240
0.00 0.00 100.00 100.00 99.37 14086 39.094 13349 5176.532 5215.626
0.00 0.00 100.00 100.00 99.37 14086 39.094 13349 5176.532 5215.626
0.00 0.00 100.00 100.00 99.37 14086 39.094 13349 5176.532 5215.626
0.00 0.00 100.00 100.00 99.37 14086 39.094 13349 5176.532 5215.626
可以看到新生代和老年代都已经爆满,永久代几乎爆满,jvm一直在做full GC,但是没有效果,各个内存区都被占用了。这种情况发生后同事直接重启了hiveServer2,我没有来的及查看一下当时堆中的对象信息,不知道有没有什么有价值的信息在里面。就现在的日志来看,我发现老年代和持久代的内存只要上去了,就再没有下降过,而当这两块区域饱和后,新生代也出现了这种现象。这时候忽然意识到,是有什么资源没释放吧!?
一看代码,果然,有两个脚本pyhs2的连接没有关闭!
java里面连接都是框架管理的,平时没管过,换到python来,忽视了这个重要的步骤,血的教训啊,连接一定要关闭!另外总的来说这次问题的原因虽然相当低级,但是排查用到的手段和思维方式给了我很多收获,自责的同时也有战胜困难的喜悦,记录下来,自勉。