Spring Batch學習記錄

什麼是Spring Batch

Spring Batch是Spring 的一個子項目,是一款基於Spring的企業批處理框架,是一個輕量級的、全面的批處理框架。
Spring Batch提供了可重用的功能,不僅提供了統一的讀寫接口、豐富的任務處理方式、靈活的事務管理以及併發處理,同時還支持日誌、監控、任務重啓玉跳過等特性。

爲什麼要使用Spring Batch以及應用的場景

  • 爲什麼要使用

    Spring Batch是基於Spring開發的很容易上手
    Spring Batch不是一個調度框架,因爲它已經有非常好的企業級調度框架包括Quartz等,它只注重任務處理的相關問題,如執行任務、事務、併發等,而不是提供調度功能

  • 應用的場景
    • 週期提交批處理任務
    • 同時批處理任務:並非處理一個任務
    • 分階段的企業消息驅動處理
    • 高併發批處理
    • 失敗後的手動或定時重啓
    • 按順序處理任務依賴(使用工作流驅動的批處理插件)
    • 部分處理:跳過記錄(例如:回滾)
    • 全批次事務:因爲可能有小數據量的批處理或存在存儲過程/腳本
  • 批處理的特點
    • 數據量大
    • 整個過程全部自動化,並預留一定接口進行自定義配置
    • 這樣的應用通常是週期性運行,比如按日、周、月運行
    • 對數據處理的準確性要求高,並且需要容錯機制、回滾機制、完善的日誌監控等

Spring Batch的處理原則

1. 儘量使用公用模塊
2. 儘量簡化操作,不要有複雜的業務邏輯,更不要處理一條數據還要調用外部接口進行數據加工
3. 儘可能少的IO操作
4. 同一個批處理文件不要處理兩次
5. 儘可能壓力測試

Spring Batch的結構

Spring Batch分三層:應用層、核心層和基礎架構層
應用層: 開發人員使用Spring Batch編寫的所有批處理任務代碼
核心層: 包含加載和控制批處理作業所需的核心類,Job,Step等類的實現
基礎架構層: 包含統用的讀寫器和重試模塊

batch流程

在這裏插入圖片描述

Spring batch框架有4個主要組件:JobLauncher、Job、Step和JobRepository。
	1)JobLauncher(任務啓動器):通過它啓動任務,可以理解爲程序的入口。
	2)Job(任務):一個具體的任務。
	3)Step(步驟):一個具體的執行步驟,一個Job中可以有多個Step。
	4)JobRepository(任務倉庫):存儲數據的倉庫,在任務執行的時候,需要用它來記錄任務狀態信息,可以看做是一個數據庫的接口。
	JobLauncher啓動Job,Job可以有多個Step組合,每個Step有開發者自己編寫
	每一個Step對應一個ItemReader、ItemProcessor和ItemWriter
	
job : 任務
  一個job可以由一個或多個step組成,通過JobBuilderFactory實例創建Bean,使用next指向下一個step;

flow:  
   1.是多個step的集合;
   2.可以被多個Job複用;
   3.由flowBuilder來創建的;

split:
     實現併發執行;


批處理框架簡單抽象成:讀取數據、處理數據、寫數據
Spring Batch提供了三個接口: ItemReader、ItemProcessor、ItemWriter
JobRepository是記錄Job、Step和發起Job的執行信息

Step的處理流程

