現象1:通路頁面出現500錯誤,錯誤描述為:java.lang.noclassdeffounderror,後面跟的類名各式各樣不一一列舉了。
現象2:resin被wathcdog自動重新開機,日志中表明這是因為:resin shutdown from out of file descriptors。
分析:由于linux預設檔案句柄限制為1024(通過指令ulimit –n來檢視),是以當web server應對高負載起了大量線程,incoming socket connections和outgoing socket connections都很多,而且背景代碼也可能涉及大量句柄打開,尤其是struts+spring組合。
是以當句柄數迅速到達1024的限制後,無法打開新句柄,于是乎檔案打不開、類定義找不到,諸如此類的錯誤就出現了。
解決:
短期政策是調大linux下對檔案句柄數限制。操作如附錄1所示。對于這個數字,一般建議是32667,也可以設定的更大,我們直接調為51200。
現象:resin被持續通路一段時間後,比如一天,就會報告如下500錯誤,導緻所有頁面不能通路:
outofmemoryerror:permgen space
此時,就隻能重新開機機器了,重新開機resin都沒用。
分析:因為線上用了spring+struts,這些架構用到大量動态class,classloader是把這部分記憶體放在permgen space裡的。而jvm的gc是不會清理permgen space的。這樣很容易導緻線上應用報告permgen space記憶體溢出。
解決:通過在resin.xml中增加jvm-arg一系列參數,調大“permsize”和“maxpermsize”這兩個參數來盡量避免出現jvm記憶體永久儲存區域溢出錯誤。permsize預設值參考附錄2。修改情況參見附錄3。
現象:resin報告如下500錯誤,導緻所有頁面不能通路:
outofmemoryerror:java heap space
此時重新開機resin還可以恢複。
分析:jvm預設的最大可用記憶體(-xmx參數)和初始堆大小(-xms參數)都偏小,很容易限制住伺服器的能力。當java架構的能力還沒有發揮出來時,就已經被系統預設的各種參數限制住了,導緻各種各樣的異常。
解決:通過在resin.xml中增加jvm-arg一系列參數,調大“xms”和“xmx”以及“xmn”這三個參數。修改情況參見附錄3。xmn附錄4。
其中xmx的值可以設定得很大,比如4096mb,跟你的實體記憶體大小差不太多都行,64位linux支援得住。xmn的值是xmx數值的1/4。
編輯/etc/profile,加入
ulimit -n 51200
有人認為設定為4096就可以,但在網絡伺服器上此數字最好調成幾萬,不然流量沖上來太容易沖破。
還有設定指令是:ulimit –shn 51200,-s、-h這兩個參數的說明如下:
-h 設定硬體資源限制。
-s 設定軟體資源限制。
-n size:設定核心可以同時打開的檔案描述符的最大值。
沒有給resin.xml加permsize的情況下,預設計算規則是:
“jvm使用-xx:permsize設定非堆記憶體初始值,預設是實體記憶體的1/64;由xx:maxpermsize設定最大非堆記憶體的大小,預設是實體記憶體的1/4。”
那麼,如果是實體記憶體4gb,那麼64分之一就是64mb,這就是permsize預設值,也就是永生代記憶體初始大小;
四分之一是1024mb,這就是maxpermsize預設大小。
優化規則:server端的jvm最好将-xms和-xmx設為相同值。為了優化gc,最好讓-xmn值約等于-xmx的1/4。
線上resin 4.0.15的resin.xml中增加如下配置節點:
<server-default>
<jvm-arg>-xms4096m</jvm-arg>
<jvm-arg>-xmx4096m</jvm-arg>
<jvm-arg>-xmn1024m</jvm-arg>
<jvm-arg>-xx:permsize=128m</jvm-arg>
<jvm-arg>-xx:maxpermsize=256m</jvm-arg>
<thread-max>1024</thread-max>
<socket-timeout>30s</socket-timeout>
<keepalive-max>512</keepalive-max>
<keepalive-timeout>60s</keepalive-timeout>
</server-default>
jvm的-xmn參數含義是young generation的heap size。
jvm有2個gc線程。第一個線程負責回收heap的young區。第二個線程在heap不足時,周遊heap,将young 區更新為older區。older區的大小等于-xmx減去-xmn,不能将-xms的值設的過大,因為第二個線程被迫運作會降低jvm的性能。