天天看點

SpringBatch系列文章-領域模型語言

文章目錄

    • 批處理的域語言
    • Job作業
      • JobInstance
      • JobParameters作業參數
      • JobExecution工作執行
    • Step步驟
      • StepExecution
    • JobRepository
    • JobLauncher作業啟動器
      • ItemReader單元讀
      • ItemWriter單元寫
      • ItemProcessor單元處理

原文位址: https://docs.spring.io/spring-batch/docs/4.2.x/reference/html/domain.html#domainLanguageOfBatch,本翻譯使用網頁翻譯功能,隻是為了友善看。

原網站支援XML格式和JAVA格式,主要展現在代碼那塊,這裡主要是Java版本。

批處理的域語言

對于任何經驗豐富的批處理設計師而言,Spring Batch中使用的批處理的總體概念應該是熟悉且舒适的。有“工作”和“步驟”,以及開發人員提供的處理單元,稱為ItemReader和ItemWriter。但是,由于存在Spring模式,操作,模闆,回調和慣用語,是以有以下機會:

  • 遵守關注點明顯分開的情況得到了顯着改善。
  • 清楚地描述了作為接口提供的體系結構層和服務。
  • 簡單和預設的實作,可以快速采用和開箱即用。
  • 顯着增強的可擴充性。

下圖是已經使用了數十年的批處理參考體系結構的簡化版本。它概述了組成批處理領域語言的元件。該體系結構架構是一個藍圖,已經在最後幾代平台(COBOL / Mainframe,C / Unix,現在是Java /任何地方)上數十年的實作中得到了證明。JCL和COBOL開發人員可能會像C,C#和Java開發人員一樣熟悉這些概念。Spring Batch提供了層,元件和技術服務的實體實作,這些層,元件和技術服務通常在健壯,可維護的系統中找到,這些系統用于解決從簡單到複雜的批處理應用程式的建立,其基礎結構和擴充可以滿足非常複雜的處理需求。

SpringBatch系列文章-領域模型語言

圖1.批處理原型

上圖突出顯示了構成Spring Batch領域語言的關鍵概念。作業有一個到多個步驟,每個步驟都隻有一個ItemReader,一個ItemProcessor和一個步驟ItemWriter。需要啟動一個作業(帶有 JobLauncher),并且需要存儲有關目前正在運作的程序的中繼資料(位于中 JobRepository)。

Job作業

本節描述與批處理作業的概念有關的構造型。

A Job是封裝整個批處理過程的實體

。與其他Spring項目一樣,a Job與XML配置檔案或基于Java的配置連接配接在一起。該配置可以被稱為“作業配置”。但是,

Job這隻是整個層次結構的頂部

,如下圖所示:

SpringBatch系列文章-領域模型語言

圖2.作業層次結構

在Spring Batch中,

a Job隻是Step執行個體的容器

。它組合了邏輯上屬于流程的多個步驟,并允許配置所有步驟全局的屬性,例如可重新啟動性。作業配置包含:

  • 作業的簡單名稱。
  • Step執行個體的定義和順序。
  • 作業是否可重新啟動。

Spring Batch以SimpleJob類的形式提供Job接口的預設簡單實作,該實作在之上建立了一些标準功能Job。使用基于Java的配置時,可使用一組建構器來執行個體化a Job,如以下示例所示:

@Bean
public Job footballJob() {
    return this.jobBuilderFactory.get("footballJob")
                     .start(playerLoad())
                     .next(gameLoad())
                     .next(playerSummarization())
                     .end()
                     .build();
}
           

XML格式配置:

<job id="footballJob">
    <step id="playerload" next="gameLoad"/>
    <step id="gameLoad" next="playerSummarization"/>
    <step id="playerSummarization"/>
</job>
           

JobInstance

A JobInstance是指邏輯作業運作的概念。考慮一個應該在一天結束時運作一次的批處理作業,例如Job上圖中的“ EndOfDay” 。有一個“ EndOfDay”作業,但是Job必須單獨跟蹤每個運作。對于這項工作,JobInstance每天隻有一個邏輯。例如,有1月1日運作,1月2日運作,依此類推。如果1月1日運作第一次失敗并在第二天再次運作,則仍是1月1日運作。(通常,這也與它正在處理的資料相對應,這意味着1月1日運作處理1月1日的資料)。是以,每個JobInstance執行可以有多個執行(JobExecution本章稍後将詳細讨論),并且

