Spring Batch 2.0新功能概述

工程 | Dave Syer | 2008年10月21日 | ...

在本文中,我們概述了Spring Batch 2.0的主要主題,並重點介紹了與1.x版本的變化。新版本的開發工作正在順利進行,上週釋出了M2版本,並且我們獲得了大量關注,因此現在似乎是提供一些指標的好時機。

Spring Batch 2.0 主題

新版本的四個主要主題是

  • Java 5和Spring 3.0
  • 非順序執行
  • 可伸縮性
  • 配置:註解和XML名稱空間
因此,我們將分別介紹每個領域,描述它們意味著什麼以及這些變化對Spring Batch現有使用者的影響。下面有更多關於已實現功能的詳細資訊,這些功能主要集中在第一類,並在其他領域提供了一些支援性功能。

Spring Batch 2.0.0.M2 在專案物理佈局方面沒有變化(下載地址不變,Java 包的基本佈局也未變)。我們沒有移除任何功能,但我們藉此機會重新設計了一些 API,並且對於從 1.x 更新專案的使用者來說,有一些小的改動。Spring Batch 尚不成熟,並且我們正在新增一些相當大的功能,因此我們決定進行主版本升級是一個進行一些清理的好機會。我們預計升級不會有任何困難,如果您是現有使用者,本文將幫助您瞭解這些變化。

Java 5和Spring 3.0

正如您可能知道的,Spring 3.0 將是 Spring 的第一個主要版本,它將完全支援 Java 5(我將留給 Juergen 和 Arjen 詳細闡述)。現在 Sun 已經給 JDK 1.4 打上了“服務生命終結”的標籤,這似乎是恰當的,而且 Spring 3.0 中有一些很棒的新功能是我們想要利用的。

型別安全

Spring Batch 2.0.0.M1 版本的大部分工作都集中在將現有程式碼轉換為 Java 5,儘可能地利用泛型和引數化型別。這為框架使用者提供了更好的程式設計體驗,允許在編譯時進行型別安全檢查,並最終降低了使用 Spring Batch 的專案的維護成本。例如,在ItemReader(Spring Batch 中的一個核心介面和使用者擴充套件點)中,我們現在有了一個型別安全的read方法

public interface ItemReader<S> {
    S read();
}

方法。需要注意的另一點是,舊的(1.x)框架回調mark()還是reset()Step實現內部處理。

面向塊的處理

類似的改動,以及一個稍顯激進的改動,也出現在配套的ItemWriter介面中,該介面用於框架寫入資料。


public interface ItemWriter<T> {
    void write(List<? extends T> items);
}

舊的框架回調,如flush()還是clear()write()方法有了新的簽名。這裡的重點是,我們已經在框架內部轉向了面向塊的處理範例。對於批處理框架來說,這實際上比舊的專案導向方法更自然,因為出於效能原因,我們經常需要緩衝和重新整理,而舊的介面使得使用者在這方面感到不便。現在您可以在write()方法實現。

Step Factory Bean 更改

面向塊的處理方法的一個副作用是步驟工廠 Bean 實現的更改。舊的SkipLimitStepFactoryBean已被重新命名為FaultTolerantStepFactoryBean,並且在大多數常見用例中,它仍然可以作為舊工廠 Bean 的替代品。預設情況下,它建立的步驟實現會在回滾時緩衝輸入項,以便新的ItemReader還是ItemWriter介面能夠與非事務性輸入源(如檔案)正確配合使用。對於回滾後會重新呈現項的輸入源,客戶端必須在工廠 Bean 中設定一個標誌(在 M2 版本中,該標誌名為isReaderTransactional)——JmsItemReader是框架中唯一相關的讀取器,並且很少有專案使用它,所以這不是一個大的改動。

業務處理

一個相關的で新功能是ItemProcessor:

public interface ItemProcessor<S,T> {
    T process(S item);
}

的出現。在 1.x 中,型別為S的輸入項和型別為T的輸出項之間的轉換必須隱藏在其他參與者(通常是ItemWriter相同的重要性級別。1.x 的使用者可能會在這裡識別出舊的ItemReader還是ItemWriter)中。現在我們已經將這個關注點泛化,並將其置於與它的同級介面ItemTransformer介面的痕跡,該介面現在已被移除。

更實用的 Tasklet 介面

