使用WebSphere構(gòu)建J2EE應(yīng)用程序
集群拓?fù)溆袃煞N類型,垂直集群或水平集群。垂直集群在同一節(jié)點(diǎn)或物理計(jì)算機(jī)上具有多個集群成員。水平集群在計(jì)算單元中的很多計(jì)算機(jī)的多個節(jié)點(diǎn)上都具有集群成員。本文將討論如圖 1 所示的水平集群拓?fù)洹?BR>
我們將討論在設(shè)計(jì)基于 Web 的應(yīng)用程序時(shí)的三個注意事項(xiàng):
實(shí)現(xiàn)應(yīng)用程序文件同步
在企業(yè)應(yīng)用程序的生命周期中,通常可以通過應(yīng)用修復(fù)程序、添加新的 Web 內(nèi)容或更新應(yīng)用程序行為來對已部署的應(yīng)用程序進(jìn)行更新。一般來說,應(yīng)用程序提供了允許用戶上傳在服務(wù)器端更改或創(chuàng)建的文件的用戶界面。
將下面的場景作為一個示例:用戶希望更新 Web 站點(diǎn)徽標(biāo)圖像文件,并且將原始文件作為 .war 文件應(yīng)用程序的一部分進(jìn)行存檔。該應(yīng)用程序提供了相關(guān)的功能和用戶界面,以便用戶完成這項(xiàng)任務(wù)。然后,用戶選擇一個新的圖像作為 Web 站點(diǎn)的新徽標(biāo),并且上傳該文件。系統(tǒng)使用新的文件替換原始的文件,并且當(dāng)用戶再次訪問他的 Web 站點(diǎn)時(shí),可以看到相應(yīng)的更改。在單節(jié)點(diǎn)環(huán)境的應(yīng)用服務(wù)器中,所有這些工作都可以順利進(jìn)行。然而,在集群環(huán)境中卻存在一些問題。
在集群環(huán)境中,如圖 2 所示,WebSphere Application Network Deployment 服務(wù)器中的 Deployment Manager 將接收到用戶的上傳請求,然后該請求被發(fā)送到 Node A。Node A 將執(zhí)行相應(yīng)的業(yè)務(wù)邏輯并使用本地文件系統(tǒng)中的新圖像文件替換原始圖像文件。然而該集群中其他的成員并不清楚這項(xiàng)更改,其本地副本并沒有得到更新。因此,該集群中各個成員之間的這個圖像文件就出現(xiàn)了不一致的情況。如果 Node A 因?yàn)橹旅e誤而停機(jī),而 Node B 接收到了該請求,那么仍將使用原始的 Web 站點(diǎn)徽標(biāo)。看上去客戶似乎丟失了他所做的更改。

這意味著,當(dāng)應(yīng)用程序運(yùn)行于 WebSphere Application Server 時(shí),需要在集群成員之間同步配置文件、二進(jìn)制文件和資源文件。有一種機(jī)制可以處理上述問題。解決方案是使用共享的文件系統(tǒng)(例如,NFS)或共享的數(shù)據(jù)庫。在這個解決方案中,所有經(jīng)過更改或更新的文件都位于同一個共享文件系統(tǒng)或同一數(shù)據(jù)庫中。對于共享的文件系統(tǒng),所有應(yīng)用程序都使用相同的位置,因此對于這些應(yīng)用程序來說,任何文件更改都是可見的。對于共享的數(shù)據(jù)庫,應(yīng)用程序可以從數(shù)據(jù)庫中獲得相應(yīng)的更改。
上述解決方案的缺點(diǎn)包括:
- 共享的文件系統(tǒng)和數(shù)據(jù)庫導(dǎo)致一個新的單點(diǎn)故障。
- 它增加了編程和配置工作的復(fù)雜性。
- 它引入了一個新的性能瓶頸。
另一個解決方案是使用細(xì)粒度 WebSphere Application Server 應(yīng)用程序管理 API,在集群的各個成員之間實(shí)現(xiàn)文件同步。WebSphere 6.0 中提供了這一特性。WebSphere 6.0 中包含許多改進(jìn),從而使得應(yīng)用程序的部署更加容易并且更加高效。有關(guān)詳細(xì)信息,請參見 WebSphere Application Server 信息中心
WebSphere 6.0 還提供了靈活的應(yīng)用程序文件管理。它允許應(yīng)用程序通過以下方式進(jìn)行更新:
- 替換整個應(yīng)用程序(例如,整個 .ear 文件)。
- 替換、添加或刪除應(yīng)用程序中的單個模塊(例如,.war、EJB.jar 或 .rar 文件)。
- 替換、添加或刪除單個文件。
- 替換、添加或刪除多個文件。
在對集群中的某個成員上的應(yīng)用程序文件進(jìn)行更新之后,將使用另一個新的特性 Rollout Update 對集群中各個成員的文件進(jìn)行同步。它通過以下方式對應(yīng)用程序進(jìn)行更新:
- 保存更新的應(yīng)用程序配置。
- 停止給定節(jié)點(diǎn)上所有的集群成員。
- 通過同步配置和重新啟動該節(jié)點(diǎn)上停止的集群成員來更新該節(jié)點(diǎn)上的應(yīng)用程序。
讓我們回到前面關(guān)于 Web 站點(diǎn)徽標(biāo)更新的示例。在這個場景中,徽標(biāo)的更新和同步對于用戶來說應(yīng)該是透明的,無需 WebSphere 管理員進(jìn)行人工干預(yù)。這就意味著,應(yīng)用程序必須控制應(yīng)用程序的更新,如替換存檔于 ear 文件中的原始文件,并在集群的成員之間執(zhí)行文件同步。您可以通過調(diào)用 WebSphere 提供的 Java Management Extensions (JMX) 接口來完成這項(xiàng)任務(wù)。JMX 是一項(xiàng) Java 應(yīng)用程序資源管理標(biāo)準(zhǔn)。有關(guān) JMX 的詳細(xì)信息,請參見 JMX Web 站點(diǎn)

