高可用性要求一種合適的基礎結構
但是
如果沒有將該基礎結構與J
EE應用程序設計策略進行協調平衡
性能很可能就會受損
如果您在高可用性硬件和軟件基礎結構方面投資了一筆數目可觀的資金
您就必須保證應用程序具備高可用性-至少應保證J
EE(Java
平台企業版)中普遍存在的做法可保證應用程序具備高可用性
別忘了
當您將數據庫和應用程序服務器的群集與群集軟件進行組合時
您將會獲得一個相當有效的組合
這裡的群集軟件包括Oracle
i數據庫和Oracle
i應用程序服務器(Oracle
iAS)中的軟件
這些群集軟件既可以將請求自動發送到可用的服務器
還可以提供透明的應用程序失敗處理
當您在J
EE體系結構中增加這類數目眾多的混合狀態管理機制(具有狀態的Web會話和無狀態Web會話
具有狀態的商業組件和無狀態商業組件
自動復制或備份beans等等)時
您應該同時保證具備高可用性
不幸地是
這種普遍的做法並非完全正確
盡管服務器與相應軟件的群集可以提供高可用性
但是它們卻無法保證高可用性
事實上
某些高可用性功能(如J
EE的狀態管理機制)的過度使用就可能會降低應用程序的性能
進而降低整體的可用性
即便使用最好的體系結構
要真正實現高可用性
其中的關鍵一步就是從一開始就把高可用性考慮到應用程序的設計中來
因此
您需要從以下幾個方面來特別關注應用程序的設計
· 便捷的狀態管理
投入一定時間來識別並確定應用程序的狀態
然後將狀態精確映射到各種可用的狀態管理機制
避免過度使用某一類型的機制而導致性能降低
· 仔細的層次設計
分析應用程序是否真正需要很多層
層次會增加復雜性
導致性能劣化並且降低可用性
· 失敗處理策略
確定並處理那些基礎結構無法自動檢測和修復的失敗
如果在應用程序設計的各個步驟中額外多投入一些時間
同時應用本文所描述的各種策略
那麼應用程序的可用性將會顯著增強
便捷的狀態管理
要確保實現高可用性
您就需要具備有效的狀態恢復機制
如果一個組件失敗
系統在處理新的請求之前
必須先恢復該組件所保持的狀態
J
EE提供多種便捷的狀態管理機制
但是這些機制常常被過度使用
而過度使用這些機制經常帶來一些不幸的結果
包括 JavaServer Pages (JSP)頁中的會話范圍的JavaBeans
HTTP會話對象servlets以及用於商業組件的有狀態會話bean等在內的這些狀態管理機制
可以識別並確定失敗時必須保持的狀態
所有這些機制都使用存儲在內存中的Java 對象來表示應用程序的狀態
在HTTP會話過程中以Java形式來保存這些對象可以為編程人員提供必要的便捷
但是卻很容易會忘記進行相關備份所需的代價
應用程序服務器(如Oracle
iAS)通過在數據庫
文件或者備份服務器的有效內存中對這些存儲在內存中的Java 對象的副本進行備份
就可以在必要時積極采取相應的恢復措施
對Java 對象進行備份時常常要求使用代價昂貴的 Java 串行操作
如果將許多大型的Java 對象用於狀態管理(這是一種常見的應用程序設計策略)
就會使J
EE 狀態管理機制負載過重
因此
應用程序的性能將會劣化到極低的級別
這會讓人無法接受
當然
這也與高可用性的目標背道而馳(我們認為一個速度極慢的應用程序不具有高可用性)
作為這種 J
EE 標准方法的另一可選方法
您應該關注多數大型 Web 站點(這些站點同時又具備高可用性)所使用的模型
在該模型中
應用程序的狀態主要保存在持久穩固的存儲器(如數據庫)中
同時在內存中進行了緩存處理以便改善響應時間(這與J
EE模型不同
J
EE模型中一開始就將狀態存儲在內存中
然後由應用程序服務器進行備份)
這裡
最關鍵的不同之處就是
對於大型的Web站點模型
應用程序的寫進程已投入一定時間來識別並確定應用程序狀態的關鍵片斷
同時還設計了一種有效機制(緩存)
用於從應用程序對緩存進行訪問
因而
中間層組件的失敗並不需要恢復中間層的狀態
而僅需重新啟動緩存
這是因為需要時可以從後端再次導入相關的狀態
一些大型的 Web站點更進一步
它們對應用程序的狀態進行分離
然後將其分別存儲在穩固持久的後端存儲器和客戶端浏覽器中
一些狀態以cookie的形式保存在浏覽器中
這樣就隱藏了 HTML 形式的元素或 URL 參數
這種技術不僅提供了更高的可用性
而且還提高了應用程序的整體品質
如果浏覽器處於未連接狀態
這種技術允許終端用戶很容易地重新開始連接會話
現在很清楚了
J
EE應用程序開發人員需要預先投入一定時間來分析應用程序狀態
然後根據特定策略將其映射到適當的可恢復存儲器中
接下來的一個問題就是如何確定哪些狀態應該映射到後端數據庫而哪些狀態應該映射到浏覽器
幸運地是
這個問題的答案通常是相當簡單直接的
它取決於所要映射的狀態信息的類型
應用程序的狀態通常可分為下面三種類型
· 頁狀態
此種類型的狀態在一頁中是有效的
例如
搜索查詢返回的一系列結果的開始索引
· 會話狀態
此種類型的狀態通常在一次會話的整個過程中是有效的
例如
運行應用程序的末端用戶的身份
· 持久狀態
此種類型的狀態的生命周期為端用戶會話
例如
購物報表或開支報告的內容
在常見的典型應用程序中
大多數應用程序狀態都是這種持久狀態類型的
一旦您將應用程序的狀態劃分為上述三種類型
您就可以將狀態映射到適當的持有器中
請您在腦中牢記
您的目標之一就是通過一種J
EE 機制使在中間層內存器中保存的狀態盡可能少
映射頁狀態
處理頁狀態的最佳方式就是將其存儲隱藏形式的元素或URL參數中
這些元素或參數嵌套在該頁中
因為此狀態需要在該頁面對浏覽器可用的整個期間中始終保持
因而它並不會產生恢復問題
諸如 Oracle
iAS 的J
EE MVC 框架之類的模型查看控制器(Model View Controller)框架
使用隱藏形式的元素將頁面流信息保存在每一個Web頁面中
映射會話狀態
您可以保存一些會話狀態
如用戶身份和in cookies
身份驗證系統(如Oracle
iAS Single Sign
On)就使用此種方法
然而
您需要在中間層內存中保存會話狀態的其他一些部分
如果cookie 的數目過多或者內容過大
就無法進行高效操作
在這些情況下
您就應該使用之前已提及的一種 J
EE狀態管理機制
把使用這些機制的情形限制到這些場合有助於保持較高的可用性
映射持久狀態
您應該非常明確地將持久狀態保存在後端數據庫中
您可以在中間層內存中對其進行緩存以便提高效率(Oracle
iAS 中的特殊JSP 標記庫可以在 Web 緩存和 J
EE 容器中對頁片斷進行緩存)
然而
您可能希望數據庫成為真實數據的來源以便中間層失敗時避免出現恢復問題
請注意
強烈建議顯式標識狀態並且通過正規的數據庫訪問機制(如實體 beans或 Java Database Connectivity (JDBC))將狀態顯式存儲在數據庫中
通過此種方式來映射這三種類型的狀態
就可以創建狀態安全的應用程序
狀態安全的應用程序可以避免無狀態應用程序的局限性
而可用性並不差
仔細的層次設計
層次設計是獲得可用性的另一領域
在J
EE中
通常有這樣一個共識
應用程序應該由多種層次組成
然而
如果您使用過多的層次
不僅不會增強可用性
反而還可能會阻礙了可用性
使用多種層次的原因是相當明顯的
首先
仔細的多層設計有助於隔離各種故障
例如
商業組件雖然失敗但並不會影響Web前端的可用性
這一點可持續至前端需要使用該組件為止
而且
在一些情況下
每一層中運行更少的邏輯可以使每一層變得更健壯
但是
使層的數目盡可能保持最低具有非常顯著的優勢
這使應用程序可以更容易地進行管理和監控
為那些負責實現高可用性的操作組提供巨大的幫助
而且
如果一個應用程序具有層數不多
通常就更易於設計
因而整體上就更加健壯
最後
設計一個層數不多的應用程序(例如
使用Enterprise JavaBeans (EJB)
本地接口)可以獲得更優的性能
這也同時會大大增強可用性
如果您將目標鎖定為高可用性
但又無法確定選用的層數應該多一些還是少一些
請您相信
使用更少的層數
出錯的可能性就會更低
失敗處理策略
與狀態管理和層次設計一樣
我們在失敗處理方面過分依賴於常規的方法和高可用性基礎結構的實際能力
因為現在的應用程序服務器能夠自動檢測和修復許多組件失敗
我們就不必投入太多的精力
以便我們的應用程序能夠處理那些不能自動修復的失敗
但是我們並沒有意識到
真正的高可用性則要求應用程序和應用程序服務器之間能夠相互協作
雙重事務是一種常見的失敗類型
這種類型的失敗很難做到自動修復
終端用戶兩次單擊Bill Me 按鈕就是該類失敗的一個示例
由於雙重事務的產生因素在於不同層之間的通信失敗
所以修復就可能會涉及一些位於應用程序服務器內嵌的修復機制范圍之外的問題
請這樣一種簡單的情形
一個JSP 頁面通過JDBC 提交事務
但是卻收到了網絡通信錯誤
那麼應用程序服務器如何才能確定在通信失敗之前該事務是否已經提交?應用程序服務器是否應該自動再重復先前的操作?這類問題在層次緊密的體系結構中更加難以解決
其中JSP頁調用在多個分布式容器中運行的EJB
通信錯誤表示bean 調用根本就沒有執行完畢
在這種情況下再次進行調用就非常合適
可是
相同的錯誤也可能是起因於這樣一種情況
調用本身已取得成功但是
From:http://tw.wingwit.com/Article/program/Oracle/201311/17598.html