Java EE集羣技術初探——第八部分(關於Java EE集羣的誤區)

 
關於Java EE集羣的誤區
 
失敗轉移能完全避免錯誤。——
JBoss的文檔中,我看見一段警告:真的需要HTTPSession複製麼?當然,有的時候不帶失敗轉移的高可用解決方案是可接受,而且也很划算。而且,失敗轉移的功能並不像想象中的那樣強大。
 
那到底失敗轉移能帶來些什麼呢?有的人認爲失敗轉移能避免錯誤。事實上,如果沒有失敗轉移,當服務器失敗時會因會話數據的丟失產生錯誤;如果有會話失敗轉移的話,會話數據能被恢復到另外一臺服務器實例中,客戶端可能都沒有察覺失敗。這是真的,但絕對是有條件的!
 
回憶一下對失敗轉移的定義。失敗轉移的時機是介於方法調用之間的。這就意味着連續兩次調用遠程對象的方法,只有當第一個方法調用完畢且第二個調用請求還未送出時纔可能發生失敗轉移。
 
所以,當正在進行方法調用的時候失敗了怎麼辦呢?答案是:處理過程中止,客戶端看見錯誤消息提示(除非方法是冪等方法)。只有方法是冪等方法的情況,一些負載均衡器才能試圖失敗轉移這些方法到別的實例。
 
冪等爲何如此重要?因爲客戶端並不知道服務器何時失敗的(在方法剛開始調用或者快要調用完成的時候)。如果是非冪等方法,則兩次調用就會兩次改變系統狀態,系統就會處於不一致的狀態。
 
在複雜應用中,不太可能把所有的方法都變成冪等方法。所以,只能通過失敗轉移減少錯誤,而不可能從根本上避免錯誤。
 
 
未採用集羣技術的應用能順利地透明遷移至集羣環境中。——
雖然一些廠商宣稱其Java EE產品的靈活性,但是我奉勸大家不要相信他們。實際上,需要從一開始的設計階段就考慮到集羣的因素,並在開發和測試階段去進行驗證。
 
HTTPSession
在集羣環境下,根據會話失敗轉移使用的機制,對HTTPSession有很多限制。首先就是限制在HTTPSession中存儲的對象必須是可序列化的。有些MVC的框架使用HTTPSession存儲一些非序列化對象(Servlet上下文、Local EJB接口和web服務的引用等等),那麼這些框架就不能在集羣環境下使用。其次,對象序列化和反序列化的過程對性能的開銷很大,尤其是採用數據庫持久化方法的時候。在這種情況下,應該避免存儲大對象和存儲的對象個數較多。如果使用的是內存複製的辦法,那麼必須注意HTTPSession中不能存在交叉引用的屬性。還有就是必須使用setAttribute()方法對HTTPSession中的屬性進行修改。
 
緩存(Cache)
幾乎所有的Java EE項目都使用緩存來改善性能,但這些緩存都是針對非集羣環境設計的,只能在一個JVM實例上工作。需要緩存的原因是有的對象頻繁創建,有的對象在創建時需要消耗大量資源,所以我們需要在緩存池中保存這些對象避免後續創建。使用緩存的根本原因是維護管理緩存的開銷比創建新的對象划算。在集羣環境下,每個JVM實例需要維護自己的緩存,還需要維護從別的服務器上同步過來的緩存,以便保證所有服務器實例的狀態一致。有時,這種同步機制會帶來更低的性能。
 
靜態變量
一些設計模式,比如單實例模式將使用靜態變量來共享多個對象的狀態。在集羣環境下,每個服務器實例需要保存自己的靜態變量,這就打破了該模式的機制。比如用靜態變量對在線用戶數進行統計的情況。在集羣環境下,這種用法將失敗,在集羣環境下,最好的辦法是將數據存入數據庫。
 
外部資源
很多系統都使用了外部I/O操作,比如上傳或動態創建XML配置文件。在集羣應用服務器中,沒有辦法跨服務器進行文件複製,所以只能通過數據庫或外部文件的方法來解決。
 
特殊服務
比如計時器(固定時間間隔觸發任務)之類的特殊服務很難在集羣環境下運行。之類的例子還有郵件通知服務、在整個系統啓動時的初始化服務等。
 
這些服務都是由時間觸發的,而不是由請求觸發的,而且只能執行一次。對他們進行負載均衡和失敗轉移意義不大。
 
有一些產品在這方面也做了一些工作,例如JBoss集羣下單模式工具(clustered singleton facility)”
 
總結
集羣與普通的環境不同,Java EE的廠商實施集羣的方法也不同。必須要認真考慮是否需要採用集羣環境,並且認真選擇相應的產品來支持集羣環境的正常工作。
發佈了13 篇原創文章 · 獲贊 0 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章