.NET Core使用 Coravel 實現任務調度
前言
前段時間需要在一個新項目里添加兩個后臺任務,去定時請求兩個供應商的API來同步數據;由于項目本身只是一個很小的服務,不太希望引入太重的框架,同時也沒持久化要求;于是我開始尋找在Quartz.Net、Hangfire之外,是否還有更為輕量級的框架滿足我的要求,最終我選擇了Coravel.
簡介
Coravel是一個專為.NET Core設計的.NET Standard庫,除了任務調度,還提供了像隊列、緩存、郵件等其它高級功能。特點就是對開發者十分友好,接入十分簡單、優雅、流暢,接近于零配置。
作為一個生于2018年的年輕項目,后發優勢明顯,一開始就是基于.Net Standard 2.0實現,沒有歷史負擔,同時又可以利用很多.Net Core新特性。
用法
首先安裝Coravel包
| dotnet add package coravel |
下面演示在.Net 6 Minimal API項目中接入Coravel并設置兩個定時任務,是不是非常簡單:)
| using Coravel; | |
| var builder = WebApplication.CreateBuilder(args); | |
| //只使用Coravel的任務調度功能 | |
| builder.Services.AddScheduler(); | |
| //注冊你自己的調度任務 | |
| builder.Services.AddTransient<YourCoravelJob1>(); | |
| builder.Services.AddTransient<YourCoravelJob2>(); | |
| var app = builder.Build(); | |
| //配置任務 | |
| app.Services.UseScheduler(scheduler => | |
| { | |
| scheduler.Schedule<YourCoravelJob1>().EveryFiveMinutes(); //每5分鐘執行一次Job1 | |
| scheduler.Schedule<YourCoravelJob2>().Hourly().Monday(); // 每周一每小時執行一次 | |
| }); |
Coravel預先定義好了很多常用的間隔頻率,非常的全面,像上面用到的 EveryFiveMinutes() 和 Hourly(),是不是非常的簡單優雅;當然Coravel也支持Cron表達式。
Invocable 是Coravel中的核心概念,代表一個獨立的任務,上面的YourCoravelJob1和YourCoravelJob2就是 Invocable,Coravel直接調度這些Invocable。
要創建你自己的Invocable,只需實現 IInvocable接口,在 Invoke方法中編碼你的任務。
| public class YourCoravelJob1 : IInvocable | |
| { | |
| private readonly ILogger _logger; | |
| public YourCoravelJob1(ILogger<YourCoravelJob1> logger) | |
| { | |
| _logger = logger; | |
| } | |
| public async Task Invoke() | |
| { | |
| _logger.LogInformation("start.."); | |
| } | |
| } | |
| } |
原理
Coravel使用是的.Net Core 2.0引入的IHostedService來實現后臺定時任務。(因此只有.Net Core 2.0以上的項目才能使用Coravel)
| public interface IHostedService | |
| { | |
| Task StartAsync(CancellationToken cancellationToken); | |
| Task StopAsync(CancellationToken cancellationToken); | |
| } |
SchedulerHost即實現了IHostedService接口,在 其StartAsync方法中,當程序完全啟動時,注冊了一個的Timer
| public Task StartAsync(CancellationToken cancellationToken) | |
| { | |
| this._lifetime.ApplicationStarted.Register(InitializeAfterAppStarted); | |
| return Task.CompletedTask; | |
| } | |
| private void InitializeAfterAppStarted() | |
| { | |
| this._timer = new Timer(this.RunSchedulerPerSecondAsync, null, TimeSpan.Zero, TimeSpan.FromSeconds(1)); | |
| } | |
| private async void RunSchedulerPerSecondAsync(object state) | |
| { | |
| if (this._schedulerEnabled) | |
| { | |
| await this._scheduler.RunSchedulerAsync(); | |
| } | |
| } |
每秒調用 RunSchedulerAsync 激活到點的Invocable,同時會根據情況將任務分組,在單獨的線程分開執行。從這里可以看到Coravel是支持秒級任務的。
在 StopAsync 方法中,會先等待正在執行的任務完成才會關閉,這個功能還是比較重要。
| public async Task StopAsync(CancellationToken cancellationToken) | |
| { | |
| this._schedulerEnabled = false; // Prevents changing the timer from firing scheduled tasks. | |
| this._timer?.Change(Timeout.Infinite, 0); | |
| this._scheduler.CancelAllCancellableTasks(); | |
| // If a previous scheduler execution is still running (due to some long-running scheduled task[s]) | |
| // we don't want to shutdown while they are still running. | |
| if (this._scheduler.IsRunning) | |
| { | |
| this._logger.LogWarning(ScheduledTasksRunningMessage); | |
| } | |
| while (this._scheduler.IsRunning) | |
| { | |
| await Task.Delay(50); | |
| } | |
| } | |
總結
本文介紹一個對開發者友好的、輕量級、零配置的.Net Standard庫Coravel,并演示了如何使用Coravel在.Net 6 Minimal API中創建定時任務,最后淺析了的實現原理。作為一個年輕的框架,Coravel站在了巨人的肩膀上,相比Quartz.Net、Hangfire,也擁有很多亮點特性,很值得嘗試。
任何問題或者建議,歡迎評論區留言討論~
參考鏈接
本文來自博客園,作者:{春光牛牛,yak},轉載請注明原文鏈接:http://www.rzrgm.cn/yakniu/p/16615306.html
歡迎各位大佬們評論指正
QQ討論群:610129902


浙公網安備 33010602011771號