隨著 J2EE 平台日趨成熟,企業越來越需要在 Web 層支撐成千上萬的並發用戶。單靠垂直擴展(增加單機 CPU、記憶體)早已撞上硬體上限與成本瓶頸,且單點故障風險極高。業界主流解法轉向「廉價伺服器 + 高速 LAN + 開源叢集軟體」的水平擴展架構,本文將深入解析開源分散式通訊基石 JavaGroups 如何為 Web 層會話複寫提供即插即用的「膠水層」。
傳統單機 SMP 伺服器受限於位址空間與硬體成本,超過 4 颗 CPU 往往需要專用硬體,維護成本飆升。更嚴重的是單點故障:一旦主機掛掉,整站癱瘓。叢集透過多台鬆散耦合的伺服器邏輯合為一體,帶來三大紅利:
硬體成本驟降、Linux 普及、TCP/IP 程式模型成熟,使得「商用級叢集」不再是大廠專利。
以線上購物車為例,用戶會話 ID 存在 Cookie 或 URL,後續請求必須路由到持有該會話的節點。若能將會話物件在叢集間即時複寫,任何節點皆可服務任一請求,即實現真正的負載均衡與故障轉移。自行開發網路通訊層極難處理封包遺失、網路分區、節點動態加退等邊界條件,JavaGroups 正是為此而生。
JavaGroups 以 Channel(通道) 為核心抽象,將開發者與協定堆疊解耦:

MessageDispatcher(同步請求/回應)、RpcDispatcher(遠端方法調用)、ReplicatedTree/DistributedHashtable(即用型分散式資料結構)。範例應用 JGCart 以 Swing 模擬單一用戶會話,啟動多個實例即組成叢集。點擊「Buy」按鈕時,本地不直接修改模型,而是廣播 AddItemMessage;所有節點(含發送者)在 MessageListener.receive() 中統一更新狀態,實現強一致複寫。


// 1. 建立協定堆疊字串
String props = "UDP:PING:FD(timeout=5000):STABLE:VERIFY_SUSPECT(timeout=1500):"
+ "MERGE:NAKACK:UNICAST(timeout=5000):FRAG:FLUSH:GMS:STATE_TRANSFER:QUEUE";
// 2. 啟用狀態傳輸事件
channel.setOpt(Channel.GET_STATE_EVENTS, Boolean.TRUE);
channel.connect(groupName);
channel.getState(null, 0); // 非同步拉取現有狀態
// 3. 實現 MessageListener 介面
public Object getState() { return cstate.deepCopy(); } // 深拷貝防併發不一致
public void setState(Object state) { cstate = (CartState)state; orderModel.changeData(cstate); }
若節點啟動時購物車已有商品,新節點需主動拉取最新狀態。JavaGroups 內建 STATE_TRANSFER 微協定,配合 GET_STATE_EVENTS 選項,讓新節點連線後自動向協調者請求完整狀態快照。實測:啟動節點 A → 加入商品 → 啟動節點 B → 節點 B 即顯示完整購物車,後續操作雙向同步。

pbcast.* 系列)並啟用 TUNNEL 穿透防火牆。Serializable 並保持輕量,避免狀態傳輸延遲。JavaGroups 以極簡 API(Channel + 協定字串)封裝了分散式系統最棘手的成員管理、可靠多播、狀態傳輸,讓開發者專注於業務邏輯。本文透過 JGCart 完整演示了「會話複寫 → 故障轉移 → 負載均衡」的閉環,證明開源軟體完全能支撐商用級 Web 層叢集。下一篇將探討 JBoss Cache / Infinispan 等更高層的資料網格方案。