很多人在檢視 Spring Batch 1.x 時都會問:“如果我的業務邏輯不是讀取和寫入怎麼辦?”為了更令人滿意地回答這個問題,我們修改了Tasklet介面。在 Spring Batch 1.x 中,它相當平淡無奇,實際上不過是一個Callable。但在 2.0 版本中,我們賦予了它更多的靈活性,並將其更好地整合到框架的主流中(例如,核心的面向塊的步驟實現現在被實現為一個TaskletTasklet


public interface Tasklet {
    ExitStatus execute(StepContribution contribution, 
        AttributeAccessor attributes);
}

這個想法是,tasklet 現在可以為封閉的步驟貢獻更多,這使得它成為實現業務邏輯的一個更靈活的平臺。雖然StepContribution已經是 1.x API 的一部分,但它並沒有被廣泛公開。它的作用是收集當前StepExecution的更新,而無需程式設計師擔心在另一個執行緒中併發修改。這也告訴我們,Taskletexecute()方法將被重複呼叫(而不是像 1.x 框架中那樣每個步驟只調用一次),因此它可以用於執行更廣泛的業務處理任務。AttributeAccessor

是一個塊作用域的鍵值對集合。tasklet 可以使用它來儲存將在回滾時保留的中間結果。

Late Binding of Job and Step Attributes到目前為止(截至 M2),我們還未能利用任何新的 Spring 3.0 功能,因為還沒有 Spring 3.0 的釋出版本。但從下一個里程碑(M3)開始,我們將使用新的 Spring EL(表示式語言)功能來實現對還是JobParametersStepExecutionResourceProxy用於繫結到檔名作為作業的輸入引數。Spring Batch 2.0 中一個更通用的解決方案是透過在適當的 Spring 作用域中定義它們來允許這些步驟屬性繫結到任意元件,例如:

<bean id="step1" parent="simpleStep">
  <property name="itemReader">
    <bean class="org.springframework.batch.item.file.FlatFileItemReader" scope="step">
        <property value="#{jobParameters[inputFile]}" />
        ...
    </bean>
  </property>
  ...
</bean>

Item reader 需要繫結到一個只在執行時可用的檔名。為此,我們將其宣告為 scope="step",並使用 Spring EL 繫結模式#{...}來繫結到 Job 引數。相同的模式也將適用於步驟和 Job 級別的執行上下文屬性。

StepScope在 nightly snapshots 中可用,但我們仍在使用 Spring 2.5.5,因此 EL 繫結尚未生效。Step 作用域的 Bean 也是解決舊 Spring Batch 如何保持步驟執行緒安全問題的好方法。如果一個步驟依賴於有狀態元件,如FlatFileItemReader,那麼它只需要將該元件宣告為 scope="step",框架就會為其建立一個惰性初始化代理,並且它將在每個步驟執行時按需建立一次。建立一個新的ApplicationContextJobExecution

來實現與 Job 的執行緒安全仍然是可行的,這是 1.x 中避免 Job 之間執行緒衝突的最佳實踐。但現在 Step 作用域提供了另一種選擇,而且對於大多數 Spring 使用者來說,這種選擇可能更容易掌握。

非順序執行

  • 在 1.x 中,Job 的模型始終是步驟的線性序列,如果一個步驟失敗,則 Job 失敗。雖然許多 Job 仍然符合這種模式,並且它並未消失,但在 2.0 版本中,我們透過引入一些新功能來解除這一限制。這些功能計劃在 M3 版本中釋出,因此實現細節可能會發生變化,但目的是支援以下三個功能:條件執行:基於上一個步驟的ExitStatus
  • 分支到不同的步驟。這包括能夠根據 FAILED 狀態進行分支,這意味著步驟失敗不再是 Job 的致命錯誤。
  • 暫停執行並等待明確的繼續指令。這在存在強制手動干預來檢查業務關鍵資料有效性的業務規則的情況下非常有用。
多個步驟的並行執行。當步驟獨立時,使用者可以指定哪些分支可以並行執行。截至本文撰寫時,Nightly snapshots 包含一個ConditionalJob

可伸縮性

Spring Batch 1.x 一直被設計為一個可能的單 VM、多執行緒模型,但我們向其中添加了許多支援多程序並行執行的功能。許多專案已成功實現可擴充套件的解決方案,依靠 Spring Batch 的服務質量功能來確保處理僅在正確的順序下發生。在 2.0 版本中,我們將更明確地公開這些功能。可擴充套件性有兩種方法,我們將同時支援這兩種:遠端分塊和分割槽。

遠端分塊

遠端分塊是一種將步驟的工作進行分割的技術,而無需顯式瞭解資料的結構。任何輸入源都可以透過在一個程序中讀取(如 1.x 中的正常情況)並將這些項作為一個塊傳送到遠端工作程序來動態分割。遠端程序實現偵聽器模式,響應請求,處理資料併發送非同步回覆。請求和回覆的傳輸必須是持久的,具有保證的交付和單個消費者,並且這些功能可以透過任何 JMS 實現輕鬆獲得。但 Spring Batch 在 Spring Integration 之上構建遠端分塊功能,因此它實際上與訊息中介軟體的實際實現無關。

分割槽

分割槽是另一種方法,相比之下,它依賴於對輸入資料結構的某些瞭解,例如主鍵範圍或要處理的檔名。這種模型的優點是,每個分割槽元素的處理器可以像它們是普通 Spring Batch Job 中的單個步驟一樣行事。它們不必實現任何特殊的新模式,這使得它們易於配置和測試。原則上,分割槽比遠端分塊更具可擴充套件性,因為它不存在從一個地方讀取所有輸入資料而產生的序列化瓶頸。

在 Spring Batch 2.0 中,分割槽由兩個介面支援:PartitionHandlerStepExecutionSplitterPartitionHandler 知道執行框架——它必須將請求傳輸到遠端步驟,並使用任何可用的網格或遠端技術收集結果。 PartitionHandler 是一個 SPI,我們透過 TaskExecutor 提供了一個開箱即用的本地執行實現。這對於我們看到的一些需要對大量 IO 密集型任務進行並行處理的專案來說將是立即有用的,因為在這些情況下,遠端執行只會使部署複雜化,並且不一定能在效能上提供太多幫助。其他實現將特定於執行框架,例如,某個網格提供商(IBM、Oracle、Terracotta、Appistry 等),並且我們不希望在 Spring Batch 中對其中任何一個相對於其他供應商有偏好。

SpringSource 計劃推出一款企業級批處理產品,該產品將提供完整的執行時解決方案,用於分割槽和遠端分塊,以及管理和排程方面的需求。敬請關注,瞭解該產品的更多詳細資訊,或參加 Spring One Americas

配置:註解和XML名稱空間

使用註解實現批處理邏輯的想法是類比 Spring @MVC。其最終效果是,您不必實現並可能註冊一堆介面(Reader、Writer、Processor、Listeners 等),只需註解一個 POJO 並將其插入到步驟中。有對應於各種介面的方法級別註解,以及對應於 Job、Step 和 Chunk 級別屬性的引數級別註解和工廠方法(有點像@ModelParameter還是@RequestParameter

Spring Batch 的 XML 名稱空間使得常見事項的配置更加容易。例如,我們上面提到的截至本文撰寫時,Nightly snapshots 包含一個ConditionalJob


<job>
  <step name="gamesLoad" next="playerLoad"/>
  <step name="playerLoad">
    <next on="*" to="summarize"/>
    <next on="FAILED" to="compensate"/>
  </step>
  <step name="compensate"/>
  <step name="summarize"/>
</job>

第一個步驟(“gamesLoad”)緊接著是“playerLoad”,但如果失敗,我們可以轉到替代步驟(“compensate”),而不是正常地用“summarize”步驟完成 Job。XML 中<step元素的 name= 屬性是一個 Bean 引用,所以Step的實現定義在別處(可能透過註解)。

資料庫 Schema 更改

在元資料 Schema 中有一些整理工作和對資料模型的擴充套件。我們將為從 1.x 遷移到 2.0 的任何人提供更新指令碼,因此它們不應該引起任何問題,並且肯定會使導航和與元資料互動更加容易。對於剛接觸 Spring Batch 的您來說,該框架的一些關鍵優勢是服務質量功能,如可重啟動性和冪等性(只處理一次業務資料)。我們透過關係資料庫中的共享狀態(在大多數用例中)來實現這些功能,並且此資料庫中的資料模型的定義在 2.0 版本中發生了一些變化。

主要更改與JobParametersExecutionContextStepExecution的儲存有關,它以前集中在一個表中,即使上下文可以與StepExecution相關聯。新模型將更受 DBA 的歡迎,因為它使 DDL 中的關係更加透明。我們還開始將上下文值儲存在 JSON 中,以便於人類使用者閱讀和跟蹤(單個實體的上下文都儲存在一個表的一行中,而不是多行)。

我們還添加了更多用於計數和核算已執行和已跳過的項的統計資訊,將每個階段的讀取、處理和寫入的總項數分開。對於不將執行分為讀取、處理、寫入的步驟(或 tasklet),這比需要的要多,但對於大多數用例來說,它比只儲存整體項計數更合適。

結束語

希望本文能激發您對 Spring Batch 2.0 的興趣,並且您有時間下載一個快照或里程碑版本並嘗試一下。我們從社群獲得了非常好的反饋,沒有您的幫助和支援,該產品就不會像現在這樣出色。如果我遺漏了您感興趣的內容,或者沒有提供足夠的細節,我表示歉意,但我需要將其壓縮成一個合理的部落格大小的格式。如果有人感興趣,我可以寫更多內容——儘管問。

如果您想了解更多資訊,有機會在今年的Spring One Americas上聽取團隊關於 Spring Batch 2.0 和所有其他 SpringSource 活動的介紹。Lucas Ward 將在一個會話中展示 Spring Batch 2.0 的功能,我將更詳細地介紹可擴充套件性功能。您還可以檢視論壇上的討論,或者在這裡訪問主頁 這裡

獲取 Spring 新聞通訊

透過 Spring 新聞通訊保持聯絡

訂閱

領先一步

VMware 提供培訓和認證,助您加速進步。

瞭解更多

獲得支援

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位制檔案,只需一份簡單的訂閱。

瞭解更多

即將舉行的活動

檢視 Spring 社群所有即將舉行的活動。

檢視所有