首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java EE 應用水平擴展實戰:從集群架構到分布式緩存與並行處理

     編輯:Java 相關知識

為何需要水平擴展?

當併發用戶數顯著增長,單台機器的效能往往無法滿足需求,或是受限於單一 JVM 實例的 GC 機制,導致應用難以進一步擴展。此時,將系統部署到多個 JVM 實例甚至多台伺服器上運行,即為水平擴展。值得注意的是,即便在同一台物理機器上運行多個 JVM 實例,也屬於水平擴展範疇,而非垂直擴展。因為 JVM 之間無法透過管道、共享記憶體或訊號量通訊,最高效的方式是 Socket 通訊。換言之,若應用能跨多個 JVM 運行,通常也能平滑擴展至多台伺服器。

隨著廉價高效能伺服器普及,透過叢集組裝低成本機器群,可獲得超越昂貴超級電腦的運算能力。但這也帶來了管理複雜度與程式模型的挑戰,如節點間吞吐量與延遲問題。Java EE 叢集技術已相當成熟,內部機制可參考 TSS 上的《Uncover the Hood of J2EE Clustering》。

核心架構原則:無共享架構(Share-Nothing Architecture, SNA)

Figure 3: share nothing cluster

最具擴展性的架構莫過於無共享叢集架構。在此架構中,每個節點功能完全相同,且無需感知其他節點存在。負載平衡器負責將請求分發至後端實例,僅執行請求分派、健康檢查、Session 保持等輕量工作,極少成為瓶頸。若後端資料庫系統足夠強大,單純增加節點即可實現運算能力的線性增長。

Session 複寫:打破無共享原則的必要之惡?

幾乎所有 Java EE 廠商皆實作 HttpSession Failover,確保節點故障時 Session 不遺失。但這實質上打破了無共享原則:相同 Session 資料需在兩個以上節點間共享。除非萬不得已,建議避免使用 Session Failover。因為故障發生時,Failover 並無法完全避免錯誤,反而會損害效能與擴展性。

若必須使用,選擇可擴展的複寫機制

若為了用戶體驗必須啟用 Failover,關鍵在於選擇可擴展的複寫方案。廠商提供的方案包括:資料庫持久化、中央狀態伺服器、節點間記憶體複寫。其中成對節點複寫(Paired Node Replication)最具擴展性,為 BEA WebLogic、JBoss、IBM WebSphere、GlassFish V2+ 所採用。最不推薦資料庫持久化 Session:實驗室測試顯示,若 Session 物件頻繁更新,僅 3-4 個節點即可導致資料庫崩潰。

部署策略:Collocated 部署優於分散式

Java EE(特別是 EJB)天生為分散式運算設計,解耦業務邏輯與遠端元件讓多層架構流行。但對擴展性而言,減少分散式層次反而更有利。

Figure 4: distributed structure Figure 5: collocated structure

實驗室以政府專案測試同樣伺服器數量下的兩種部署:分散式與 Collocated。結果證明 Collocated 部署擴展性更佳。假設一個方法調用多個 EJB,若每次調用都經負載平衡分散到不同伺服器,會產生大量無謂的跨伺服器呼叫,甚至導致應用崩潰;若涉及跨伺服器交易,效能損害更大。Collocated 方式將相關元件部署在同一 JVM,避免遠端呼叫開銷。

共享資源與服務的處理

叢集系統擴展後的效能,取決於對不支援線性擴展的共享資源的操作:資料庫伺服器、JNDI 樹、LDAP 伺服器、外部檔案系統等。

  • 外部檔案系統:叢集內節點若需複寫檔案,隨節點增加會佔滿網路頻寬與 CPU。解決方案:改用資料庫儲存檔案、採用 SAN 集中儲存、或高效分散式檔案系統(如 Hadoop DFS)。
  • 共享服務:如分散式日誌、時間服務,常部署於專屬節點。分散式鎖管理器(DLM)需確保同步存取,即使網路延遲或節點故障也能正常運作。實驗室曾測試某 ERP 系統自製 DLM,持有鎖的節點失效導致鎖永遠無法釋放。

