J2EE集羣原理(一)

J2EE集羣原理
什麼是集羣呢?總的來說,集羣包括兩個概念:“負載均衡”(load balancing)和“失效備援”(failover
圖一:負載均衡
多個客戶端同時發出請求,位於前端的負載均衡器根據特定算法,將請求分擔給比較空閒的機器,從而實現較高性能和較好的擴展性
 
圖二:失效備援
當客戶端連續向某個服務器發出請求時,該服務器可能處理到一半就宕機了,失效備援系統能夠檢測出有問題的服務器,將後續的請求轉發至其他可用的機器,從而實現容錯功能
 
那麼,哪些對象可以被集羣呢,答案是:“可以被部署在分佈式拓撲的組件
因此,負載均衡和失效備援會發生在哪些J2EE代碼中呢?“僅當你調用分佈式對象的方法時

 

圖四:分佈式對象
客戶端和目標服務器不在一個JVM上,他們之間通過標準的網絡協議進行通訊,這也就給集羣提供了用武之地,實現集羣效果的設備可以放在邊界上對通訊做一些處理
J2EE的分佈式技術包括:JSP,JDBC,EJB,JNDI,WEB SERVICE等等
 
網絡層的集羣實現
這是最常見最基本的J2EE集羣功能,網絡層集羣技術包括:網絡負載均衡和HTTP SESSION的失效備援
圖五:網絡負載均衡
 
負載均衡器可以是一個硬件設備,比如F5 Load Balancer,也可以是另外一臺服務器加一個負載均衡的插件,甚至一個Linux的嵌入式設備都能勝任。通常,負載均衡包括以下幾個特點:
實現負載均衡算法
常用的算法有:Round-Robin, Random Weight Based,算法的最終目標是儘量使每臺服務器的負載達到平衡,但以上算法只是根據每臺服務器接收的請求來進行均衡,因此都不能完全達到理想化的目標。有些複雜的算法可以在分發請求之前檢測機器的性能,從而決定要由哪臺機器來處理請求。
健康監測
一旦某臺機器宕機了,負載均衡器要能夠及時發現情況,並且將請求轉交給其他可用的服務器,保證做到“failover
Session stickiness
即是讓一次session會話的請求都儘量交給一臺機器處理,這樣省去了服務器之間交換session數據的開銷
 
HTTPSession  Failover
session進行到一半時,如果服務器掛了,我們就要想辦法讓session在另外一臺機器上繼續進行,而不是讓用戶重新來過。下面圖六解釋了實現HTTPSession Failover的原理:每次的session都會分配一個唯一的id,這個idcookies的形式存放在客戶端中,負載均衡器通過id分辨請求是屬於哪個session的。在第四步中,服務器A以某種定義好的方式,定期將session數據保存起來,一旦出問題,負載均衡器會自動通知另一臺服務器B,讓它取出保存的數據,接A的班

圖六
 
要實現以上基本功能,首先要支持以下特性:
全局session id
每個jvm內部都會爲每次session維護一個唯一的id,但多個jvm之間的session id會不會重複就很難說了,所以負載均衡器要能夠協調各個jvm,使每個session id都能全局唯一。
如何備份session
這個跟具體廠商有關,後面會講到
備份的頻度和粒度
這個事關負載均衡的性能,因爲備份數據的過程直接佔用cpu、網絡和IO性能
 
 
數據庫方式備份

這是最簡單的實現方式,數據庫還能在整個系統都當掉時依舊保存好session數據,可靠性高,幾乎所有J2EE實現都提供了這種方式,當然,你的session數據必須是可序列化的。但是,這種方式一般推薦不要在session中存放過大過多的數據,因爲數據庫的事務過程相當費資源,但這樣也大大限制了它的使用範圍,畢竟我們有時必須要在session中存放一些大對象

 

內存拷貝方式

 

這種方式好處很多,首先它省去了數據庫連接和事務的開銷,其次由於備份的數據已經放在內存中了,也就省去了從數據庫恢復的過程
 
“JavaGroup”是當前tomcat和jboss集羣方案的通訊層協議,本質上是一個可靠的組間通訊和管 理的toolkit,它的核心功能在於“ Group membership protocols” 和“message multicast”,用在集羣上非常適合,關於JavaGroup的更多內容,請參考 http://www.jgroups.org/javagroupsnew/docs/index.html
 
Tomcat的實現:多服務器之間互相拷貝內存

雖然實現起來容易,但這種方法的弊端也顯而易見,當節點增加時,拷貝量就要成倍增長,性能有時還不如不集羣

 

Weblogic, Jboss WebSphere的實現:雙服務器拷貝

 

雖然這種方法的性能和擴展性都很好,但也有不少弊端

l  負載均衡器的複雜度加大,因爲要記住每個服務器的備份者是誰

l  除了處理請求外,每個服務器還得自己維護備份開銷

l  平時大量的內存都被用於備份數據,會增加jvm的垃圾收集頻率,間接影響性能

l  一旦某個服務器長時間掛掉,那麼另一臺服務器的負荷就會翻倍,可能也被一起拖垮

 

爲了克服以上缺點,各個廠商都有自己的不同解決方案

 

IBM的方案:中央服務器

很像是之前的數據庫方式吧,只是把數據庫換成了一臺專門備份的服務器,綜合了數據庫和內存方式的優點。

l  將備份和請求處理分開,增強了系統的魯棒性

l  所有的備份數據都在專門的服務器上,節省了其他服務器的內存

l  所有服務器都能存取備份機器上的數據,任何服務器宕機了,負載都能平滑的分配到剩餘所有服務器上,而不至於加重某臺機器的負擔

l  比起數據庫連接,備份服務器使用的socket連接更加輕量級

 

比起直接的雙服務器互拷內存,這種方式效率還是比較低的,因爲還要有個恢復的過程,而且在管理上也增加了系統的複雜度。此外,備份服務器本身也很有可能成爲瓶頸。

 

Sun的實現:專用數據庫

表面上就是數據庫的方式,但實際上,Sun JES應用服務器使用的稱爲“HADB”的數據庫是專門爲session的備份做了優化的,其大部分數據都是直接存放在內存中


Session備份的性能考慮

集羣中每臺服務器都有多個web應用,每個應用又同時有數以千記的用戶session,這些session的備份和恢復都會耗費大量資源。更恐怖的是,session一直在變,比如失效了,比如增加或修改某個屬性了,等等。所以如何備份session是考驗系統架構水平的

 

何時備份?

不管是用數據庫還是內存方式,下面兩點都是比較常見的考慮

l  web 請求,即每次請求都進行備份更新,這樣可以保證備份的數據是最新的

l  固定時間備份,雖然不能保證備份的session是最新的,但卻可以提高性能

 

備份粒度

l  全部備份,最保險也是最慢的方法

l  備份修改過的session。通常的做法是檢測”HTTPSession.setAttribute()” “HTTPSession.removeAttribute()” 的調用,當然你要保證session的狀態只能由這兩個方法更改,儘管這不是J2EE規範的要求。

l  備份修改過的session的屬性,最節省性能的做法。但是有一點很重要:防止交叉引用。如下圖,session中包含school對象,指向一個student對象。當school對象某個屬性改變後,被備份到AS2中,它此時引用的是舊的student對象。接着student對象被單獨改變了,也進行了備份,但是school中仍然引用舊的student。因此這種方法對web容器的設計要求很高,儘管它的性能是最好的。

圖十三:session複製中的交叉引用

 

其他失效備援的實現

以上不論是數據庫還是內存複製,歸根結底都要使用Java的序列化機制,這給web容器的性能造成了不小的影響,因此有些應用服務器使用別的方式進行session備份

 

JRun with Jini

JRun 4使用jini實現集羣,jini的詳細介紹請參考 http://java.sun.com/products/jini/2_0index.html

 

Tangosol with Distributed Cache

Tangosol Coherence™提供了一個分佈式數據管理平臺,可以嵌入到大部分J2EE系統中,此外還提供一個分佈式緩存系統,能夠在多臺jvm上有效的共享緩存,詳情請參考 http://www.tangosol.com/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章