爲你的 Go 應用添加定時任務
在 Linux 上,我們經常使用計劃任務來執行一些定時任務,比如,在凌晨執行數據庫備份、進行賬務日結操作等。在我們的 Golang 應用中,我們也想執行一些定時任務,怎麼辦?
cron 是 Golang 的一個定時任務庫,被廣泛應用於 Golang 應用中。cron 目前使用的 V3 版本,默認支持 Linux cron 表達式,沒有秒的字段。
Linux cron 表達式格式:
# * * * * * <command to execute>
# | | | | |
# | | | | day of the week (0–6) (Sunday to Saturday;
# | | | month (1–12) 7 is also Sunday on some systems)
# | | day of the month (1–31)
# | hour (0–23)
# minute (0–59)
我們要實現定時任務,集成 cron 後會非常簡單。首先,在我們的應用中引入該庫:
import "github.com/robfig/cron/v3"
然後,創建 cron 實例,添加 Job 即可。例如:
c := cron.New()
c.AddFunc("30 * * * *", func() { fmt.Println("Every hour on the half hour") })
c.AddFunc("30 3-6,20-23 * * *", func() { fmt.Println(".. in the range 3-6am, 8-11pm") })
c.AddFunc("CRON_TZ=Asia/Tokyo 30 04 * * *", func() { fmt.Println("Runs at 04:30 Tokyo time every day") })
c.AddFunc("@hourly", func() { fmt.Println("Every hour, starting an hour from now") })
c.AddFunc("@every 1h30m", func() { fmt.Println("Every hour thirty, starting an hour thirty from now") })
c.Start()
..
// Funcs are invoked in their own goroutine, asynchronously.
...
// Funcs may also be added to a running Cron
c.AddFunc("@daily", func() { fmt.Println("Every day") })
..
// Inspect the cron job entries' next and previous run times.
inspect(c.Entries())
..
c.Stop() // Stop the scheduler (does not stop any jobs already running).
上面的調度支持多種寫法:
其中有 Linux 表達式,沒有秒字段,如果你要支持秒字段,例如像 Java 中的 Quartz 表達式,可以這樣初始化 cron:
cron.New(cron.WithSeconds())
還支持預定義表達式,例如,每天 @daily,每小時 @hourly。
還支持一個固定的間隔,例如,@every ,其中,這個 duration 是一個能夠被 time.ParseDuration 解析的字符串。例如,每半個小時,就可以這樣寫 "@every 30m"。
還支持時區。例如東京時區,“CRON_TZ=Asia/Tokyo 30 04 * * *”。
講完了表達式,我們看下如何添加定時任務。首先除了上方代碼中已經寫出的 AddFunc 方法,它的一個參數是函數,函數格式爲 func(){}。還支持直接添加 Job,如果添加 Job,需要你自行實現 Job 接口。下面是我定義的一個 Job,例如:MyJob
type MyJob struct {
Name string
}
func (g MyJob) Run() {
fmt.Println("Hello ", g.Name)
}
c.AddJob("@every 5s", MyJob{"dj"})
最後,啓動 cron。
c.Start()
當執行 Start() 函數後,cron 自動開始執行,在調用 Stop() 方法之前,我們可以隨時添加 Job,cron 內部會自動判斷任務是否運行,然後執行不同的邏輯。這對於動態添加任務非常有用。
下面講下 Cron 實現原理:
Cron 將執行的實體條目(Job)存儲在數組中,並按照其下一次調度時間進行排序。然後進行休眠,直到下一個調度時間到達。
當調度時間到達後,它會按順序執行如下操作:
-
運行在該時刻處於活動狀態的條目。
-
計算已運行作業的下一次運行時間。
-
按下一次激活時間對條目數組進行重新排序。
-
睡眠直到下一次調度時間到達。
以上操作重複執行,直到 cron 任務被調用者停止。
這個 cron 庫非常強大,除了上方的常用用法外,還支持自定義日誌,Job 包裝器等高級用法。推薦閱讀一下 cron 源碼,它實現非常精巧,Github 地址:
https://github.com/robfig/cron
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/QepAIqyOLRnyIWZRdtZcKQ