Spring Batch的核心概念

  • 什麼是JobLauncher

    JobLauncher是任務啓動器,該接口只有一個run方法

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

    除了傳入Job對象外,還需要傳入JobParameters對象,通過JobLauncher可以在java程序中調用批處理任務,也可以通過命令行或者其他框架(如定時調度框架Quartz、Web後臺框架Spring MVC)中調用批處理任務

  • 什麼是JOB

    Job是一個封裝整個批處理過程的概念,體現在代碼中是最上層的一個接口
    Job的實現類主要有兩種:一個是simplejob,另一個是flowjob
    一個Job是我們運行的基本單位,它內部由Step組成,Job實質上是Step的一個容器,

    @Bean
    public Job footballJob(){
        return jobBuilderFactory.get("footballJob")
                .start(firstStep())
                .next(secondStep())
                .build();
    }
    配置的意思是:首先給Job起一個名字footballJob,接着指定這個Job的兩個Step(有幾個Step指定幾個,也可以靈活指定),他們分別由方法firstStep()secondStep()實現
    
  • 什麼是JobInstance

    JobInstance指的是邏輯單元的概念,考慮一個批作業,不僅僅執行一次,所以對每個作業的運行必須單獨邏輯的JobInstance跟蹤,而且每個JobInstance可以多個執行,並且在給定時間內相同參數的同一個JobInstance只能有一個能運行。

    JobInstance的定義與要加載的數據完全沒有關係

  • 什麼是JobParameters

    同一個Job每天運行一次的話,每天也就都有一個JobInstance,但是如何區分JobInstance呢?那麼就是JobParameters

    JobParameters對象包含一組用於啓動批處理作業的參數,它在運行期間用於識別或者用作參考數據。
    JobInstance =Job + JobParameters
    JobInstance

  • 什麼是JobExecution

    JobExecution作爲一個Job一次執行任務的上下文,因爲Job的一個JobInstance有可能失敗而多次執行,這樣就需要一個上下文來管理同一個JobInstance的多次執行,一次執行有可能失敗或成功結束,只有JobExecution執行成功JobInstance才被認爲是完成了。

  • 什麼是Step

    Step是一個領域對象,它體現了批處理作業的獨立的、連續的階段。一個Step可以簡單也可以複雜,一個簡單的步驟可能會將數據從文件加載到數據庫中,只需要很少或根本不需要代碼,更復雜的步驟可能有作爲處理一部分應用的複雜業務規則。與Job一樣,Step也有獨立的StepExecution存儲每一個Step的執行信息。

    Step流程

  • 什麼是StepExecution

    StepExecution表示一次執行Step,每次運行一個Step時都會創建一個新的StepExecution,類似與JobExecution,但是某個步驟可能由於其之前的步驟失敗而無法執行,且僅當Step實際啓動時纔會創建StepExecution。

    StepExecution 用來表示每一個step 的執行。每個StepExecution都包含對其相應step和與JobExecution以及事務相關數據的引用,比如提交和回滾計數以及開始和結束時間。此外,每個步驟執行都包含一個ExecutionContext,它包含開發人員在批處理運行期間需要持久化的任何數據,例如重新啓動所需的統計信息或狀態信息。

  • 什麼是ExecutionContext

    ExecutionContext即每一個StepExecution 的執行環境。它包含一系列的鍵值對。我們可以用如下代碼獲取ExecutionContext

    ExecutionContext ecStep = stepExecution.getExecutionContext();
    ExecutionContext ecJob = jobExecution.getExecutionContext();
    
    
  • 什麼是JobRepository

    JobRepository是一個用於將上述job,step等概念進行持久化的一個類。 它同時給Job和Step以及下文會提到的JobLauncher實現提供CRUD操作。 首次啓動Job時,將從repository中獲取JobExecution,並且在執行批處理的過程中,StepExecution和JobExecution將被存儲到repository當中。

    @EnableBatchProcessing註解可以爲JobRepository提供自動配置。

  • 什麼是JobLauncher

    JobLauncher這個接口的功能非常簡單,它是用於啓動指定了JobParameters的Job,爲什麼這裏要強調指定了JobParameter,原因jobparameter和job一起才能組成一次job的執行

    public interface JobLauncher {
        public JobExecution run(Job job, JobParameters jobParameters)
                throws JobExecutionAlreadyRunningException, JobRestartException,
                JobInstanceAlreadyCompleteException, JobParametersInvalidException;
    }
    
  • 什麼是Item Reader

    ItemReader是一個讀數據的抽象,它的功能是爲每一個Step提供數據輸入。 當ItemReader以及讀完所有數據時,它會返回null來告訴後續操作數據已經讀完。Spring Batch爲ItemReader提供了非常多的有用的實現類,比如JdbcPagingItemReader,JdbcCursorItemReader等等。
    ItemReader包括各種類型的數據庫,文件,數據流,等等

    JdbcPagingItemReader必須指定一個PagingQueryProvider,負責提供SQL查詢語句來按分頁返回數據

    下面是一個JdbcCursorItemReader的例子代碼:
    	private JdbcCursorItemReader<Map<String, Object>> buildItemReader(final DataSource dataSource, String tableName,
            String tenant) {
    
        JdbcCursorItemReader<Map<String, Object>> itemReader = new JdbcCursorItemReader<>();
        itemReader.setDataSource(dataSource);
        itemReader.setSql("sql here");
        itemReader.setRowMapper(new RowMapper());
        return itemReader;
    }
    
  • 什麼是Item Writer

    ItemReader是讀數據的一個抽象,那麼ItemWriter自然就是一個寫數據的抽象,它是爲每一個step提供數據寫出的功能。寫的單位是可以配置的,我們可以一次寫一條數據,也可以一次寫一個chunk的數據,關於chunk下文會有專門的介紹。ItemWriter對於讀入的數據是不能做任何操作的。

  • 什麼是Item Processor

    ItemReader是讀數據的一個抽象,那麼ItemWriter自然就是一個寫數據的抽象,它是爲每一個step提供數據寫出的功能。寫的單位是可以配置的,我們可以一次寫一條數據,也可以一次寫一個chunk的數據,關於chunk下文會有專門的介紹。ItemWriter對於讀入的數據是不能做任何操作的。

  • 什麼是Chunk

    由於我們一次batch的任務可能會有很多的數據讀寫操作,因此一條一條的處理並向數據庫提交的話效率不會很高,因此spring batch提供了chunk這個概念,我們可以設定一個chunk size,spring batch 將一條一條處理數據,但不提交到數據庫,只有當處理的數據數量達到chunk size設定的值得時候,才一起去commit.

    @Bean
    public Job footballJob(){
        return jobBuilderFactory.get("footballJob")
                .start(Step1())
                .build();
    }
    @Bean
    public Step Step1() {
        return stepBuilderFactory.get("Step1")
                .chunk(10)
                .reader(itemReader())
                .writer(itemWriter())
                .build();
    }
    在上面這個step裏面,chunk size被設爲了10,當ItemReader讀的數據數量達到10的時候,
    這一批次的數據就一起被傳到itemWriter,同時transaction被提交。
    

    Tasklet 與chunk 的區別

    Tasklet 意味着在step中執行單個任務,job有多個step按一定順序組成,每個步驟應該執行一個具體任務。
    我們的job有三個步驟:
    a.從輸入csv文件讀
    b.對每個輸入行數據計算年齡
    c.寫姓名和年齡至輸出csv文件

    Chunk 方法該方法基於數據塊(一部分數據)執行。也就是說,其不是一次讀、處理和寫所有行,而是一次僅讀、處理、寫固定數量記錄。然後重複循環執行直到讀不到數據爲止。
    因此,此流程與上面有些差異:
    while 有數據:
    do X 行數據
    讀一行
    處理一行
    寫 X 行數據

    Tasklet 與chunk 總結:

    兩者差異顯示了各自適用場景。tasklet更適合一個步驟到另一個步驟場景。chunk提供簡單解決方案:實現處理分頁讀,或我們不想在內存中保留大量數據場景。

Spring Batch小案例

Spring Batch完整入門實踐

Spring Batch 入門級示例教程

參考文檔

Spring Batch參考文檔中文版

spring batch 理解、特點、使用場景、結構 簡單介紹

Spring Batch 文檔和手冊(中文)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章