使用Elastic Job的分片配置加速任務執行和提高資源利用率

程式猿DD發表於2021-07-28

上一篇,我們介紹瞭如何使用Elastic Job實現定時任務。解決了使用@Scheduled來實現時候存在的競爭問題,同時也實現了定時任務的高可用執行。

然而,還有一類問題是我們在做定時任務時候容易出現的,就是任務執行速度時間過長;同時,為了實現定時任務的高可用,還啟動了很多工例項,但每個任務執行時候就一個例項在跑,資源利用率不高。

所以,接下來我們就來繼續介紹,使用Elastic Job的分片配置,來為任務執行加加速,資源利用抬抬高的目標!

動手試試

建議直接下載文末倉庫中的chapter7-2工程,然後在這個基礎上進行修改。當然,如果你對如何使用Elastic Job還不輸入,那麼先前往上一篇做個知識鋪墊,再繼續下面的內容!

第一步:建立一個分片執行的任務

@Slf4j
@Service
public class MyShardingJob implements SimpleJob {

    @Override
    public void execute(ShardingContext context) {
        switch (context.getShardingItem()) {
            case 0:
                log.info("分片1:執行任務");
                break;
            case 1:
                log.info("分片2:執行任務");
                break;
            case 2:
                log.info("分片3:執行任務");
                break;
        }
    }

}

這裡通過switch來判斷當前任務上下文的sharding-item值來執行不同的分片任務。sharding-item的值取決於後面將要配置的分片總數,但注意是從0開始計數的。 這裡僅採用了日誌列印的方式,來展示分片效果,真正實現業務邏輯的時候,一定記得根據分片數量對執行任務也要做分片操作的設計。比如:你可以根據批量任務的id求摩的方式來區分不同分片處理不同的資料,以避免重複執行而出現問題。

第二步:在配置檔案中,設定配置任務的實現類、執行表示式、以及將要重要測試的分片總數引數

elasticjob.jobs.my-sharding-job.elastic-job-class=com.didispace.chapter73.MyShardingJob
elasticjob.jobs.my-sharding-job.cron=0/5 * * * * ?
elasticjob.jobs.my-sharding-job.sharding-total-count=3

這裡設定為3,所以任務會被分為3個分片,每個分片對應第一步中一個switch的分支。

執行與測試

單例項執行

在完成了上面的程式碼之後,嘗試啟動上面實現的第一個例項。

此時,我們可以看到,每間隔5秒,這個例項會列印這樣的日誌:

2021-07-21 17:42:00.122  INFO 63478 --- [           main] .s.b.j.ScheduleJobBootstrapStartupRunner : Starting ElasticJob Bootstrap.
2021-07-21 17:42:00.126  INFO 63478 --- [           main] org.quartz.core.QuartzScheduler          : Scheduler my-sharding-job_$_NON_CLUSTERED started.
2021-07-21 17:42:00.126  INFO 63478 --- [           main] .s.b.j.ScheduleJobBootstrapStartupRunner : ElasticJob Bootstrap started.
2021-07-21 17:42:05.254  INFO 63478 --- [-sharding-job-1] com.didispace.chapter73.MyShardingJob    : 分片1:執行任務
2021-07-21 17:42:05.254  INFO 63478 --- [-sharding-job-3] com.didispace.chapter73.MyShardingJob    : 分片3:執行任務
2021-07-21 17:42:05.254  INFO 63478 --- [-sharding-job-2] com.didispace.chapter73.MyShardingJob    : 分片2:執行任務
2021-07-21 17:42:10.011  INFO 63478 --- [-sharding-job-4] com.didispace.chapter73.MyShardingJob    : 分片1:執行任務
2021-07-21 17:42:10.011  INFO 63478 --- [-sharding-job-5] com.didispace.chapter73.MyShardingJob    : 分片2:執行任務
2021-07-21 17:42:10.011  INFO 63478 --- [-sharding-job-6] com.didispace.chapter73.MyShardingJob    : 分片3:執行任務

每次任務都被拆分成了3個分片任務,就如我上文中所說的,每個分片對應一個switch的分支。由於當前情況下,我們只啟動了一個例項,所以3個分片任務都被分配到了這個唯一的例項上。

雙例項執行

接下來,我們再啟動一個例項(注意使用-Dserver.port來改變不同的埠,不然本地會啟動不成功)。此時,兩個例項的日誌出現了變化:

例項1的日誌:

2021-07-21 17:44:50.190  INFO 63478 --- [ng-job_Worker-1] com.didispace.chapter73.MyShardingJob    : 分片2:執行任務
2021-07-21 17:44:55.007  INFO 63478 --- [ng-job_Worker-1] com.didispace.chapter73.MyShardingJob    : 分片2:執行任務
2021-07-21 17:45:00.010  INFO 63478 --- [ng-job_Worker-1] com.didispace.chapter73.MyShardingJob    : 分片2:執行任務

例項2的日誌:

2021-07-21 17:44:50.272  INFO 63484 --- [-sharding-job-1] com.didispace.chapter73.MyShardingJob    : 分片1:執行任務
2021-07-21 17:44:50.273  INFO 63484 --- [-sharding-job-2] com.didispace.chapter73.MyShardingJob    : 分片3:執行任務
2021-07-21 17:44:55.009  INFO 63484 --- [-sharding-job-3] com.didispace.chapter73.MyShardingJob    : 分片1:執行任務
2021-07-21 17:44:55.009  INFO 63484 --- [-sharding-job-4] com.didispace.chapter73.MyShardingJob    : 分片3:執行任務

隨著例項數量的增加,可以看到分片的分配發生了變化。這也就意味著,當一個任務開始執行的時候,兩個任務執行例項都被利用了起來,這樣我們的任務執行和資源利用的效率就可以得到優化。

你也可以嘗試再繼續啟動例項和關閉例項來觀察任務的動態分配,怎麼樣?這樣寫定時任務是不是方便多了? 一定記得自己動手寫一寫,這樣體會更深哦!如果碰到問題,可以拉取文末的程式碼示例對比一下是否有地方配置不一樣。下一篇,我們還將繼續介紹關於定時任務的一些高階內容。

本系列教程《Spring Boot 2.x基礎教程》點選直達!,歡迎收藏與轉發!如果學習過程中如遇困難?可以加入我們Spring技術交流群,參與交流與討論,更好的學習與進步!

程式碼示例

本文的完整工程可以檢視下面倉庫中的chapter7-3目錄:

如果您覺得本文不錯,歡迎Star支援,您的關注是我堅持的動力!

歡迎關注我的公眾號:程式猿DD,分享外面看不到的乾貨與思考!

相關文章