数据平台做一些计算需要通过hive jdbc方式连到hiveserver2执行job,但是hiveserver 正常运行一段时间后,总是会报如下OOM:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
Hive history file=/tmp/work/hive_job_log_ce580f37-05ff-4ca6-b4c8-bb4337e0ed47_1912327686.txt Total MapReduce jobs = 1 Launching Job 1 out of 1 Number of reduce tasks not specified. Estimated from input data size: 1 In order to change the average load for a reducer (in bytes): set hive.exec.reducers.bytes.per.reducer=<number> In order to limit the maximum number of reducers: set hive.exec.reducers.max=<number> In order to set a constant number of reducers: set mapred.reduce.tasks=<number> java.lang.OutOfMemoryError: Java heap space at org.apache.hadoop.hdfs.DFSOutputStream$Packet.<init>(DFSOutputStream.java:209) at org.apache.hadoop.hdfs.DFSOutputStream.writeChunk(DFSOutputStream.java:1501) at org.apache.hadoop.fs.FSOutputSummer.writeChecksumChunk(FSOutputSummer.java:173) at org.apache.hadoop.fs.FSOutputSummer.write1(FSOutputSummer.java:116) at org.apache.hadoop.fs.FSOutputSummer.write(FSOutputSummer.java:102) at org.apache.hadoop.fs.FSDataOutputStream$PositionCache.write(FSDataOutputStream.java:54) at java.io.DataOutputStream.write(DataOutputStream.java:107) |
偶尔碰到未解决问题,重启HiveServer2,印证了那句老话,重启能解决80%以上的问题,但是好景不长,经过长期的观察,发现是HiveServer进程GC状况:
到这一步可以断定有资源没有释放, 再看下Heap对象分布:
看到这里我确实找不到招了,HashMap HashTable代码在Hive源码遍地都是,压根无法定位是哪个代码片段存在内存泄漏
然后我尝试去官网查下别人是否也碰到过同样的问题,果然在jira里搜索 “HiveServer2 OutOfMemoryError” ,存在一个Case跟我的情况一模一样,但Bug是Open状态,也就是还未解决!! https://issues.apache.org/jira/browse/HIVE-9893
有问题就解决问题,考虑到HiveServer2是单点,对系统高可用、稳定性都会带来隐患;于是我想到了一个解决办法——开启多个HiveServer2,上层用Haprocxy来转发请求,再通过服务拨测实时对OOM的节点报警通知,以便研发能第一时间发现问题。但OOM依然存在,治标不治本。
这个Bug一直持续了将近半年,直到最近在调研Spark并计划将Spark取代Mapreduce来提升平台的计算效率时,发现Spark-sql能完美的兼容Hive SQL,同时还提供了ThriftServer(就是SparkHiveServer),不止于此,由于Spark更好的使用了内存,期执行效率是MR/Hive的10倍以上。
其实就是在Spark集群上执行$SPARK_HOME/sbin/start-thriftserver.sh –master=spark://MASTER:7077 就默认开启了10000端口,该服务可以取代hiveserver2,如果与HiveServer2在同一台服务器上,可以先shutdown hiveserver2,再启动spark thriftserver。运行了1个礼拜,服务非常稳定,GC也正常!