最近準備上線cassandra這個產品,同事在作一些小規格ECS(8G)的壓測。壓測時候比較容易觸發OOM Killer,把cassandra進程幹掉。問題是8G這個規格我配置的heap(Xmx)並不高(約6.5g)已經留出了足夠的空間給系統。只有多是Java堆外內存使用超出預期,致使RES增長,纔可能觸發OOM。node
0.初步懷疑是哪裏有DirectBuffer泄漏,或者JNI庫的問題。
1.按慣例經過google perftools追蹤堆外內存開銷,可是並未發現明顯的異常。
2.而後用Java NMT 看了一下,也沒有發現什麼異常。google
3.查到這裏思路彷佛斷了,由於跟DirectBuffer彷佛沒啥關係。這時候我注意到進程虛擬內存很是高,已經超過ECS內存了。懷疑這裏有些問題。spa
4.進一步經過/proc/pid/smaps 查看進程內存地址空間分佈,發現有大量mmap的文件。這些文件是cassandra的數據文件。線程
此時這些mmap file 虛擬內存是2G,可是物理內存是0(由於我以前重啓過,調低過內存防止進程掛掉影響問題排查)。code
顯然mmap的內存開銷是不受JVM heap控制的,也就是堆外內存。若是mmap的文件數據被從磁盤load進物理內存(RES增長),Java NMT和google perftool是沒法感知的,這是kernel的調度過程。blog
5.考慮到是在壓測時候出現問題的,因此我只要讀一下這些文件,觀察下RES是否會增長,增長多少,爲啥增長,就能推斷問題是否是在這裏。經過下面的命令簡單讀一下以前導入的數據。進程
cassandra-stress read duration=10m cl=ONE -rate threads=20 -mode native cql3 user=cassandra password=123 -schema keysp ace=keyspace5 -node core-3
6.能夠觀察到壓測期間(sar -B),major page fault是明顯上升的,由於數據被實際從磁盤被load進內存。內存
同時觀察到mmap file物理內存增長到20MB:get
最終進程RES漲到7.1g左右,增長了大約600M:產品
若是加大壓力(50線程),還會漲,每一個mmap file物理內存會從20MB,漲到40MB
7.Root cause是cassandra識別系統是64仍是32來肯定要不要用mmap,ECS都是64,可是實際上小規格ECS內存並很少。
1.問題誘因是mmap到內存開銷沒有考慮進去,具體調整方法有不少。能夠針對小規格ECS下降heap配置或者關閉mmap特性(disk_access_mode=standard)
2.排查Java堆外內存仍是比較麻煩的,推薦先用NMT查查,用起來比較簡單,配置JVM參數便可,能夠看到內存申請狀況。
原文連接 本文爲雲棲社區原創內容,未經容許不得轉載。