隻有一個JobInstance可以在給定時間運作Job與特定内容和辨別相對應的内容JobParameters

a的定義JobInstance絕對與要加載的資料無關。完全取決于ItemReader實作來确定如何加載資料。例如,在EndOfDay方案中,資料上可能有一列訓示該資料所屬的“生效日期”或“計劃日期”。是以,1月1日的運作将僅加載第1次的資料,而1月2日的運作将僅使用第2次的資料。由于此确定可能是一項業務決策,是以由 ItemReader決定。但是,使用同一個參數可JobInstance确定是否使用ExecutionContext先前執行中的“狀态”(即本章稍後讨論的)。使用新的JobInstance 表示“從頭開始”,使用現有執行個體通常意味着“從上次中斷的地方開始”。

JobParameters作業參數

在讨論JobInstance了它與Job的不同之處之後,自然要問的問題是:“一個人JobInstance與另一個人有什麼差別?” 答案是: JobParameters。一個JobParameters對象擁有一組用于啟動批處理作業的參數。它們可以在運作期間用于辨別甚至用作參考資料,如下圖所示:

工作參數

SpringBatch系列文章-領域模型語言

圖3.作業參數

在前面的示例中,有兩個執行個體,一個執行個體是1月1日,另一個執行個體是1月2日,實際上隻有一個執行個體,Job但是它有兩個JobParameter對象:一個執行個體是用job參數01-01-2017啟動的,另一個執行個體是該參數以01-02-2017開頭。是以,合同可以定義為:JobInstance= Job +辨別JobParameters。這使開發人員可以有效地控制a JobInstance的定義方式,因為他們可以控制傳入的參數。

并非所有作業參數都需要有助于識别 JobInstance。預設情況下,它們會這樣做。但是,該架構還允許送出Job帶有對a的身份無貢獻的參數的a JobInstance。

JobExecution工作執行

A JobExecution是指一次嘗試運作Job的技術概念。執行可能以失敗或成功結束,但是JobInstance與給定執行相對應的執行除非成功完成,否則不視為完成。以Job前面描述的EndOfDay 為例,考慮JobInstance01-01-2017的首次運作失敗。如果使用與第一次運作(01-01-2017)相同的辨別作業參數再次運作,JobExecution則會建立一個新的。但是,仍然隻有一個JobInstance。

A Job定義什麼是作業及其執行方式,而a JobInstance是将執行組合在一起的純粹的組織對象,主要用于啟用正确的重新啟動語義。JobExecution但是,A 是運作期間實際發生情況的主要存儲機制,它包含許多必須控制和保留的屬性,如下表所示:

表1. JobExecution屬性

屬性 定義
Status 甲BatchStatus對象,訓示執行的狀态。在運作時,它是 BatchStatus#STARTED。如果失敗,則為BatchStatus#FAILED。如果成功完成,那就是BatchStatus#COMPLETED
startTime 一個java.util.Date代表當執行開始時的目前系統時間。如果作業尚未開始,則此字段為空。
endTime 一個java.util.Date代表當執行完成後,無論它是否是成功的目前系統時間。如果作業尚未完成,則該字段為空。
exitStatus 的ExitStatus,說明運作的結果。這是最重要的,因為它包含傳回給調用者的退出代碼。有關更多詳細資訊,請參見第5章。如果作業尚未完成,則該字段為空。
createTime 甲java.util.Date表示當目前系統時間JobExecution最早持續。作業可能尚未啟動(是以沒有啟動時間),但是它始終具有createTime,這是管理作業級别的架構所需的ExecutionContexts。
最近更新時間 java.util.Date代表上一次JobExecution持續存在的A。如果作業尚未開始,則此字段為空。
executionContext “屬性包”包含兩次執行之間需要保留的所有使用者資料。
failureExceptions 執行Job。時遇到的異常清單。如果在失敗時遇到多個異常,這些功能将非常有用Job。

這些屬性很重要,因為它們可以持久儲存,并且可以用來完全确定執行狀态。例如,如果01-01的EndOfDay作業在9:00 PM執行并在9:30失敗,則在批進行中繼資料表中進行以下輸入:

後面設計表的直接看官網即可,有時間再慢慢整理格式。

表2. BATCH_JOB_INSTANCE

JOB_INST_ID JOB_NAME
1個 EndOfDayJob

表3. BATCH_JOB_EXECUTION_PARAMS

為了清楚和格式化,列名可能已被縮寫或删除。

