此系列博客皆為學習Spring Batch時的一些筆記;
Spring Batch的架構
一個Batch Job是指一系列有序的Step的集合,它們作為預定義流程的一部分而被執行;
Step代表一個自定義的工作單元,它是Job的主要構件塊;每一個Step由三部分組成:ItemReader、ItemProcessor、ItemWriter;這三個部分將執行在每一條被處理的記錄上,ItemReader讀取每一條記錄,然后傳遞給ItemProcessor處理,最后交給ItemWriter做持久化;ItemProcessor不是必須的,一個Step可以僅僅包含ItemReader和ItemWriter;如果你不需要去讀寫任何數據,你可以僅僅在一個Step中包含一個Tasklet(等價於ItemProcessor);
組成Spring Batch的一些相關的類和接口:
- org.springframework.batch.core.Job:表示一個Job,同時也提供了執行Job的能力;
- org.springframework.batch.core.Step:表示一個step,同時也提供了執行Step的能力;
- org.springframework.batch.item.ItemReader<T>:提供了讀取數據的能力;
- org.springframework.batch.item.ItemProcessor<T>:我們可以通過它應用業務邏輯到每一條要處理的數據;
- org.springframework.batch.item.ItemWriter<T>:提供了寫數據的能力
Spring Batch通過這種方式構建一個Job的優點在於解耦每一個Step到它自己獨立的處理器當中;每一個Step負責得到數據、應用業務邏輯到這些數據、寫數據到適當的位置;
一個Tasklet是一種特別的Step類型,在沒有ItemReader和ItemWriter的情況下,使用它來執行一個功能;tasklet僅僅能被使用作一個單一的功能,如執行一些初始化、調用一個存儲過程、發送一個郵件通知Job已經完成。
運行Job
首先看下面這個圖,描述了Job的各個組件及其關系:
你會發現JobRepository這個組件會和多個其它組件發生聯系,它代表一個數據存儲(內存或者外部數據庫),被用來持久化Job或Step執行過程中用到的信息(用JobExecution和StepExecution來表示);
Job通過JobLauncher開始執行,JobLauncher通過檢查JobRepository來核實Job在之前是否運行過,並且驗證傳入到Job的參數,最后執行Job;
Job的執行流程和Step非常相似,Job首先實行每一個它包含的Step,當數據處理完成后,它將執行的結果更新到JobRepository的JobExecution和StepExecution中;Step首先通過ItemReader讀取每一個它要處理的數據項,交由StepPrpcessor處理,同時更新JobRepository中的StepExecution數據。一些信息如Commit次數、開始結束時間都會被存儲到JobRepository中,當一個Job/Step完成后,在JobRepository中相關的執行信息會被更新至最終狀態。
並行運算
在Spring Batch中,並行可以通過以下四種方式實現:
- 將Step多線程化:在Spring Batch里面,我們把Job被配置去處理的工作塊稱為Chunk,每一個Chunk被處理完成后,都會執行一次Commit;這些Chunk依次執行,假如有10000條記錄,一次處理50條,那么job會在1到50條記錄完成后Commit,然后在51到100條記錄完成后再次Commit;如果我們在Step中開啟3個線程,那么將增加3倍的處理能力:
- 並行的執行Step:假設我們有兩個Step,每一個都負責加載一個輸入文件的數據到數據庫中,這兩個Step之間沒有相互的依賴關系,我們則可以讓這兩個Step並行執行:
- 遠程chunking:前兩種方式都是在一個JVM里面去處理,這種方式允許你擴展你的處理跨多個JVM實例,其中一個JVM作為主節點,它通過一個ItemReader讀取輸入數據,然后通過網絡將數據發送到其它的JVM實例上(稱之為從節點)進行處理,處理完成后,從節點又將處理的結果發送回主結點,主結點通過ItemWriter輸出;
- 分區:這種方式不需要跨多個JVM實例,因此不需要網絡數據傳輸,但依然使用了主從配置;也就是說一個Step作為主Step,它扮演了其它多個從Step的控制器;它通過一個ItemReader讀取輸入數據,然后傳遞給從Step進行處理,處理完成后從Step又將處理的結果傳遞回主Step:
實例Job
Spring Batch提供了很多簡單的Job實例,讓你在開發你自定義的批處理應用程序時參考:
- adhocLoopJob:演示了一個無限循環的Job,通過JMX去暴露元素;
- beanWrapperMapperSampleJob:演示了如何實現基於文件的輸入數據的驗證和將文件字段映射到域對象;
- compositeItemWriterSampleJob:一個Step只能包含一個ItemReader和ItemWriter,這個Job教你如何繞開這個限制;
- customerFilterJob:演示如何使用一個ItemProcessor過濾無效的Customer;
- delegatingJob:使用ItemReaderAdapter,將輸入數據的讀取行為委托給一個POJO的某個方法;
- footballJob:一個足球賽事統計Job,在加載兩個輸入文件(一個文件是運動員數據,一個文件是賽事數據)之后,產生一個統計信息並輸出到日志文件;
- groovyJob:演示運行由groovy編寫的文件壓縮和解壓的腳本;
- headerFooterSample:演示如何使用回調,在輸出的時候添加Header和Footer;
- hibernateJob:Spring Batch Reader和Writer默認不會使用Hibernate,這個Job演示了如何整合Hibernate;
- infiniteLoopJob:一個無限循環Job,在Job停止后自動重啟;
- ioSampleJob:提供了很多不同IO方式的例子,如讀取分隔符文件、固定長度字段的文件、Xml、JDBC、iBATIS集成;
- jobSampleJob:演示了如何從一個Job中執行另外一個Job;
- loopFlowSample:演示如何用編程的方式去控制執行流程;
- mailJob:演示如何使用SimpleMailMessageItemWriter去發送eMail;