Spring用JobRunr分佈式後台作業調度和處理
- Spring
- java
1.概述
在本教程中,我們將研究使用JobRunr在Java中進行分佈式後台作業調度和處理,並將其與Spring集成。
2.關於JobRunr
JobRunr是一個我們可以嵌入到我們的應用程序中的庫,它允許我們使用Java 8 lambda調度後台作業。我們可以使用Spring服務的任何現有方法來創建作業,而無需實現接口。作業可以是短期的,也可以是長期運行的,它將自動卸載到後台線程,這樣就不會阻止當前的Web請求。
為此,JobRunr分析了Java 8 lambda。它將其序列化為JSON,並將其存儲到關係數據庫或NoSQL數據存儲中。
3. JobRunr功能
如果我們看到我們正在生成過多的後台作業,而我們的服務器無法應付負載,則可以通過添加應用程序的額外實例來輕鬆地水平擴展。 JobRunr將自動分擔負載,並在我們應用程序的不同實例上分配所有作業。
它還包含自動重試功能,並為失敗的作業提供了指數補償策略。還有一個內置的儀表板,使我們可以監視所有作業。 JobRunr是自我維護的–成功的作業將在可配置的時間後自動刪除,因此無需執行手動存儲清理。
4.設定
為了簡單起見,我們將使用內存中的數據存儲來存儲所有與作業相關的信息。
4.1 Maven配置
讓我們直接跳到Java代碼。但是在此之前,我們需要在pom.xml
文件中聲明以下Maven依賴項:
<dependency>
<groupId>org.jobrunr</groupId>
<artifactId>jobrunr-spring-boot-starter</artifactId>
<version>1.1.0</version>
</dependency>
4.2 Spring整合
在我們直接轉到如何創建後台作業之前,我們需要初始化JobRunr。由於我們正在使用jobrunr-spring-boot-starter
依賴項,因此這很容易。我們只需要向application.properties
添加一些屬性:
org.jobrunr.background-job-server.enabled=true
org.jobrunr.dashboard.enabled=true
第一個屬性告訴JobRunr我們要啟動一個負責處理作業BackgroundJobServer
第二個屬性告訴JobRunr啟動嵌入式儀表板。
默認情況下,如果有關係數據庫來存儲所有與作業相關的信息jobrunr-spring-boot-starter
會嘗試使用您現有的DataSource
但是,由於我們將使用內存中的數據存儲,因此我們需要提供一個StorageProvider
bean:
@Bean
public StorageProvider storageProvider(JobMapper jobMapper) {
InMemoryStorageProvider storageProvider = new InMemoryStorageProvider();
storageProvider.setJobMapper(jobMapper);
return storageProvider;
}
5.用法
現在,讓我們了解如何使用JobRunr在Spring中創建和安排後台作業。
5.1 注入依賴
當我們要創建作業時,我們需要注入JobScheduler
和我們現有的Spring服務,其中包含我們要為其創建作業的方法,在本例中為SampleJobService
:
@Inject
private JobScheduler jobScheduler;
@Inject
private SampleJobService sampleJobService;
JobScheduler
類允許我們排隊或安排新的後台作業。
SampleJobService
可以是我們現有的任何Spring服務,其中包含一種方法,該方法可能需要很長時間才能在Web請求中處理。它也可以是在其他我們要添加彈性的外部服務上調用的方法,因為如果發生異常,JobRunr將重試該方法。
5.2 創建一勞永逸的工作
現在我們有了依賴關係,我們可以使用enqueue方法enqueue
jobScheduler.enqueue(() -> sampleJobService.executeSampleJob());
作業可以具有參數,就像其他任何lambda一樣:
jobScheduler.enqueue(() -> sampleJobService.executeSampleJob("some string"));
該行確保將lambda(包括類型,方法和參數)作為JSON序列化為持久性存儲(Oracle,Postgres,MySql和MariaDB之類的RDBMS或NoSQL數據庫)。
BackgroundJobServer
運行的專用線程工作池將以先進先出的方式盡快執行這些排隊的後台作業。 JobRunr通過樂觀鎖定保證單個工人執行您的工作。
5.3 計劃將來的作業
我們還可以使用schedule
方法來計劃將來的作業:
jobScheduler.schedule(() -> sampleJobService.executeSampleJob(), LocalDateTime.now().plusHours(5));
5.4 定期周期性作業
如果我們想擁有周期性工作,則需要使用scheduleRecurrently
方法:
jobScheduler.scheduleRecurrently(() -> sampleJobService.executeSampleJob(), Cron.hourly());
5.5 使用@Job
批註進行批註
為了控製作業的各個方面,我們可以使用@Job
批註來批註我們的服務方法。這樣可以在儀表板中設置顯示名稱,並配置萬一作業失敗的重試次數。
@Job(name = "The sample job with variable %0", retries = 2)
public void executeSampleJob(String variable) {
...
}
String.format()
語法以顯示名稱傳遞給作業的變量。
如果我們有非常特定的用例,僅希望在特定的例外情況下重試特定的作業,則可以編寫自己的ElectStateFilter
,在其中我們可以訪問Job
並完全控制執行方式。
6.儀表板
JobRunr帶有內置的儀表板,可讓我們監視作業。我們可以在http:// localhost:8000上找到它,並檢查所有作業,包括所有重複發生的作業,以及在處理所有排隊的作業之前需要多長時間的估計:
可能發生不好的事情,例如SSL證書過期或磁盤已滿。默認情況下,JobRunr將使用指數退避策略重新計劃後台作業。如果後台作業繼續失敗十次,則只有這樣才能進入Failed
狀態。解決了根本原因後,您可以決定重新排隊失敗的作業。
所有這些信息在儀表板中都是可見的,包括每次重試以及確切的錯誤消息和作業失敗原因的完整堆棧跟踪:
7.結論
在本文中,我們使用Jobrunr和jobrunr-spring-boot-starter
構建了第一個基本調度程序。本教程的主要收穫是,我們能夠僅用一行代碼創建作業,而無需任何基於XML的配置或實現接口的需要。