分散式快取:叢集擴展的關鍵

幾乎所有 Java EE 專案都使用物件快取提升效能,但許多快取僅設計給單 JVM 環境。叢集中每個 JVM 維護自己的快取,為保持狀態一致需同步,同步機制有時比不使用快取效能更差。因此可擴展的分散式快取系統至關重要。

主流開源方案實測比較

  • 1 個基於 JBoss Cache 的專案
  • 3 個基於 Terracotta 的專案
  • 9 個基於 Memcached 的專案

測試結果:Terracotta 能良好擴展至 10 節點,5 節點內效能極高;Memcached 則在 20+ 節點時表現優異。

Memcached:高效能分散式物件快取

Memcached 透過兩階段 Hash 實現鍵值查找:客戶端先依伺服器列表 Hash 定位伺服器,伺服器端再做內部 Hash 定位資料。客戶端 Hash 層使得新增節點極簡單,無節點互連負載、無多播協議洪水效應。雖非 Java 產品,但提供 Java Client API,整合輕鬆。

使用關鍵注意事項:

  • 勿快取寫入頻繁物件:Memcached 針對讀多寫少場景,需關注讀/寫比率。
  • 避免 Memcached 節點互相調用:對擴展性災難性打擊。
  • 避免單行式快取:改用複雜物件聚合快取。
  • 選擇合適 Hash 演算法:預設演算法增減節點會導致所有快取失效,建議採用一致性 Hash(Consistent Hashing),確保大部分快取物件仍有效。

Terracotta:JVM 級叢集方案

Figure 6: Terracotta JVM clustering

Terracotta 為企業級開源 JVM 級叢集方案,擴展 JVM 記憶體模型,讓不同虛擬機上的執行緒如同在同一 JVM 中交互。程式設計方式與單機應用無異,無專屬 API,透過位元碼織入(Bytecode Weaving) 注入叢集邏輯。實驗室測試顯示超過 20 節點時擴展性不佳,推測與其互連或多播協議機制有關(僅代表實驗室測試結果)。

並行處理:打破單執行緒瓶頸

單執行緒任務是擴展性瓶頸。對於處理巨大資料集的任務(如每週 120GB 日誌分析),單執行緒需 4 小時,採用 Hadoop MapReduce 水平擴展至 10+ 節點並行,僅需 7 分鐘。

MapReduce 與 Hadoop

MapReduce 由 Google 提出,包含 Map(並行處理資料集產生中間結果)與 Reduce(合併中間結果)兩階段。Hadoop 為開源純 Java 實作,支援大型廉價叢集,廣泛應用於 Yahoo、Amazon EC2/S3、Sun Grid Engine。應用場景涵蓋分散式檢索、排序、Web 鏈結分析、日誌分析、索引重建、文件叢集、機器學習、統計機器翻譯等。

MPI 與 CCJ

MPI(Message Passing Interface)為語言無關的平行通訊協定,Java 實作有 mpiJava(JNI 綁定 Native MPI)與 MPJ(100% 純 Java)。CCJ 提供 barrier、broadcast、scatter、gather 等集合操作,底層用 Java RMI,支援複雜序列化物件傳遞。

突破傳統思維:為極致擴展而生的非常規架構

Google 為滿足擴展需求,自研 GFS(分散式檔案系統)與 Bigtable(分散式資料庫),不遵循 POSIX 或 ANSI SQL 標準,卻完美支撐其海量儲存與擴展需求。

實驗室測試某社交網站應用(Tomcat + MySQL,20+ 廉價 PC Server),採用用戶資料分區:不同用戶資料存放於不同資料庫實例,元資訊表記錄路由規則。應用先查元資訊表定位目標資料庫,再執行操作。

Figure 7: Users data partitions

優勢:擴展寫入頻寬(並行寫入)、高可用性(單庫故障僅影響部分用戶)。挑戰:動態增減節點難用連線池、兩步操作難用 ORM、跨庫複雜查詢困難。架構師表示已準備好應對方案,甚至預留了元資訊表再分區的二級路由機制。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved