越來越多的關鍵應用運行在J2EE(Java 2, Enterprise Edition)中,這些諸如銀行系統和賬單處理系統需要高的可用性(High Availability, HA),同時像Google和Yahoo這種大系統需要大的伸縮性。高可用性和伸縮性在今天高速增長的互連接的世界的重要性已經證實了。eBay于1999年6月停機22小時的事故,中斷了約230萬的拍賣,使eBay的股票下降了9.2個百分點。
J2EE集群是用來提供高可用性和伸縮性服務,同時支持容錯處理的一種流行的技術。但是,由于J2EE規范缺乏對集群的支持,J2EE供應商實現集群的方法也各異。這給J2EE架構師和開發人員帶來了很多困難。以下是幾個常見的問題:
l 為什么帶集群功能的商業J2EE服務器產品如此昂貴?(10倍于不帶集群功能的產品)
l 為什么基于單服務器環境構建的應用不能在集群中運行?
l 為什么應用在集群環境中運行得很慢,但在非集群環境中卻快得多?
l 為什么集群的應用移植到其他服務器中失???
理解這些限制和要素的最佳方法是學習他們的實現方式。
基本術語
在我們討論不同的集群實現之前,先談談幾個概念。這有助于理解不同的J2EE集群產品不同的設計結果和概念:
伸縮性(Scalability):
在一些大的系統中,預測最終用戶的數量和行為是非常困難的,伸縮性是指系統適應不斷增長的用戶數的能力。提高這種并發會話能力的一種最直觀的方式就增加資源(CPU,內存,硬盤等),集群是解決這個問題的另一種方式,它允許一組服務器組在一起,像單個服務器一樣分擔處理一個繁重的任務。
高可用性(High availability):
單一服務器的解決方案并不是一個健壯方式,因為容易出現單點失效。像銀行、賬單處理這樣一些關鍵的應用程序是不能容忍哪怕是幾分鐘的死機。它們需要這樣一些服務在任何時間都可以訪問并在可預期的合理的時間周期內有響應。集群方案通過在集群中增加的冗余的服務器,使得在其中一臺服務器失效后仍能提供服務,從而獲得高的可用性。
負載均衡(Load balancing):
負載均衡是集群的一項關鍵技術,通過把請求分發給不同的服務器,從而獲得高可用性和較好的性能。一個負載均衡器可以是從一個簡單的Servlet或Plug-Ins(例如一個Linux box利用ipchains來實現),到昂貴的內置SSL加速器的硬件。除此之外,負載均衡器還需執行一些其他的重要任務,如“會話膠粘”讓一個用戶會話始終存在一個服務器上,“健康檢查”用于防止將請求分發到已失效的服務器上。有些負載均衡器也會參與我們下面將要談到“失效轉移”過程。
容錯(Fault tolerance):
高可用性意味著對數據正確性的要求不那么高。在J2EE集群中,當一個服務器實例失效后,服務仍然是有效的,這是因為新的請求將被冗余服務器處理。但是,當一個請求在一個正在失效的服務器中處理時,可能得到不正確的結果。不管有多少個錯誤,容錯的服務應當能確保有嚴格的正確的行為。
失效轉移(Failover):
失效轉移是集群中用來獲取容錯能力的另一項關鍵的技術。當一個結點失效后,通過選擇集群中的另一個結點,處理將會繼續而不會終止。轉移到另一個結點可以被顯式的編碼,或是通過底層平臺自動地透明地路由到另一個服務器。
等冪方法(Idempotent methods):
等冪方法是指這樣一些方法:重復用相同的參數調用都能得到相同的結果。這些方法不會影響系統狀態,可以重復調用而不用擔心改變系統。例如:getUsername()就是等冪的,而deleteFile就不是。當我們討論HTTP Session失效轉移和EJB失效轉移時,它是一個重要的概念。
什么是J2EE集群
一個天真的問題,不是嗎?但我仍要用幾句話和圖來回答它。通常,J2EE集群技術包括"負載均衡"和"失效轉移"。

圖 1 負載均衡
如圖1所示,負載均衡意味著有許多客戶端向目標對象同時發出請求。負載均衡器在調用者和被調用者之間,分發請求到與原始對象相同的冗余對象中。伸縮性和高可用性就是這樣得到的。

圖 2 失效轉移
如圖2所示,失效轉移與負載均衡不同。有時客戶端會連續發請求到目標對象,如果請求中間目標對象失效了,失效轉移系統將檢測到這次失敗,并將請求重定向到另一個可用的對象。通過這種方式可以獲得容錯能力。
如果你想知道更多的有關J2EE集群的知識,你就會問到一個基本的問題,“什么對象可以集群?”和“在我的J2EE代碼中哪里會發生負載均衡和失效轉移呢?”。這些都是用來理解J2EE集群的非常好的問題。實際上,并不是所有的對象都能被集群的,并且負載均衡和失效轉移并不是在J2EE代碼所有地方都能發生。看看下面的例子代碼:

圖 3 例子代碼
在Class A的bussiness()方法中,instance1可以負載均衡嗎?或是當其失效,可以失效轉移到其他B的實例上嗎?我想是不行的!對負載均衡和失效轉移來說,必須要有個攔截器在調用者和被調用者之間分發或重定向請求到不同的對象上。Class A和Class B的實例是運行在一個JVM中緊密耦合的,在方法調用間加入分發邏輯非常困難。
什么類型對象可以被集群?——只有那些可以被部署到分布式拓樸結構中的組件。
在我的J2EE代碼中,什么地方會有負載均衡和失效轉移?——只在你調用分布式組件的方法時。

圖 4 分布式對象
在如圖4所示的分布式環境中,調用者和被調用者被分離在有明顯邊界的不同的運行容器中,這個邊界可以是JVM,進程和機器。
當目標對象被客戶端調用時,目標對象的功能是在容器中運行的(這就是為什么我們說它是分布式的原因)??蛻舳撕湍繕藢ο笸ㄟ^標準的網絡協議通信。這些特性就為一些機制提供了機會可以介入到方法調用之間實現負載均衡和失效轉移。
如圖4,瀏覽器通過HTTP協議調用JSP對象,JSP運行在WEB服務器中,瀏覽器只需要返回結果而不關心它是怎么運行的。在上述場景中,一些東西就可以在瀏覽器與WEB服務器之間實現負載均衡和失效轉移的功能。在J2EE平臺,分布式技術包括:JSP(Servlet),JDBC,EJB,JNDI,JMS,WEB Service等。負載均衡和失效轉移就發生在這些分布式方法被調用時。在后續部分我們將詳細討論這些技術。
posted on 2007-10-16 01:53
前方的路 閱讀(396)
評論(0) 編輯 收藏 所屬分類:
軟件思想