應(yīng)用程序在接收到用戶上傳的文件之后,它將調(diào)用 File Updater 以構(gòu)造增量 EAR 文件。這個增量 EAR 文件是一個存檔文件,它具有與完整的應(yīng)用程序 ear 文件相同的結(jié)構(gòu)。增量 EAR 文件和完整的應(yīng)用程序 EAR 文件之間的區(qū)別在于,該增量 EAR 文件僅包含要進(jìn)行更新的文件。File Updater 將構(gòu)建這個增量 EAR。它可以是封裝了增量 EAR 生成邏輯的簡單 Java 類,或者是添加了驗(yàn)證邏輯和生成文件的相關(guān)復(fù)雜組件。
序列化會話對象
使用集群方式的應(yīng)用程序可以提高系統(tǒng)的可靠性和可用性。然而,這也引入了一些挑戰(zhàn),如會話管理。HTTP 會話是包括用戶特定信息的集合。從用戶開始訪問到用戶最后一次訪問結(jié)束的這段時(shí)間內(nèi),由容器對會話進(jìn)行維護(hù)。會話由一系列的會話屬性組成。事實(shí)上,這些屬性都是由系統(tǒng)或開發(fā)人員創(chuàng)建的 Java 對象。
在集群環(huán)境中,開發(fā)人員必須清楚,HTTP 會話可能運(yùn)行于多個 JVM 中。這些會話屬性應(yīng)該在每個 JVM 中保持一致。否則,當(dāng)應(yīng)用程序運(yùn)行于不同的節(jié)點(diǎn)時(shí),相同的輸入可能產(chǎn)生不同的結(jié)果,這是因?yàn)榕c用戶相關(guān)的數(shù)據(jù)在這兩個節(jié)點(diǎn)中不一致。
WebSphere 為集群方式的應(yīng)用程序提供了實(shí)時(shí)的、完全一致的數(shù)據(jù)共享。然而,前提是必須對所有共享的屬性進(jìn)行序列化和反序列化。當(dāng)您將 Java 對象放入到會話中并希望在所有的節(jié)點(diǎn)之間共享該對象時(shí),需要將這個 Java 對象聲明為一個 serializable 接口。下面的代碼顯示了在將對象放入到會話屬性時(shí)進(jìn)行的驗(yàn)證工作。
- public class MySession{
- public static void addObjectToSession(HttpServletRequest req, String key, Object value) {
- HttpSession session = req.getSession(true);
- if(value instanceof Serializable)
- session.setAttribute(key, value);
- else
- throw new NonSerializationException ();
- }
- public MySession() {
- }
- }
在上面的示例中,您創(chuàng)建了一個名為 MySession 的新類,用來將對象添加到會話中。您可以通過調(diào)用 addObjectToSession() 方法來添加它。首先應(yīng)該檢查該對象是否實(shí)現(xiàn)了 serializable 接口。如果已經(jīng)實(shí)現(xiàn),可以隨后將這個對象添加到當(dāng)前的 Http 會話中。否則,將會出現(xiàn) NonSerializationException。有些時(shí)候,在運(yùn)行于另一個 JVM 中時(shí),會話屬性中包含的信息無關(guān)緊要,如文件的絕對目錄。在這種情況下,通過將其聲明為瞬態(tài)屬性可以使得這些字段不使用集群方式。
使用動態(tài)緩存
如上所述,將應(yīng)用程序數(shù)據(jù)保存在中央數(shù)據(jù)庫中可以確保在集群環(huán)境中寫入和一致地讀取數(shù)據(jù)。這種解決方案的缺點(diǎn)是,數(shù)據(jù)庫服務(wù)器引入了新的單點(diǎn)故障 (SPOF),并且不適合那些需要高性能的應(yīng)用程序。另一種解決方案是使用 WebSphere Dynamic Cache 和 Data Replication Service (DRS)。您可以在基于內(nèi)存的對象緩存的方式下,通過共享整個集群中某些服務(wù)器上的對象,來實(shí)現(xiàn)這個解決方案。圖 4 顯示了帶 Data Replication Service 的 WebSphere Dynamic Cache 的體系結(jié)構(gòu)。

