Spring Web Flow是Spring Framework中的web應用組件它提供了一種編寫有狀態和基於會話的web應用的簡便手段Spring Web Flow使得邏輯流程成為Web應用中的一等公民它能讓你定義為自包含模塊以獨立於應用的其它部分來配置和重用
Spring Web Flow引入了幾種有狀態數據域requestflashflow和conversation等這讓你能用新的方式來開發有狀態Web應用它也提供了定制應用狀態管理的擴展點
Terracotta for Spring是通過在多個JVM集群來給基於Spring的應用提供高可用性的運行時它給Spring Web Flows的所有域都提供了透明的聲明式集群服務(普通的Spring beans同樣適用)
在這篇文章中我們會首先給你一個Spring Web Flow和Terracotta for Spring的總體介紹然後會向你展示如何聯合使用這些技術來進入構建有狀態基於會話可擴展和高可用的Web應用的新領域
什麼是Spring Web Flow?
Spring Web Flow是Spring Framework中的web應用組件它提供了一種編寫有狀態和基於會話的web應用的簡便手段Spring Web Flow使得邏輯流程成為web應用中的一等公民它能讓你定義為自包含模塊以獨立於應用的其它部分來配置和重用它不依賴於框架從而能夠方便的與可選的web應用框架一同使用比如Spring MVCStruts或者JSF等
頁面流轉使用一種領域定義語言(DSL)來配置這個語言專門開發用來定義和組合頁面流轉目前的實現方式是XML和Java
Spring Web Flow引入了能滿足多種用戶案例和需求的幾種有狀態數據域requestflashflow和conversation這給你開發有狀態web應用提供了很大的靈活性和能力
這裡是 release中最有趣特性的快速概要
在一個地方而不是把邏輯分散在很多地方來定義應用任務的所有控制邏輯比如一個搜索流程
把簡單的流轉組合在一起來創建富控制模塊
使用自然和面向對象的線性編程模型而不是冗長的的if/else塊來定義嚴格的用戶導航規則
但流轉結束或過期時自動清除你在流轉執行中分配的內存
在使用你選擇的基礎web框架的Servlet環境中Deploy一個可執行的流轉
改變web框架(比如StrutsSpring MVCJSF及其它)而不用修改流轉定義
和環境一起改變而不需要修改你的流轉定義 比如從JUnit測試到Portlet
開發時在不重啟容器的情況下不斷完善你的應用導航規則
自動正確響應浏覽器按鈕(後退前進刷新)而不需要定制編程
在個受管理域中存儲任務數據requestflashflow和conversation等每個都有自己的獨特語義
脫離容器單獨測試流轉能在部署前確保應用控制邏輯能正常運作
使用Spring IDE 進行可視化編輯你的流轉導航邏輯圖
聽上去很有趣?到目前為止還僅僅是概念和理論但我們很快會看到這些都能在實踐中應用所以請多等一會
企業對擴展性和高可用性的需求
集群在企業應用開發中變得越來越重要開發人員經常會碰到這樣的問題
我們如何在一個節點上擴展來提高應用的可擴展性?
如果保證高可用性和消除單點故障如何確保我們能滿足客戶的SLAs(Service Level Agreement)?
為了支撐業務可預測的擴展性和高可用性是一個生產應用必須展示的運行特性一些企業需要超過%的正常運行時間另一些不要求這麼高但所有的應用都需要保證SLA規定的可運行性從預測的角度看開發一個系統在%和%級別是一樣困難的
集群一直以來都是難以解決的問題在Spring Web Flow和普通web應用上下文中這尤其意味著保證用戶狀態的高可用性和故障恢復能力是滿足性能且值得信賴的在一個節點出現故障(應用服務器或JVM崩潰)使用session粘滯(這是配置負載均衡最通用的首選方式)是一個開始但我們需要一個有效手段來無縫的將用戶狀態從一個節點遷移到另一個節點
當我們說集群時意味著什麼它和緩存有什麼區別?我們使用的集群定義是: 在多個JMV間共享應用狀態而緩存可以被定義為 讓應用狀態靠近執行上下文從這個角度看緩存是集群的一個子集
我們所認為的企業級Web/企業集群最小解決方案集至少需要包括
可擴展性
高可用性
failover
性能
對已有代碼的最小影響
簡單的部署和配置
可見運行時(監控)
讓我們關注一個能解決所有這些看上去無關的需求的解決方案通常解決一個問題有很多方案而且市場上也有很多宣稱能給web應用提供高可用性的產品Terracotta就提供了這樣一個解決方案
什麼是Terracotta for Spring?
Terracotta for Spring是基於Spring應用的運行時它為Spring應用提供了透明的高性能集群支持對應用代碼和部署及配置流程影響都很小它通過在應用下面的堆級別進行集群而不是直接集群應用
這讓開發者能夠開發與無狀態方式不同的單節點有狀態Spring應用這使得在需要擴展的應用開始設計時不考慮集群而在應用需要擴展或者要保證搞可用性和故障恢復時他們只需要在Terracotta配置文件中定義哪些Spring應用上下文中的beans需要進行集群Terracotta for Spring使得應用能夠被自動和透明的集群還保證在集群間的語義和單節點一樣
對於Spring Web Flow來說這實際上更簡單用戶為了獲得web應用的狀態和持續倉庫的集群能力 只需要在Terracotta配置文件中把特定的web應用聲明為啟用sessionsupport(詳細內容見下面的章節聲明式配置)
從宏觀上看Terracotta for Spring提供了
HTTP session狀態的集群保證Spring Web Flow中的用戶狀態和擴展倉庫或放入HTTP session的其它狀態的高可用性和故障恢復能力
Spring bean的集群Springbean的生命周期語義和域在集群間被保存它們在邏輯上相同的ApplicationContext中目前能被集群的bean類型是singleton和session scoped 用戶可以聲明式配置哪個application contexts中的哪個bean需要被集群
透明集群POJO不需要修改已有的代碼甚至不需要源代碼應用基於很少的聲明式XML 配置文件在載入期透明的生效Terracotta for Spring不需要實現Serializable Externalizable或其它接口的類能這樣實現的原因它並沒有使用序列化而只是將實際的差量和已經改變了的數據傳輸給當前需要的節點(lazily)
虛擬內存管理它也提供分布式垃圾收集和虛擬堆功能比如由於物理內存在需要時被換入換出它能在一個G RAM的機器上運行需要G堆的Web應用 這也意味著你不需要關心Spring Web Flow會話數據的大小是否超過了物理堆大小
堆層次集群
Terracotta for Spring使用aspectoriented技術來在類載入時適配應用在這個階段它擴展了應用以保證Java語義在集群間被正確的維護包括對象引用進程調用和垃圾收集等
我們在前面提到Terracotta並沒有使用serialization這意味著任何Spring Web Flow維護的會話都可以在集群間共享這也意味著Terracotta並沒有把會話狀態的全部對象圖發給所有節點而是把圖分解成純粹的數據並在網絡間傳輸實際的差量和改變數據的原始信息在其它節點上
因為有一個記錄節點間相互引用的中心調度器(見下文)它能以lazy的方式工作而只把改變傳送到引用了這些dirty數據的節點這需要使用局部引用如果負載均衡配置為使用session粘滯 就更有效率因為這意味著很多數據可能永遠不會脫離實際的session而不用復制到其它節點
這個架構是中心輻射的也就是有一個管理客戶端的中心調度器在這裡客戶端就是你配有Terracotta for Spring運行時的普通應用調度器不是單點失敗的但你可以配置一組備用調度器並在主調度器崩潰時選擇一個來接替你也可以獨立於客戶端對調度器進行集群擴展
構建一個高可用的有狀態web應用
這裡我們使用一個叫Sellitem的示例應用來推動討論並展示給大家
如何使用Spring Web Flow來構建一個有狀態基於會話的web應用
如何使用Terracotta for Spring來聲明式集群有狀態應用
Sellitem示例應用可以在Spring Web Flow的發布版本中找到(更多信息見文章末尾的Resources章節)
使用Spring Web Flow實現一個有狀態Web應用: Sellitem
Sellitem是展示結合了有條件轉移會話域流程執行轉向和延續性的示例應用用戶在幾個頁面間導航可以定義貨物的價格可以銷售的貨物數量折扣比率送貨詳情(如果需要)和最後查看所有信息
我們不會通讀應用的所有源碼而是主要介紹一些關鍵概念如怎麼配置Spring Web Flow輸出的不同標准服務(Bean)和怎麼定義頁面流轉(使用針對頁面流轉的Spring Web FlowDSL的XML版本)
在Spring MVC中配置DispatcherServlet
應用的入口是一個標准的Spring MVC DispatcherServlet它在webxml中注冊並在web application context中映射到
sellitem
orgspringframeworkwebservletDispatcherServlet
contextConfigLocation
/WEBINF/sellitemservletconfigxml
/WEBINF/sellitemwebflowconfigxml
sellitem
DispatcherServlet配置在Spring的配置文件sellitemservletconfigxml和sellitemwebflowconfigxml中 sellitemservletconfigxml中有一個映射到/的控制器它將所有該URL的請求轉發到Spring Web Flow系統(它的入口是一個流程執行器)
配置flow executor和flow registry beans
Spring flowExecutor bean配置使用一個flowRegistry bean來執行/WEBINF/flows/目錄中的基於XML的流轉定義
定義頁面流轉
剩余的邏輯在我們已經注冊的flowRegistry bean的流轉定義中(參照前面的配置flow executor和flow registry beans章節)
在深入流轉實現細節前我們先看一下頁面流轉的狀態圖(如下圖)
從上面我們可以看到流轉在結束前經過了幾個步驟在決定銷售是否需要送貨時有一個決策狀態
一個很好的針對上面導航規則的初始流轉定義實現如下
xmlns:xsi=instance
xsi:schemaLocation=
webflowxsd>
我們從上面的定義可以看到實際狀態與狀態圖中的狀態對應狀態轉換與圖中的箭頭對應sale bean是流轉開始時分配的流轉變量實例它持有了Sale相關的屬性
上面的定義展示了所有的導航邏輯但還沒有實現任何應用行為特別是在用戶提交時更新Sale Bean的邏輯還沒有實現另外後台的sale處理邏輯還沒有定義
實現了所有必需行為的完整Spring Web Flow定義如下
xmlns:xsi=instance
xsi:schemaLocation=
webflowxsd
在定義導航邏輯之外也定義了適時調用恰當應用行為的action這包括處理用戶提交事件和調用後台處理器來處理sale的邏輯
Form綁定和驗證
當進入展示表單的視圖狀態時流轉調用一個FormAction command bean來進行表單的裝配和提交邏輯在提交時FormAction把用戶的請求參數綁定到相應的sale屬性上並同時驗證它們
更多信息
Spring Web Flow全部的代碼文檔和個示例應用(包括sellitem)都可以在Spring網站上找到
集群Sellitem應用
現在我們已經看過了如何使用Spring Web Flow來實現一個有狀態web應用接下來讓我們更高興的看如何給我們的示例應用啟用高可用性和故障恢復如何使用Terracotta for Spring進行集群來提供透明容錯性和在節點間共享狀態
聽上去很難? 你會發現這實際上很簡單
聲明式配置
Sellitem示例應用使用一個Sale類的實例來保存當前銷售的會話數據同樣Spring Web Flow executor repository也使用HTTP session 來保存所有的會話數據
要使用Terracotta for Spring我們需要確保為給定的web應用啟用了HTTP session集群包括所有可能被保存在 HTTP session中(或者能被保存在HTTP session中的實例引用)的類以便於檢測這裡是Terracotta for Spring的tcconfigxml配置文件的一個例子
name=swfsellitem>
true
orgspringframeworkwebflowsamplessellitemSale
這裡我們為swfsellitem WAR文件啟用了HTTP session集群並配置了Sale類
就是這樣我們已經做了很多了
啟用Terracotta
我們唯一需要做的就是在應用中啟用Terracotta for Spring運行時這可以通過修改Tomcat web服務器的啟動腳本並在腳本最前面加入下面的環境變量完成
set JAVA_OPTS=Xbootclasspath/p:%DSO_BOOT_JAR%
set JAVA_OPTS=%JAVA_OPTS% Dtcinstallroot=%TC_INSTALL_DIR%
set JAVA_OPTS=%JAVA_OPTS% nfig=%LOCAL_DIR%\tcconfigxml
這裡面
DSO_BOOT_JAR環境變量指向jar的根目錄(能在Terracotta for Spring安裝的根目錄的common/lib/dsoboot下找到)
TC_INSTALL_DIR環境變量指向Terracotta for Spring安裝的根目錄
LOCAL_DIR指向包含tcconfigxml的目錄
Sellitem應用預配置了Terracotta for Spring集群的代碼可以在下面的Resources章節找到也包括了開箱即用的Tomcat集群配置
注解Spring應用上下文中的集群bean可以在服務(bean)級別配置並依賴於Terracotta for Spring的 autoinclude檢測機制例如大多數情況下我們不需要關心引入哪個類而只需要在tcconfigxml文件中定義希望集群的bean的名稱
總結
Spring Web Flow 給包括文章中看到的這種簡單應用到有很多頁面流轉的大型企業應用都提供了構建基於會話的有狀態應用的有力手段 Terracotta for Spring給你的Spring Web Flow提供了高可用性
簡而言之 Terracotta for Spring提供了
給基於Spring Web Flow的應用包括普通Spring的應用提供容錯性
不需要實現javalangSerializable在多個節點間分布的應用中透明共享狀態
在多個分布式節點進行資源調用
在多個分布式節點間保持了Passbyreference語義
聲明式配置基本上不用修改現有代碼(除了以前是無狀態Spring應用現在需要變成有狀態)
Spring Web Flow和Terracotta for Spring結合在一起給你提供了構建有狀態基於會話可擴展和高可用性web應用的新方式
From:http://tw.wingwit.com/Article/program/Java/ky/201311/28016.html