如何在Spring中使用JobRunr實現後臺作業? - Baeldung

banq發表於2020-10-17

在本教程中,我們將研究使用JobRunr在Java中進行分散式後臺作業排程和處理,並將其與Spring整合。

JobRunr是一個我們可以嵌入到應用程式中的庫,它使我們可以使用Java 8 lambda排程後臺作業。我們可以使用Spring服務的任何現有方法來建立作業,而無需實現介面。作業可能是一個短期或長期執行的過程,它將被自動解除安裝到後臺執行緒,這樣就不會阻止當前的Web請求。JobRunr分析了Java 8 lambda。它將其序列化為JSON,並將其儲存到關聯式資料庫或NoSQL資料儲存中。
如果我們看到我們產生了太多的後臺作業,而我們的伺服器無法應付負載,則可以透過新增應用程式的額外例項來輕鬆地水平擴充套件。JobRunr將自動分擔負載,並在我們應用程式的不同例項上分配所有作業。
它還包含自動重試功能,並針對失敗的作業提供指數補償策略。還有一個內建的儀表板,使我們可以監視所有作業。JobRunr是自我維護的–成功的作業將在可配置的時間後自動刪除,因此無需執行手動儲存清理。
 

設定

<dependency>
    <groupId>org.jobrunr</groupId>
    <artifactId>jobrunr-spring-boot-starter</artifactId>
    <version>1.0.0</version>
</dependency>

只需要向application.properties新增一些屬性:

org.jobrunr.background_job_server=true
org.jobrunr.dashboard=true

第一個屬性告訴JobRunr我們要啟動一個負責處理作業的BackgroundJobServer例項。第二個屬性告訴JobRunr啟動嵌入式儀表板。
預設情況下,如果是關聯式資料庫來儲存所有與工作相關的資訊,jobrunr-spring-boot-starter會嘗試使用您現有的資料來源。
但是,由於我們將使用記憶體中的資料儲存,因此我們需要提供一個StorageProvider bean:

@Bean
public StorageProvider storageProvider(JobMapper jobMapper) {
    InMemoryStorageProvider storageProvider = new InMemoryStorageProvider();
    storageProvider.setJobMapper(jobMapper);
    return storageProvider;
}

 

用法
當我們要建立作業時,我們需要注入JobScheduler和我們現有的Spring服務,其中包含我們要為其建立作業的方法,在本例中為SampleJobService:

@Inject
private JobScheduler jobScheduler;
 
@Inject
private SampleJobService sampleJobService;


jobscheduler從JobRunr類允許我們排隊或安排新的後臺作業。
SampleJobService可能是我們任何包含可能需要很長時間的web請求處理方法存在的Spring服務。它也可以是在其他我們想新增彈性的外部服務上呼叫的方法,因為如果發生異常,JobRunr將重試該方法。
現在我們有了依賴關係,我們可以使用enqueue方法建立即發即棄的作業:

jobScheduler.enqueue(() -> sampleJobService.executeSampleJob());


作業可以具有引數,就像其他任何lambda一樣:

jobScheduler.enqueue(() -> sampleJobService.executeSampleJob("some string"));

將lambda(包括型別,方法和引數)作為JSON序列化到永續性儲存(Oracle,Postgres,MySql和MariaDB之類的RDBMS或NoSQL資料庫)。
然後,在所有不同BackgroundJobServer中執行的專用執行緒工作池將以先進先出的方式儘快執行這些排隊的後臺作業。JobRunr透過樂觀鎖定保證單個工人執行您的工作。
還可以使用schedule方法來計劃將來的作業:

jobScheduler.schedule(() -> sampleJobService.executeSampleJob(), LocalDateTime.now().plusHours(5));

如果我們想擁有周期性工作,則需要使用scheduleRecurrently方法:

jobScheduler.scheduleRecurrently(() -> sampleJobService.executeSampleJob(), Cron.hourly());


為了控制作業的各個方面,我們可以使用@Job註釋來註釋我們的服務方法。這樣可以在儀表板中設定顯示名稱,並配置萬一作業失敗的重試次數。

@Job(name = "The sample job with variable %0", retries = 2)
public void executeSampleJob(String variable) {
    ...
}

我們甚至可以使用透過String.format()語法以顯示名稱傳遞給作業的變數。
如果我們有非常特殊的用例,而我們只想在特定的例外情況下重試特定的作業,則可以編寫自己的ElectStateFilter,在其中可以訪問Job並完全控制操作方式。
 

儀表板
JobRunr帶有內建的儀表板,可讓我們監視作業。我們可以在http:// localhost:8000上找到它,並檢查所有作業,包括所有重複出現的作業,以及在處理所有排隊的作業之前需要多長時間的估計。
可能會發生不良情況,例如SSL證照過期或磁碟已滿。預設情況下,JobRunr將使用指數退避策略重新計劃後臺作業。如果後臺作業繼續失敗十次,則只有這樣才能進入失敗狀態。解決了根本原因後,您可以決定重新排隊失敗的作業。
所有這些資訊在儀表板中都是可見的,包括每次重試以及確切的錯誤訊息和作業失敗原因的完整堆疊跟蹤:
 
在本文中,我們使用Jobrunr和jobrunr-spring-boot-starter構建了第一個基本排程程式。本教程的主要收穫是,我們僅用一行程式碼即可建立作業,而無需進行任何基於XML的配置或實現介面。
該示例的完整原始碼可在GitHub上獲得

相關文章