成為Java GC專家(4)—Apache的MaxClients引數詳解及其在Tomcat執行FullGC時的影響
MaxClients 與backlog
在這種情況下,設定哪個引數可以避免返回給使用者503錯誤呢?
首先,我們應該知道backlog的值要夠大,以至於能夠容納所有因為Full GC導致暫停期間湧入的請求。換句話說太應該不小於200。
那麼,這麼設定之後會不會產生新的問題呢?
讓我們假設將backlog設定為200後再重複一下上面的過程。得到的結果比之前更加嚴重。系統記憶體使用量一般情況下為50%,但是,在發生Full GC時快速增加到100%,同時導致交換記憶體空間快速增加,更為嚴重的是導致Full GC的暫停時間從1秒變成了4秒甚至更多,系統在此期間完全宕機,不能響應任何請求。
在第一種情況下,只有100或更多的請求返回503錯誤。但是,當我們把backlog調整到200後,超過500個請求會掛起3秒甚至更多地時間無法得到應答
上面這個例子可以很好的說明當你沒有完全理解各個設定之間的內在關係時(例如,對於系統的影響),盲目修改系統會導致什麼後果。
那麼,為什麼會產生這個現象呢?
問題的根源在於 MaxClients
引數的特性。
將MaxClients
設定為一個很大的值本身沒有問題,但最重要的是在設定MaxClients
引數時,你要確保即使等同於MaxClients
數量的httpd程序被同時建立,記憶體使用量也不會超過80%。
系統的記憶體交換引數一般被設定為60(預設)。因此,當記憶體使用量超過80%時,就會進行記憶體交換。
讓我們再來看一下為什麼這個特性會導致上面那個嚴重的問題。當請求以200 req/s的速度湧向Tomcat時,Tomcat由於full GC暫停了。此時backlog被設定為200。Apache大約建立100個httpd程序。在這種情況下,一旦記憶體使用量超過80%,作業系統會啟用交換記憶體區域,並且由於系統認為JVM的老年代中的物件在很長一段時間內未被使用,而將他們移動到交換區域。
最終的結果是,GC使用了記憶體交換空間,暫停時間劇增。因此httpd程序數進一步增加。從而導致上面描述的記憶體使用量達到100%的情況。
這兩個場合的唯一區別就是backlog的值:100 vs.200。為什麼只在200的情況下發生?
兩者不同的原因在於建立的httpd程序的數量。當backlog設定為100時並且Full GC發生時,會建立100個請求的連線並儲存在backlog佇列中。其他請求得到拒絕連線錯誤資訊併發揮503錯誤。因此,總的httpd 程序數量僅僅會略高於100。而當backlog被設定為200時,200個請求會建立連線,因此。總的httpd程序數會多於200。這樣超過閥值,從而導致記憶體交換的發生。緊接著,不考慮記憶體使用量而的設定 MaxClients
MaxClients引數的計算公式
如果系統的記憶體使2GB,MaxClients
的值在任何情況下都不應該超過記憶體的80%(1.6GB),以避免由於記憶體交換導致的效能下降。換句話說。1.6GB的記憶體應該共享和分配給Apache,Tomcat以及那些預設被安裝的代理程式。
讓我們假設代理程式被預設安裝在系統,並佔用了200m記憶體,對於Tomcat堆記憶體的-Xmx
被設定為 600m。因此根據top命令的結果,Tomcat會一直佔用725m(Perm Gen + Native Heap Area)。最終Apache可以使用700m記憶體空間。如下所示。
圖2:測試系統的top截圖