現在工作失敗了,假設确定問題已花費了一整夜,是以“批處理視窗”現在關閉了。進一步假設該視窗在9:00 PM開始,該作業将在01-01再次開始,從停止的地方開始,并在9:30成功完成。因為現在是第二天,是以也必須運作01-02作業,此作業随後才在9:31開始,并在正常的一小時時間内在10:30完成。并不需要一個接一個JobInstance地啟動,除非這兩個作業有可能嘗試通路相同的資料,進而導緻在資料庫級别鎖定的問題。完全由排程程式确定何時Job應運作a。由于它們是分開的JobInstances,Spring Batch不會嘗試阻止它們同時運作。(嘗試JobInstance在另一個已經運作的情況下運作相同的結果 JobExecutionAlreadyRunningException會抛出該錯誤)。現在,JobInstance和JobParameters表中都應該有一個額外的條目,并且表中應該有兩個額外的條目, JobExecution如下表所示:

表5. BATCH_JOB_INSTANCE

表6. BATCH_JOB_EXECUTION_PARAMS

表7. BATCH_JOB_EXECUTION

為了清楚和格式化,列名可能已被縮寫或删除。

Step步驟

A Step是一個域對象,封裝了批處理作業的一個獨立的順序階段。是以,每個作業完全由一個或多個步驟組成。一個Step包含了所有的定義和控制實際的批量處理所需的資訊。這是一個模糊的描述,因為任何給定的内容Step都由開發人員自行決定編寫Job。A Step可以根據開發人員的要求簡單或複雜。一個簡單的方法Step可能會将檔案中的資料加載到資料庫中,幾乎不需要代碼(取決于所使用的實作)。較複雜的 Step業務規則可能包含複雜的業務規則,這些規則将在處理過程中應用。與a一樣Job,a Step有一個個體StepExecution與unique相關聯 JobExecution,如下圖所示:

圖2.1:帶步驟的作業層次結構

SpringBatch系列文章-領域模型語言

圖4.帶有步驟的作業層次結構

StepExecution

A StepExecution代表執行的單次嘗試Step。StepExecution 每次Step運作a都會建立一個新内容,類似于JobExecution。但是,如果某個步驟由于執行失敗而無法執行,則不會繼續執行。A StepExecution僅在其Step實際啟動時建立。

Step執行由StepExecution類的對象表示。每次執行均包含對其相應步驟和JobExecution與事務相關的資料的引用,例如送出和復原計數以及開始和結束時間。此外,每個步驟執行都包含一個ExecutionContext,其中包含開發人員在批處理運作中需要保留的所有資料,例如重新啟動所需的統計資訊或狀态資訊。下表列出了的屬性StepExecution:

表8. StepExecution屬性

ExecutionContext執行上下文

An ExecutionContext表示鍵/值對的集合,這些鍵/值對由架構進行持久化和控制,以便允許開發人員存儲一個範圍為StepExecution對象或JobExecution對象的持久狀态。對于熟悉Quartz的人來說,它與JobDataMap非常相似。最佳用法示例是促進重新啟動。以平面檔案輸入為例,在處理各個行時,架構會定期保留ExecutionContext送出點**

(批注:通過對footballl例子的運作,批量送出一次記錄一次,和chunk中commit-interval有關,大緻是總資料量除以一次送出的數量)

**。這樣做可以ItemReader在運作期間發生緻命錯誤或斷電的情況下存儲其狀态。所需要做的就是将目前讀取的行數放入上下文中,如下面的示例所示,架構将完成其餘工作:

executionContext.putLong(getKey(LINES_READ_COUNT), reader.getPosition());

以JobStereotypes部分的EndOfDay示例為例,假設有一個步驟“ loadData”将檔案加載到資料庫中。第一次失敗運作後,中繼資料表将類似于以下示例:

看官網表格,這裡不複制了。

在上述情況下,Step運作了30分鐘并處理了40321個“件”,在這種情況下,這代表了檔案中的行。此值會在架構每次送出之前更新,并且可以包含與中的條目相對應的多行 ExecutionContext。在送出之前得到通知需要各種 StepListener實作之一(或ItemStream),本指南後面将對此進行詳細讨論。與前面的示例一樣,假定Job于第二天重新啟動。重新啟動後,ExecutionContext将從資料庫中重新建構上次運作的值。當ItemReader被打開時,它可以檢查以檢視它是否具有在上下文任何存儲的狀态,并從那裡初始化自身,如圖以下示例:

