JIRA應用的內存參數設置不當+容器沒有對資源進行限制導致服務掛掉的例子

背景:
應用的部署結構是這樣的:使用rancher管理的Docker集羣,有三臺物理主機,二十多個Docker容器,
提供的功能是問題跟蹤(JIRA),文檔管理(Confluence),代碼託管(svn,gitlab),持續集成(jenkins,gitlab-ci + Docker),代碼質量管理(Sonar),構件管理(nexus3)和測試管理(TestLink)的功能.服務於1400多個研發人員

前端使用Apache來對後端的服務進行反向代理,同時Apache集成了CAS和LDAP 提供了單點登錄的功能

某天下午,用戶反饋,應用訪問的速度非常的慢,登錄的請求也無法響應了.

到Apache所在的主機上看資源的佔用,,發現CPU佔用率超過500%,apache沒有足夠的CPU資源來處理請求

通過在主機上ps這個CPU超過500%的進程,發現是一個java的進程,對應的是JIRA的容器

主機上顯示的進程號,和容器裏邊的進程號是不一樣的

在容器裏,JIRA對應的java進程是進程號爲1的進程

進入JIRA容器

dump出來這個進程的所有的線程棧

jstack 1 > jirastack.log

查看這個進程中的佔cpu最高的線程

top -Hp 1

得到的結果如下:

可以看到,有8個線程的CPU佔用都超過了70左右,合計起來是 500%多

前邊的 49,53之類的是和線程棧裏邊的線程的nxID對應的,只不過,nxID是用十六進制來表示的

我們把這些十進制的數字也變成十六進制

從dump出來的線程棧裏邊找到了對應的線程:

從線程棧裏邊搜索 nid=0x31,搜到了以下的線程

我們可以看到,這些都是垃圾回收的線程,垃圾回收的線程佔據了所有的CPU的時間

查看JIRA的參數設置,發現了內存的設置較小 -Xms1024m -XmX2048m,使用的垃圾收集器是ParallelGC,因爲主機的CPU有8個內核,所以就默認啓動了8個垃圾收集器的線程

系統的用戶大概有1.4K人,都是開發和測試人員來使用,對比另一個應用 confluence的內存配置(6G的堆大小,G1垃圾收集器),JIRA的堆的配置是有點小了,所以把JIRA的堆內存設置爲4G(主機所在的內存還有很多沒有使用)然後針對增大的這個堆,啓用G1垃圾收集器,然後打印了垃圾收集的日誌信息到一個日誌文件裏邊

配置如下:

JVM_MINIMUM_MEMORY 和 JVM_MAXIMUM_MEMORY的值都是4096m

然後,爲了防止某個容器佔用的資源過多,影響其他的容器(就是開頭的時候我們遇到的問題,JIRA佔用的CPU過多,導致了apache無法響應請求,其他的應用都無法訪問了),所以,我們在rancher上對容器的資源做了一些限制

事後的反思

JIR的jvm參數設置不當和沒有對容器佔用的主機的資源進行隔離這兩個原因共同導致了這個問題的發生

在使用容器作爲生產環境的時候,要對自己在容器內所部署的應用的性能和配置參數等有足夠的瞭解,

對Docker容器所在的物理機的CPU和內存等資源所能支撐的容器的數量進行合理的預估,對容器所佔用的物理機的資源進行限制,防止容器因配置不當佔滿物理機的資源,影響其他容器

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章