使用Rqueue框架基於Redis和Spring Boot執行非同步任務 -sonus21
在本文中,我們將學習如何使用Spring Boot 2.x和Redis執行非同步任務,最後的程式碼演示了本文中描述的步驟。
一個典型的API呼叫包括五件事:
- 執行一個或多個資料庫(RDBMS / NoSQL)查詢。
- 在某些快取系統(記憶體中,分散式等)上的一項或多項操作。
- 一些計算(可能是做一些數學運算的一些資料處理)。
- 呼叫其他服務(內部/外部)。
- 安排一個或多個任務在以後或立即在後臺執行。
出於多種原因,可以在以後的某個時間安排任務。例如,必須在訂單建立或裝運後7天生成發票。同樣,不需要立即傳送電子郵件通知,因此我們可以延遲它們。
考慮到這些實際示例,有時,我們需要非同步執行任務以減少API響應時間。例如,我們收到一個立即刪除1K +記錄的請求,如果我們在同一API呼叫中刪除所有這些記錄,那麼肯定會增加API響應時間。為了減少API響應時間,我們可以在後臺執行一個任務,以刪除這些記錄。
Cron計劃缺點
每當我們計劃任務以給定時間或特定間隔執行時,我們就會使用計劃在特定時間或間隔進行的cron作業。我們可以使用UNIX風格的crontabs,Chronos等其他工具來執行計劃任務。如果我們使用的是Spring框架,則可以使用現成的Scheduled註釋。
大多數cron作業會查詢何時需要採取特定措施的記錄,例如,在7天后查詢所有發貨以及未生成發票的記錄。這些排程機制中的大多數都存在縮放問題,因為我們在其中掃描資料庫以查詢相關的行/記錄。
在許多情況下,這會導致全表掃描表現很差,想象一下實時應用程式和此批處理系統使用相同資料庫的情況。
由於它不可擴充套件,因此我們需要一些可擴充套件的系統,該系統可以在給定的時間或間隔執行任務,而不會出現任何效能問題。
有許多以這種方式擴充套件的方法,例如以批處理方式執行任務或在使用者/區域的特定子集上執行任務。另一種方法是在給定時間執行特定任務,而不依賴於其他任務,例如無伺服器功能。一個延遲佇列可以的情況下,一旦定時器達到預定時間的作業將被觸發使用。有許多可用的排隊系統/軟體,但很少有提供此功能的系統,例如SQS 它提供15分鐘的延遲,而不是7個小時或7天之類的任意延遲。
Rqueue框架
Rqueue是為Spring框架構建的訊息代理,將資料儲存在Redis中,並提供了一種在任意延遲下執行任務的機制。由於Redis與其他廣泛使用的排隊系統(例如Kafka或SQS)相比,具有一些優勢,因此Rqueue得到了Redis的支援。在大多數Web應用程式的後端中,Redis用於儲存快取的資料或其他目的。在當今世界上,有8.4% 的Web應用程式正在使用Redis資料庫。
通常,對於佇列,我們使用Kafka,SQS或其他一些系統。這些系統帶來了不同維度的額外開銷,例如,使用Rqueue和Redis可以將金錢減少為零。
除了成本外,如果我們使用Kafka,那麼我們需要進行基礎架構設定,維護,即需要更多操作,因為大多數應用程式已經在使用Redis,因此我們不會有操作開銷。實際上,相同的Redis伺服器/群集可與Rqueue一起使用,因為 Rqueue支援任意延遲。
這篇文章的完整程式碼可以在我的GitHub repo中找到。
訊息傳遞
Rqueue保證至少一次傳送訊息,因為長時間的資料不會在資料庫中丟失。您可以在這裡閱讀更多有關此內容:Rqueue簡介。
我們將需要的工具:
- Any IDE
- Gradle
- Java
- Redis
依賴:
- Spring Data Redis
- Spring Web
- Lombok
我們將使用Rqueue庫以任意延遲執行任何任務。Rqueue是基於Spring的非同步任務執行器,可以在任何延遲下執行任務。它是由Spring訊息傳遞庫構建的,並由Redis支援。
我們將新增Rqueue Spring Boot starter 2.7.0依賴項:
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'com.github.sonus21:rqueue-spring-boot-starter:2.0.0-RELEASE'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
出於測試目的,我們將啟用Spring Web MVC功能,以便我們可以傳送測試請求。
建立任務
使用Rqueue新增任務非常簡單,我們只需要使用RqueueListener註釋一個方法即可。RqueuListener批註具有多個可以根據用例設定的欄位,例如,設定deadLetterQueue可以將任務推送到另一個佇列,否則在失敗時將丟棄該任務。我們還可以使用numRetries欄位設定任務應重試多少次。
建立一個Java檔名MessageListener並新增一些方法來執行任務。
import com.github.sonus21.rqueue.annotation.RqueueListener; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @Component @Slf4j public class MessageListener { @RqueueListener(value = "${email.queue.name}") public void sendEmail(Email email) { log.info("Email {}", email); } @RqueueListener(value = "${invoice.queue.name}") public void generateInvoice(Invoice invoice) { log.info("Invoice {}", invoice); } } |
任務提交
可以使用RqueueMessageEnqueuer bean提交任務。 它有多種方法可以根據用例排隊任務,例如重試使用,重試計數和延遲任務的延遲。
我們需要AutoWire RqueueMessageEnqueuer或使用建構函式來注入此bean。
建立用於測試目的的控制器:
我們將計劃在接下來的30秒內完成發票生成,為此,我們將提交一個延遲30000(毫秒)的任務。另外,我們將嘗試傳送將在後臺完成的電子郵件。為此,我們將新增兩個GET方法sendEmail和generateInvoice,我們也可以使用POST。
@RestController @RequiredArgsConstructor(onConstructor = @__(@Autowired)) @Slf4j public class Controller { private @NonNull RqueueMessageEnqueuer rqueueMessageEnqueuer; @Value("${email.queue.name}") private String emailQueueName; @Value("${invoice.queue.name}") private String invoiceQueueName; @Value("${invoice.queue.delay}") private Long invoiceDelay; @GetMapping("email") public String sendEmail( @RequestParam String email, @RequestParam String subject, @RequestParam String content) { log.info("Sending email"); rqueueMessageEnqueuer.enqueue(emailQueueName, new Email(email, subject, content)); return "Please check your inbox!"; } @GetMapping("invoice") public String generateInvoice(@RequestParam String id, @RequestParam String type) { log.info("Generate invoice"); rqueueMessageEnqueuer.enqueueIn(invoiceQueueName, new Invoice(id, type), invoiceDelay); return "Invoice would be generated in " + invoiceDelay + " milliseconds"; } } |
application.properties:
email.queue.name=email-queue invoice.queue.name=invoice-queue # 30 seconds delay for invoice invoice.queue.delay=300000 |
執行測:http://localhost:8080/email?email=xample@exampl.com&subject=%22test%20email%22&content=%22testing%20email%22
30秒後發票:
http://localhost:8080/invoice?id=INV-1234&type=PROFORMA
總之,我們可以使用Rqueue排程任務,而無需花費很多鍋爐程式碼。在配置和使用Rqueue庫時,我們需要考慮一些事項。重要的一項是任務是否是延遲的任務。預設情況下,假定任務需要儘快執行。
完整的程式碼可以在我的Github帳戶中找到https://github.com/sonus21/rqueue-task-exector
Rqueue庫程式碼:https://github.com/sonus21/rqueue
相關文章
- Spring Boot @Async 非同步任務執行Spring Boot非同步
- Spring Boot使用執行緒池處理事務任務Spring Boot執行緒
- 同步任務與非同步任務執行順序非同步
- Django配置celery執行非同步任務和定時任務Django非同步
- 基於 swoole 的連線池模型和非同步任務小框架模型非同步框架
- Spring Boot 非同步框架的使用Spring Boot非同步框架
- Spring / Spring boot 非同步任務程式設計 WebAsyncTaskSpring Boot非同步程式設計Web
- Spring boot 非同步/定時任務/郵件Spring Boot非同步
- Spring 非同步執行緒池、排程任務執行緒池配置Spring非同步執行緒
- 基於Redis實現分散式鎖,避免重複執行定時任務Redis分散式
- 基於Istio/gRPC/Redis/BigQuery/Spring Boot/Spring Cloud和Stackdriver的微服務案例RPCRedisSpring BootCloud微服務
- 實戰Spring Boot 2.0系列(四) – 使用WebAsyncTask處理非同步任務Spring BootWeb非同步
- 實戰Spring Boot 2.0系列(四) - 使用WebAsyncTask處理非同步任務Spring BootWeb非同步
- laravel框架任務排程(定時執行任務)Laravel框架
- Spring Boot中有多個@Async非同步任務時,記得做好執行緒池的隔離!Spring Boot非同步執行緒
- spring執行定時任務Spring
- AsyncTask實現非同步任務執行非同步
- 使用spring @Scheduled註解執行定時任務、Spring
- 基於REDIS實現延時任務Redis
- 基於redis實現定時任務Redis
- Celery非同步任務框架非同步框架
- 並行執行任務的Fork/Join框架並行框架
- spring boot 定時任務Spring Boot
- 基於Spring Boot和Spring Cloud實現微服務架構Spring BootCloud微服務架構
- django + redis + celery 非同步任務DjangoRedis非同步
- Fork Join 併發任務執行框架框架
- Spring Boot應用中進行任務排程Spring Boot
- 基於asyncio和redis的Python分散式任務佇列RedisPython分散式佇列
- 微任務和巨集任務哪個先執行
- Spring Boot(九):定時任務Spring Boot
- 基於spring boot框架進行二次封裝,微型框架編寫思路Spring Boot框架封裝
- 使用Spring Boot實現Redis事務 | VinsguruSpring BootRedis
- 基於註解的Spring多資料來源配置和使用(非事務)Spring
- Springboot非同步任務執行緒池Spring Boot非同步執行緒
- Spring Boot使用@Async實現非同步呼叫:自定義執行緒池Spring Boot非同步執行緒
- spring boot中redis使用Spring BootRedis
- Spring Boot(三):Spring Boot 中 Redis 的使用Spring BootRedis
- 基於Redis的任務排程設計方案Redis