WebSphere Dynamic Cache 是面向 J2EE 體系結(jié)構(gòu)和緩存對象的解決方案。表示層中 Web 服務(wù)、Servlet 和 JSP 的輸出、WebSphere 命令類以及 Java 對象都可以使用應(yīng)用程序編程接口 (API) 進(jìn)行緩存,或者聲明一些緩存策略并將其添加到應(yīng)用程序中。
Data Replication Service (DRS) 是用于復(fù)制數(shù)據(jù)的 WebSphere Application Server 內(nèi)部組件。DRS 使得集群中的各個服務(wù)器都可以使用會話管理、動態(tài)緩存和無狀態(tài)會話 Bean 的數(shù)據(jù)。動態(tài)緩存可以利用應(yīng)用服務(wù)器中的 DRS 在集群的各個服務(wù)器中復(fù)制緩存的數(shù)據(jù)。在集群范圍內(nèi)傳輸數(shù)據(jù)失效通知,以保持?jǐn)?shù)據(jù)的一致性和有效性。圖 5 顯示了如何使用動態(tài)緩存和 DRS 在集群中共享應(yīng)用程序數(shù)據(jù)。

首先,應(yīng)用程序運(yùn)行于 Server One,并通過調(diào)用 DistributedMap API 將 Object A 放入其本地緩存中。通過合適的配置,DRS 可以在整個集群范圍內(nèi)復(fù)制緩存的對象并保持緩存數(shù)據(jù)的一致性。因此,將 Object A 復(fù)制到 Server Two 的本地緩存。當(dāng)應(yīng)用程序運(yùn)行于 Server Two(假如 Server One 遇到問題或根據(jù)負(fù)載平衡策略將事務(wù)提交到 Server Two)時(shí),應(yīng)用程序可以從 Server Two 的本地緩存中獲得 Server One 的 Object A。
WebSphere Application Server 通過使用緩存實(shí)例存儲和管理緩存的 Java 對象。緩存實(shí)例還可以用于對相關(guān)的對象進(jìn)行邏輯分組。特定實(shí)例的緩存中存儲的對象不會受到其他緩存實(shí)例的影響。如上所述,DistributedMap 公共接口使得應(yīng)用程序可以直接訪問緩存實(shí)例。
應(yīng)用程序可以存儲和檢索任何實(shí)現(xiàn)了 java.util.Map 接口的對象。您所緩存的任何其他 Java 對象都必須實(shí)現(xiàn) java.io.Externalizable 或 java.io.Serializable 接口。集群中的服務(wù)器可以通過使用其 JNDI 名稱來訪問緩存實(shí)例。這些服務(wù)器必須位于同一個復(fù)制域。下面的代碼示例顯示了應(yīng)用程序如何通過其 JNDI 名稱查找緩存實(shí)例,將對象放入緩存實(shí)例中,并稍后對其進(jìn)行檢索。
- Import javax.naming.InitialContext;
- Import com.ibm.websphere.cache.DistributedMap; ... InitialContext context=new InitialContext();
- DistributedMap map=(DistributedMap)context.lookup("cache/example_cache_instance");
- map.put("cache_id", yourJavaObject);
- YourJavaObject obj=(YouJavaObject)map.get("cache_id");
結(jié)束語
本文討論了設(shè)計(jì)運(yùn)行于 WebSphere 集群環(huán)境的應(yīng)用程序時(shí)需要考慮的三個方面。存儲于文件系統(tǒng)的應(yīng)用程序數(shù)據(jù)應(yīng)當(dāng)在每個集群服務(wù)器中保存一致。針對這個需求的解決方案是使用共享的文件系統(tǒng)或共享的數(shù)據(jù)庫。使用細(xì)粒度文件更新特性,您可以在集群范圍內(nèi)擁有更靈活的應(yīng)用程序文件,并避免引入新的單點(diǎn)故障。會話管理是 Web 應(yīng)用程序的一個重要的考慮事項(xiàng)。您應(yīng)該考慮進(jìn)行對象序列化和反序列化,以便在集群范圍內(nèi)進(jìn)行共享。您可以使用自已定義的類將對象封裝到會話中,然后同時(shí)執(zhí)行驗(yàn)證。您還可以通過使用 WebSphere Dynamic Cache 和 Data Replication Service 實(shí)現(xiàn)集群范圍內(nèi)應(yīng)用程序數(shù)據(jù)的共享,這將顯著地提高應(yīng)用程序的性能。
【編輯推薦】