下文所说的 hbase client 版本,如无特指,则皆为 1.2.3。
之前项目中出现堆外内存溢出(排查过程),虽然已经解决了问题,但当时没有深究底层的原理,最近抽空从底层入手,深入研究了 hbase client 读写源码,配合 jmeter 压测特定接口,并使用 mat 等工具分析,最终定位到了 hbase 堆外内存溢出的根本原因,本次就梳理下完整的过程,以及涉及的一些原理,防止以后踩坑。
一.溢出现象
单台服务器刚发布时 java 进程占用3g,以一天5%左右的速度增长,一定时间过后进程占用接近90%,触发服务器报警,而此时 old 区占用在 50%,未触发 CMS GC,而导致堆外内存溢出。
异常堆栈:
-Xms8g -Xmx8g -Xmn3g -Xss512k
-XX:MetaspaceSize=256m
-XX:MaxMetaspaceSize=512m
-XX:+UseConcMarkSweepGC
-XX:+DisableExplicitGC
-XX:-UseGCOverheadLimit
-XX:+UseCMSInitiatingOccupancyOnly
-XX:CMSInitiatingOccupancyFraction=70
-XX:+CMSParallelRemarkEnabled
-XX:+UseFastAccessorMethods
二.排查过程&原理分析
1.初步分析
根据异常堆栈,可以看出是 hbase.write() 分配直接内存导致的堆外内存溢出。而直接内存分配空间不足时,会调用 System.gc(),由于 JVM 参数配置了 -XX:+DisableEx