高性能硬件上的程序部署策略:
硬件系統為4個CPU、16GB物理內存,操作系統為64位CentOS,Resin作為web服務器。管理員選用了64位的JDK1.5,並通過-Xmx和-Xms的參數將Java堆固定在12GB。
高性能硬件上部署程序,目前主要由兩種方式:
1.通過64位JDK來使用大內存
2.使用若干個32位虛擬機建立邏輯集群來利用硬件資源
對於用戶交互性強、對停頓時間敏感的系統,可以給Java虛擬機分配超大堆的前提是有把握應用程序的Full GC頻率控制得足夠低,至少要低到不會影響用戶使用,譬如十幾個小時甚至一天才出現一次Full GC,這樣可以通過在深夜執行定時任務的方式觸發Full GC甚至自動重啟服務器來保持內存可用空間在一個穩定的水平
控制Full GC頻率的關鍵是看應用中絕大多數對象能否符合 朝生夕滅 的原則,即大多數對象的生存時間不應太長,尤其是不能有成批量的、長生存時間的大對象產生,這樣才能保障老年代空間的穩定
如果計划使用64位JDK來管理大內存,還需要考慮下面可能面臨的問題:
1.內存回收導致長時間停頓
2.現階段,64位JDK的性能測試結果普遍低於32位JDK
3.需要保證程序足夠穩定,因為這種應用要是產生堆溢出幾乎就無法產生堆轉儲快照,哪怕產生了快照也幾乎無法進行分析
4.相同程序在64位JDK消耗的內存一般比32位JDK大,這是由於指針膨脹,以及數據類型對齊補白等因素導致的
如果使用第二種方式,使用多個32位虛擬機建立邏輯集群來利用硬件資源。具體做法是在一台物理機器上啟動多個應用服務器進程,每個服務器進程分配不同端口,然后在前端搭建一個負載均衡器,以反向代理的方式來分配訪問請求。
使用第二種邏輯集群的方式部署程序,可能會遇到下面一些問題:
1.盡量避免節點競爭全局的資源,最典型的就是磁盤競爭,各個節點如果同時訪問某個磁盤文件的話,容易導致IO異常
2.很難最高效領某些資源池,比如連接池,一般都是在各個節點建立自己獨立的連接池,這樣有可能導致一些節點池滿了而另外一些節點仍有較多空余。盡管可以使用集中式的JNDI,但這個有一定復雜性並且可能帶來額外的性能開銷
3.各個節點仍然不可避免地受到32位的內存限制,在32位Windows平台中每個進程只能使用2GB內存,考慮到堆以外的內存開銷,堆一般最多只能開到1.5GB。在某些Linux或Uninx系統中,可以提升到3GB乃至接近4GB的內存,但32位中仍然受最高4G內存的限制
4.大量使用本地緩存的應用,在邏輯集群中會造成較大的內存浪費,因為每個邏輯節點上都有一份緩存,這時候可以考慮把本地緩存改為集中式緩存
回到上面的案例中,最后的部署方案調整為建立5個32位JDK的邏輯集群,每個進程按2GB內存計算(堆固定為1.5),占用了10GB內存。另外建立一個Apache服務作為前端均衡代理訪問門戶。考慮到用戶對響應速度比較關心,並且文檔服務的主要壓力集中在磁盤和內存訪問,CPU資源敏感度較低,因此改為CMS收集器進行垃圾回收。
