Go 每日一庫之定時任務(wù)庫:cron
在Linux中,Cron是計(jì)劃任務(wù)管理系統(tǒng),通過crontab命令使任務(wù)在約定的時間執(zhí)行已經(jīng)計(jì)劃好的工作,例如定時備份系統(tǒng)數(shù)據(jù)、周期性清理緩存、定時重啟服務(wù)等。本文介紹的cron庫,就是用Go實(shí)現(xiàn)Linux中crontab命令的相似效果。
使用示例
安裝下載cron,目前最新的穩(wěn)定版已經(jīng)迭代到了v3
go?get?github.com/robfig/cron/v3@v3.0.0
在項(xiàng)目中導(dǎo)入包
import?"github.com/robfig/cron/v3"
使用
1package?main
2
3import?(
4????"fmt"
5
6????"github.com/robfig/cron/v3"
7)
8
9func?main()?{
10????c?:=?cron.New()
11????c.AddFunc("30?*?*?*?*",?func()?{?fmt.Println("Every?hour?on?the?half?hour")?})
12????c.AddFunc("30?3-6,20-23?*?*?*",?func()?{?fmt.Println("..?in?the?range?3-6am,?8-11pm")?})
13????c.AddFunc("CRON_TZ=Asia/Tokyo?30?04?*?*?*",?func()?{?fmt.Println("Runs?at?04:30?Tokyo?time?every?day")?})
14????c.AddFunc("@hourly",?func()?{?fmt.Println("Every?hour,?starting?an?hour?from?now")?})
15????c.AddFunc("@every?1h30m",?func()?{?fmt.Println("Every?hour?thirty,?starting?an?hour?thirty?from?now")?})
16????c.AddFunc("@every?1s",?func()?{fmt.Println("Every?1?second,?starting?an?hour?thirty?from?now")})
17????c.Start()
18????select?{}
19}
創(chuàng)建cron對象
添加觸發(fā)任務(wù)
30?*?*?*?*表示每個小時內(nèi)的第30分鐘時觸發(fā);30 3-6,20-23 *?*?*表示在早上3點(diǎn)到6點(diǎn),下午8點(diǎn)到11點(diǎn)的第30分鐘時觸發(fā);CRON_TZ=Asia/Tokyo 30?04 *?*?*表示東京時間每天早上4點(diǎn)半觸發(fā);@hourly表示從添加該任務(wù)時算起的之后每小時觸發(fā);@every 1h30m表示從添加該任務(wù)時算起的之后每一個半小時觸發(fā);@every 1s表示從添加該任務(wù)時算起的之后每秒觸發(fā)。
啟動定時循環(huán)
1?$?go?run?main.go?
2Every?1?second,?starting?an?hour?thirty?from?now
3Every?1?second,?starting?an?hour?thirty?from?now
4Every?1?second,?starting?an?hour?thirty?from?now
5Every?1?second,?starting?an?hour?thirty?from?now
6...
cron時間表達(dá)式規(guī)則
1Field?name???|?Mandatory??|?Allowed?values??|?Allowed?special?characters
2----------???|?----------?|?--------------??|?--------------------------
3Minutes??????|?Yes????????|?0-59????????????|?*?/?,?-
4Hours????????|?Yes????????|?0-23????????????|?*?/?,?-
5Day?of?month?|?Yes????????|?1-31????????????|?*?/?,?-??
6Month????????|?Yes????????|?1-12?or?JAN-DEC?|?*?/?,?-
7Day?of?week??|?Yes????????|?0-6?or?SUN-SAT??|?*?/?,?-??
1cron.New(
2????cron.WithParser(
3????????cron.NewParser(
4????????????cron.Second?|?cron.Minute?|?cron.Hour?|?cron.Dom?|?cron.Month?|?cron.Dow?|?cron.Descriptor)))
1cron.New(cron.WithSeconds())
預(yù)定義時間表
1Entry??????????????????|?Description????????????????????????????????|?Equivalent?To
2-----??????????????????|?-----------????????????????????????????????|?-------------
3@yearly?(or?@annually)?|?Run?once?a?year,?midnight,?Jan.?1st????????|?0?0?1?1?*
4@monthly???????????????|?Run?once?a?month,?midnight,?first?of?month?|?0?0?1?*?*
5@weekly????????????????|?Run?once?a?week,?midnight?between?Sat/Sun??|?0?0?*?*?0
6@daily?(or?@midnight)??|?Run?once?a?day,?midnight???????????????????|?0?0?*?*?*
7@hourly????????????????|?Run?once?an?hour,?beginning?of?hour????????|?0?*?*?*?*
時間間隔
1@every?
cron可控選項(xiàng)
在cron源碼option.go文件中,暴露了5個函數(shù)供開發(fā)者控制cron對象的選項(xiàng)。
WithLocation()
指定時區(qū)。默認(rèn)情況下基于當(dāng)前時區(qū)(在Unix系統(tǒng)中,查詢TZ環(huán)境變量確定要使用的時區(qū),若未定義TZ,則使用/etc/localtime文件中的定義時區(qū))??赏ㄟ^在時間字符串前添加CRON_TZ=字符串再加上具體的時區(qū)。例如東京時區(qū)為Asia/Tokyo。
1c.AddFunc("CRON_TZ=Asia/Tokyo?30?04?*?*?*",?func()?{?fmt.Println("Runs?at?04:30?Tokyo?time?every?day")?})
WithParser()
WithSeconds()
增加對秒的時間格式支持,其內(nèi)部調(diào)用的WithParser()方法。
1func?WithSeconds()?Option?{
2????return?WithParser(NewParser(
3????????Second?|?Minute?|?Hour?|?Dom?|?Month?|?Dow?|?Descriptor,
4????))
5}
WithChain()
Job包裝器,下文中會講解Job接口。
WithLogger()
1package?main
2
3import?(
4????"fmt"
5????"log"
6????"os"
7
8????"github.com/robfig/cron/v3"
9)
10
11func?main()?{
12????c?:=?cron.New(cron.WithLogger(cron.VerbosePrintfLogger(log.New(os.Stdout,?"cron?process:?",?log.LstdFlags))))
13????c.AddFunc("@every?1s",?func()?{?fmt.Println("Every?1?second")?})
14????c.Start()
15????select?{}
16}
該logger記錄了cron內(nèi)部的調(diào)度過程,輸入如下
1go?run?main.go?
2cron?process:?2020/08/30?00:07:04?start
3cron?process:?2020/08/30?00:07:04?schedule,?now=2020-08-30T00:07:04+08:00,?entry=1,?next=2020-08-30T00:07:05+08:00
4cron?process:?2020/08/30?00:07:05?wake,?now=2020-08-30T00:07:05+08:00
5cron?process:?2020/08/30?00:07:05?run,?now=2020-08-30T00:07:05+08:00,?entry=1,?next=2020-08-30T00:07:06+08:00
6Every?1?second
7cron?process:?2020/08/30?00:07:06?wake,?now=2020-08-30T00:07:06+08:00
8Every?1?second
9cron?process:?2020/08/30?00:07:06?run,?now=2020-08-30T00:07:06+08:00,?entry=1,?next=2020-08-30T00:07:07+08:00
10cron?process:?2020/08/30?00:07:07?wake,?now=2020-08-30T00:07:07+08:00
11cron?process:?2020/08/30?00:07:07?run,?now=2020-08-30T00:07:07+08:00,?entry=1,?next=2020-08-30T00:07:08+08:00
12Every?1?second
13...
自定義Job
cron中定義了Job接口,對象只要實(shí)現(xiàn)了Job接口所定義的Run()方法,均可以調(diào)用cron.AddJob()方法將該對象添加到定時管理器中。
1//?Job?is?an?interface?for?submitted?cron?jobs.
2type?Job?interface?{
3????Run()
4}
AddFunc()
在上文示例中,通過cron.AddFunc()方法為cron對象添加定時任務(wù)。實(shí)質(zhì)上,AddFunc()方法內(nèi)部調(diào)用的也是AddJob()方法:定義新類型對象FuncJob,為其實(shí)現(xiàn)Job接口,在AddFunc()方法中,將回調(diào)參數(shù)func()轉(zhuǎn)為FuncJob類型,調(diào)用AddJob()方法。
1type?FuncJob?func()
2
3func?(f?FuncJob)?Run()?{?f()?}
4
5func?(c?*Cron)?AddFunc(spec?string,?cmd?func())?(EntryID,?error)?{
6????return?c.AddJob(spec,?FuncJob(cmd))
7}
自實(shí)現(xiàn)Job接口
除了通過AddFunc()將無參函數(shù)直接作為回調(diào)外,我們還可以通過AddJon()自定義對象。
1package?main
2
3import?(
4????"fmt"
5????"time"
6
7????"github.com/robfig/cron/v3"
8)
9
10type?CallJob?struct?{
11????name???string
12????number?int
13}
14
15func?(c?CallJob)?Run()?{
16????fmt.Printf("call?%s?:?%d\n",?c.name,?c.number)
17}
18func?main()?{
19????c?:=?cron.New()
20????c.AddJob("@every?1s",?CallJob{
21????????name:???"Bob",
22????????number:?13888888888,
23????})
24????c.Start()
25
26????time.Sleep(3?*?time.Second)
27}
輸出
1?$?go?run?main.go?
2call?Bob?:?13888888888
3call?Bob?:?13888888888
4call?Bob?:?13888888888
總結(jié)
cron庫為go開發(fā)者提供了強(qiáng)大的定時任務(wù)管理功能,它的時間表達(dá)式格式和linux下的crontab命令是對齊的。
cron的代碼并不算多,其核心定時管理功能依賴了go標(biāo)準(zhǔn)庫time和sort,非常值得學(xué)習(xí)和參考。另外有一個基于該庫抽離出來的最小化定時任務(wù)庫gron,更易理解和使用,文末會附上該庫地址。
cron是小菜刀在實(shí)際項(xiàng)目中引入過的三方庫,感覺挺不錯,就總結(jié)出來分享給大家。如果你喜歡看更多關(guān)于三方庫的文章,請點(diǎn)贊支持。
倉庫地址
1.?https://github.com/robfig/cron
2.?https://github.com/roylee0704/gron
推薦閱讀
站長 polarisxu
自己的原創(chuàng)文章
不限于 Go 技術(shù)
職場和創(chuàng)業(yè)經(jīng)驗(yàn)
Go語言中文網(wǎng)
每天為你
分享 Go 知識
Go愛好者值得關(guān)注