if (executionContext.containsKey(getKey(LINES_READ_COUNT))) {
    log.debug("Initializing for restart. Restart data is: " + executionContext);

    long lineCount = executionContext.getLong(getKey(LINES_READ_COUNT));

    LineReader reader = getReader();

    Object record = "";
    while (reader.getPosition() < lineCount && record != null) {
        record = readLine();
    }
}
           

在這種情況下,運作上述代碼後,目前行為40322,進而允許Step 再次從中斷處開始。該ExecutionContext也可用于那些需要被保留的關于運作本身的統計資料。例如,如果平面檔案包含跨多行存在的處理訂單,則可能有必要存儲已處理的訂單數量(與讀取的行數有很大不同),以便可以通過以下方式發送電子郵件:結束Step于正文中處理的訂單總數。架構負責為開發人員存儲此内容,以便将其正确地界定為個人JobInstance。很難知道是否存在ExecutionContext是否應該使用。例如,使用上面的’EndOfDay’示例,當01-01運作第二次再次開始時,架構會識别出它是相同的JobInstance并且是單獨的Step,将其ExecutionContext拉出資料庫,并将其移交給資料庫(作為自身的一部分 StepExecution)Step。相反,對于01-02運作,架構識别出它是一個不同的執行個體,是以必須将空上下文傳遞給 Step。架構為開發人員做出了許多類型的确定,以確定在正确的時間将狀态提供給開發人員。同樣重要的是要注意,在任何給定時間,ExecutionContext每個人都隻存在一個StepExecution。客戶ExecutionContext應該小心,因為這會建立一個共享的鍵空間。是以,在輸入值時應注意確定沒有資料被覆寫。但是,Step存儲絕對不會在上下文中存儲任何資料,是以沒有辦法對架構産生不利影響。

同樣重要的是要注意,至少有一個ExecutionContext每 JobExecution一個用于每一個StepExecution。例如,考慮以下代碼片段:

ExecutionContext ecStep = stepExecution.getExecutionContext();

ExecutionContext ecJob = jobExecution.getExecutionContext();

//ecStep does not equal ecJob

如評論中所述,ecStep不等于ecJob。他們是兩個不同的人 ExecutionContexts。範圍為的Step一個儲存在中的每個送出點 Step,而範圍為的一個儲存在每次Step執行之間。

JobRepository

JobRepository是上述所有構造型的持久性機制。它提供了CRUD操作JobLauncher,Job以及Step實作。當 Job第一次啟動,一個JobExecution被從庫中獲得,并且,執行的過程中,StepExecution和JobExecution實施方式是通過将它們傳遞到存儲庫持續。

使用Java配置時,@EnableBatchProcessing注釋提供 JobRepository作為開箱即用自動配置的元件之一。

批處理名稱空間為JobRepository使用标簽配置執行個體 提供了支援,如以下示例所示:

JobLauncher作業啟動器

JobLauncher表示一個用于啟動Job帶有給定集合的 的簡單界面JobParameters,如以下示例所示:

public interface JobLauncher {

public JobExecution run(Job job, JobParameters jobParameters)
            throws JobExecutionAlreadyRunningException, JobRestartException,
                   JobInstanceAlreadyCompleteException, JobParametersInvalidException;
}
           

預計實作獲得有效JobExecution距離 JobRepository和執行Job。

ItemReader單元讀

ItemReader是一種抽象,表示一次檢索一項的輸入Step。當ItemReader用盡了它可以提供的物品時,它通過傳回來表明這一點null。有關ItemReader接口及其各種實作的更多詳細資訊,請參見 讀者和作家。

ItemWriter單元寫

ItemWriter是一個抽象,一次代表一個Step,一批或大塊項目的輸出。通常,一個ItemWriter不知道下一步應該接收的輸入,并且隻知道目前調用中傳遞的項目。有關ItemWriter接口及其各種實作的更多詳細資訊,請參見 讀者和作家。

ItemProcessor單元處理

ItemProcessor是表示項目的業務處理的抽象。在ItemReader讀取一項并将其ItemWriter寫入的同時,它們 ItemProcessor提供了一個通路點來轉換或應用其他業務處理。如果在處理項目時确定該項目無效,則傳回 null訓示不應寫出該項目。有關該ItemProcessor接口的更多詳細資訊,請 參見 讀者和作家。

版本4.2.4.RELEASE 最後更新時間2020-06-11 07:52:24 UTC

繼續閱讀