Tomcat
服務器為集群和SESSION復制提供了集成的支持
本系列的第一篇文章將為大家提供SESSION持久性以及TOMCAT集群中SESSION復制的內在工作機制一個概要認識
我將會討論SESSION復制在TOMCAT
中是怎樣進行的以及跨越多集群節點的SESSION持久性的復制機制
在第
部分
我會詳細討論一個帶有SESSION復制功能的TOMCAT集群的安裝例子
並且比較不同的復制情形
集群 傳統獨立服務器(非集群的)不提供任何失效無縫轉移以及負載平衡能力
當服務器失敗的時候
就無法獲取整個網站的內容
除非服務器被重新喚起
由於服務器失效
任何存儲在服務器內存中的SESSION都會丟失
用戶必須重新登陸並且輸入所有由於服務器失效丟失的數據
不同的是
作為集群一部分的服務器則提供了可測性以及失效無縫轉移能力
一個集群就是一組同步運行並且協同工作
能提供高可靠性
高穩定性以及高可測性的多服務器例程
服務端集群對客戶端表現出來似乎就是一個單獨的服務器例程
從客戶端的視角來看
集群的客戶端和單獨的服務器沒多大不同
但是他們通過提供實效無縫轉移和SESSION復制做到了不間斷服務以及SESSION數據持久性
集群中的服務器通訊 集群中的應用程序服務器通過諸如IP多點傳送(IP multicast)和IP sockets這樣的技術和其他服務器共享信息
●IP多點傳送
主要用於
對多的服務器通訊
通過廣播服務和 heartbeats消息的可用來顯示服務器的有效
●IP sockets
主要用於在集群的服務器例程中進行P
P服務器通訊
使用IP多點傳送進行一對多通訊 TOMCAT服務器使用IP多點傳送在集群中的服務器例程間進行一對多的通訊
IP多點傳送是一種能夠讓多服務器向指定IP地址和端口號進行訂閱並且監聽消息的廣播技術(多點傳送IP地址范圍從
到
)
在集群中的每個服務器都使用多點傳送廣播特定的 heartbeat消息
通過監視這些 heartbeat消息
在集群中的服務器例程判斷什麼時候服務器例程失效
在服務器通訊中使用IP多點傳送的一個缺點是他不能保證這些消息被確實接收到了
例如
一個應用持續的本地多點傳送緩存滿了
就不能寫入新的多點傳送消息
等消息過了之後該應用程序就沒有被通知到
使用IP Sockets進行服務器通訊 IP sockets 同樣也通過了一套在集群中的服務器間進行發送消息和數據的機制
服務器例程使用IP sockets 在集群節點間進行HTTP SESSION狀態的復制
正確的SOKET配制對於集群的性能是至關重要的
基於SOCKET的通訊的效率取決於SOCKET的實現類別(例如
系統使用本地的或者純JAVA SOCKET讀取器實現)
如果服務器使用純JAVA SOCKET讀取器則要看服務器例程是否注冊使用了足夠的SOCKET讀取器線程
如果想要有最佳的SOCKET性能
系統應該注冊使用本地的SOCEKT而不是純JAVA實現
這是因為相對於基於JAVA的SOCKET實現
本地SOCKET消耗更少的系統資源
雖然SOCKET讀取器的JAVA實現是P
P通信中一種可靠而且可移動的方法
可是他不能為集群中的重型SOCKET使用提供最好的性能
當判斷從SOCKET是否有數據讀取的時候本地SOCKET讀取器使用了更有效率的方法
使用本地SOCKET讀取器實現
讀取器線程不需要去統計靜止的SOCKET
他們僅僅為活動的SOCKET服務
並且在一個給定的SOCKET開始活躍起來時他們可以立刻捕捉到
而使用純JAVA SOCKET讀取器
線程必須動態的統計所有打開的SOCKET
判斷他們是否包含可讀取的數據
換句話說
SOCKET讀取器總是忙於統計SOCKET
即使這些SOCKET沒有數據可讀
這些本不應該的系統開銷降低了性能
TOMCAT 中的集群 雖然在TOMCAT
的早些版本中也有集群的功能
但是在稍後的版本中(
或者更高)
集群變的更加模塊組件化
在 server
xml 中集群元素已經被重構
這樣我們可以替換集群的不同部分而不會影響其他元素
例如
當前配置中把成員服務設置為多點傳送發現
這裡可以輕易地把成員服務修改替換為使用TCP或者 Unicast
而不會改變集類邏輯的其他部分
其他一些集群元素
例如SESSION管理器
復制發送端
復制接受端也可以被自定義的實現取代而不影響集群配置的其他部分
同樣
在TOMCAT集群中的任何服務器組件可以使用集類API向集群中的所有成員發送消息
SESSION復制 服務器集群通常操縱兩種SESSION
sticky sessions和 replicated sessions
sticky sessions就是存在單機服務器中的接受網絡請求的SESSION
其他集群成員對該服務器的SESSION狀態完全不清楚
如果存有SESSION的服務器失敗的話
用戶必須再次登陸網站
重新輸入所有存儲在SESSION中的數據
另一種SESSION類型是
在一台服務器中SESSION狀態被復制到集群中的其他所有服務器上
無論何時
只要SESSION 被改變
SESSION數據都要重新被復制
這就是 replicated session
sticky 和 replicated sessions都有他們的優缺點
Sticky sessions簡單而又容易操作
因為我們不必復制任何SESSION數據到其他服務器上
這樣就會減少系統消耗
提高性能
但是如果服務器失敗
所有存儲在該服務器內存中的SESSION數據也同樣會消失
如果SESSION數據沒有被復制到其他服務器
這些SESSION就完全丟失了
當我們在進行一個查詢事務當中的時候
丟失所有已經輸入的數據
就會導致很多問題
為了支持 JSP HTTP session 狀態的自動失效無縫轉移
TOMCAT服務器復制了在內存中的SESSION狀態
這是通過復制存儲在一台服務器上的SESSION數據到集群中其他成員上防止數據丟失以及允許失效無縫轉移
對象的狀態管理 通過在服務器上的保存狀態可以區分出
種對象
●無狀態
一個無狀態對象在調用的時候不會在內存中保存任何狀態
因為客戶端和服務器端沒必要保存任何有關對方的信息
在這種情況下
客戶端會在每次請求服務器時都會發送數據給服務器
SESSION狀態被在客戶端和服務器端來回發送
這種方法不總是可行和理想的
特別是當傳輸的數據比較大或者一些安全信息我們不想保存在客戶端的時候
●會話
一個會話對象在一個SESSION中只被用於特定的某個客戶端
在SESSION中
他可以為所有來自該客戶端的請求服務
並且僅僅是這個客戶端的請求
貫穿一個SESSION
兩個請求間的狀態信息必須保存
會話服務通常在內存中保存短暫的狀態
當在服務器失敗的時候可能會丟失
SESSION狀態通常被保存在請求間的服務器的內存中
為了清空內存
SESSION狀態也可以被從內存中釋放(就像在一個對象CACHE)
在該對象中
性能和可量測性都有待提高
因為更新並不是被單獨的寫到磁盤上
並且服務器失敗的時候數據也沒辦法搶救
●緩存
緩存對象在內存中保存狀態
並且使用這個去處理從多客戶端來的請求
緩存服務的實現可以擴展到他們把緩存的是數據備份保存在後端存儲器中(通常是一個關系數據庫)
●獨立的
一個獨立的對象在一個時間內只活躍在集群中的一台服務器上
處理來自多客戶端的請求
他通常由那些私有的
持久的
在內存中緩寸的數據支持
他同樣也在內存中保持短暫狀態
在服務器失敗的時候要重建或者丟失
當失敗的時候
獨立對象必須在同一個服務器上重起或者移植到另一台服務器上
(來源:
Using WebLogic Server Clusters
)
SESSION復制的設計考慮事項
網絡考慮事項 把集群的多點傳送地址和其他應用程序隔離是至關重要的
我們不希望集群配置或者網絡布局干擾到多點傳送服務器通信
和其他應用程序共享集群多點傳送地址將迫使集群的服務器例程處理不應該的消息
消耗系統內存
共享多點傳送地址可能也會使IP多點傳送緩沖過載
延遲服務器 heartbeat 消息傳輸
這樣的延遲可能導致一個服務器例程被標識為死亡
僅僅因為他的 heartbeat 消息沒有被及時接收
編程考慮事項 除了上面提到的網絡相關因素
還有些和我們寫 J
EE 網絡應用程序有關的設計考慮也會影響SESSION復制
以下列出了一些編程方面的考慮
●SESSION數據必須被序列化
為了支持HTTP session 狀態的內存內復制
所有的 servlet 和 JSP session 數據必須被序列化
對象中的每個域都必須被序列化
這樣對象被可靠的序列化
●把應用程序設計為冪等的
冪等的的意思就是一個操做不會修改狀態信息
並且每次操作的時候都返回同樣的結果(換句話說就是
做多次和做一次的效果是一樣的)
通常
WEB請求
特別是 HTML forms 都被發送多次(當用戶點擊發送按紐兩次
重載頁面多次)
導致多次HTTP請求
設計SERVLET和其他WEB對象為 冪等的
可以容忍多次請求
詳細可以去參考設計模式
Synchronized Token
和
Idempotent Receiver
關於怎樣設計冪等的的應用程序
●在BUSINESS層存儲狀態
會話狀態應該使用有狀態的SESSION BEANS存儲在EJB層
而不是存儲在WEB層的HttpSession
因為企業應用程序要支持各種類型客戶端(WEB客戶端
JAVA應用程序
其他EJB)
存儲數據在WEB層會導致在客戶端的雙數據存儲
因此
有狀態的SESSION BEAN在這些情況下就被用於存儲SESSION狀態
無狀態的SESSION BEAN要為每次的調用重構造會話狀態
這些狀態可能必須從數據庫中恢復的數據中重編譯
這些缺點失去了使用無狀態SESSION BEAN去提高性能和可測量性的目的
嚴重的減低了性能
●序列化系統消耗
序列化SESSION數據在復制SESSION狀態的時候回會些系統消耗
隨著序列化對象大小的增長消耗也越多
最好是保持SE
From:http://tw.wingwit.com/Article/program/Java/ky/201311/28514.html