1. 程式人生 > >記一次記憶體告警

記一次記憶體告警

個人部落格原文:
記一次記憶體告警

hbase_logo_with_orca_largepng

今天給大家分享一次生產上遇到的記憶體問題。

生產上的一個應用經常執行一段時間後就記憶體告警,在一次告警中,先 dump 了記憶體下來,然後再重啟了應用。

dump 命令:

jmap -dump:format=b,file=memory.pro {pid}

用 VisualVM 開啟檔案,看了一下,發現佔用很高的是 java.nio.ByteBuffer[],點選多層引用進去發現是 HBase 連線,看起來很明顯,大概知道是什麼問題了,有 6 萬多個連線物件,肯定是連線未釋放導致的。

記憶體

到底是什麼導致連線未釋放? 看了公司內部封裝的框架程式碼,操作 HBase 有使用 HTablePool,配置了佇列數是 10,這就奇了怪了。為啥連線數還那麼高?

只能通過 HBase 原始碼來看個究竟,直到看了 HBase 的 HTablePool#getTable(),取出為空的話還會自動建立 HTable,說明配置佇列數不是固定死的,還會自動建立的。當 HBase 操作慢的時候,存 HTable 的佇列很容易就為空了,這個時候會額外建立 HTable,這時候懷疑額外建立的 HTable 沒有釋放資源,再繼續看程式碼。

getTable

既然可以無限建立 HTable,那就得關注下存 HTable 到佇列的程式碼了。看了 HTablePool#putTable() 程式碼發現,只是簡單判斷了佇列沒滿,就把 HTable 放到佇列,多餘的 HTable 竟然啥都沒處理,就這樣堆積在記憶體中。

putTable

看了 HBase 版本,是可憐的 0.89 古老版,在新的版本這個問題都不存在了,下面是 0.98 版本,已經解決了這個問題,把多餘的 HTable 回收了。

putTable

這個坑也是公司一直沒升級 HBase 導致的。所以要跟得上開源的腳步,儘量用高的版本的開源框架。在沒升級 HBase 的時候,只能根據業務,把 HTablePool 佇列配置配高些,才會減少自動建立的 HTable。

公眾號