LZ開發的一個公司內部應用供查詢HIVE數據使用。部署上線后總是會出現CPU偏高的情況,而且本地測試很難重現。之前出現幾次都是通過直接重啟后繼續使用,因為是內部使用,重啟一下也沒有很大影響(當然,每次重啟都是順帶改改BUG,添加一些監控,或者修改了一些參數)。
今天再次發生占用CPU偏高的情況(機器是16核的),跑了幾天后出現占用到200-300CPU的情況,之后快速升高,占用到700-1000。隨機對應用狀態狀態盡興了檢查。
首先看了GC情況,看是否在進行FGC。
(在CPU剛開始飆高的時候FGC的次數是0,上圖9次定位完問題才截的圖,之前的沒有保留)
發現應用並沒有在進行FGC,而是進行頻繁的YGC。
YGC也存在異常,S1和S0區域都是從0直接跳到99%
觀察堆大小裝太發現Young區內存都是不斷的從0到99,而Old區在慢慢遞增,還未達到FGC的狀態。但預計后續會不停的上漲,導致FGC頻道,應用無法提供服務。
在發現YGC頻繁之后大約3個小時,終於開始了頻繁的FGC,Old區滿。
以下是堆大小和FGC的情況:
可以看到差不多10秒鍾Old區就用滿了導致一次FGC,而且Old區大小是10G(多么恐怖,10個G十來秒就用完了)
從內存和GC的角度只能看到YGC頻繁導致了FGC頻道(10秒一次)。但這樣的情況應用還是能提供服務,只是占了較高的CPU(如果FGC在頻繁一些應用應該是不能訪問的)。
查完內存的狀態確認並不是old區太小,被用滿了導致了不停的FGC,因為old明顯是夠大的,如果10G不夠,那應用肯定是有問題的。
之后去查了哪些線程占用了很高CPU(本應當在發現沒有頻繁FGC之后就入手查線程狀態,經驗不夠)
查看進程的線程CPU使用情況:
拿到CPU占用較高的幾個線程,轉成16進制
使用jstack看進程內的線程堆棧信息(jstack 24820 > abc.log)
vim編輯abc.log,查找上面獲取到的線程的16進制數
發現是使用了com.trilead.ssh2.StreamGobbler類的線程。這是一個ssh的第三方包。
后續查了其他CPU占用高的線程,除了GC占用,大部分都是SSH占用。
應用場景是每次使用HIVEQL進行查詢的時候都會起一個線程,SSH到遠程服務器,執行查詢內容,返回結果。
如果有多個用戶同時進行多個查詢(一個用戶也可以進行多次查詢),就會出現多個線程多次SSH的情況。
后續處理的兩個方案:
方案一,替換現有的第三方SSH工具,看有沒有更好的
方案二,修改代碼。考慮SSH后保持SESSION(查SSH SESSION的時效時間),統一賬號,所有用戶后台使用統一賬號登錄遠程服務器執行查詢。只使用一個SESSION,發現SESSION失效后進行一次重連。而不是每次查詢都建一個登錄一次獲取session,用完后關閉,相信能減少SSH的引起的問題。
(PS:因為手頭上還在進行其他項目,所以還是重啟了應用先頂一陣,后面做完hive的權限控制,后台統一用戶執行后優化SSH的處理)
OOM、CPU占用問題,JVM工具使用這些都是從菜鳥程序員不斷提高要經歷的,希望自己變的更好。
附JVM常用工具說明:http://my.oschina.net/feichexia/blog/196575