Go 定时任务执行-cron

Go 定时任务执行-cron

stromXu 760 2022-08-23

cron-github地址:
https://github.com/robfig/cron

1、安装依赖

go get github.com/robfig/cron/v3@v3.0.0

导入:
import "github.com/robfig/cron/v3"

2、代码示例

2.1、普通操作

func TestCron(t *testing.T) {
	c := cron.New()
	cronId, err := c.AddFunc("@every 1s", func() {
		fmt.Println(time.Now(), "一秒一次")
	})
	fmt.Println("执行定时任务id", cronId, err)
	c.Start()
	time.Sleep(8 * time.Second)
}
=== RUN   TestCron
执行定时任务id 1 <nil>
2022-08-23 16:47:15.0004815 +0800 CST m=+0.594273801 一秒一次
2022-08-23 16:47:16.0006382 +0800 CST m=+1.594430501 一秒一次
2022-08-23 16:47:17.0007651 +0800 CST m=+2.594557401 一秒一次
2022-08-23 16:47:18.0009394 +0800 CST m=+3.594731701 一秒一次
2022-08-23 16:47:19.0010578 +0800 CST m=+4.594850101 一秒一次
2022-08-23 16:47:20.0003283 +0800 CST m=+5.594120701 一秒一次
2022-08-23 16:47:21.0004863 +0800 CST m=+6.594278601 一秒一次
2022-08-23 16:47:22.0005673 +0800 CST m=+7.594359601 一秒一次
--- PASS: TestCron (8.00s)
PASS
ok      eth2-lighthouse/test    8.002s


> 测试运行完成时间: 2022/8/23 16:47:22 <

2.2、多定时任务

func TestCrons(t *testing.T) {
	c := cron.New(cron.WithChain())
	cronId1, err := c.AddFunc("@every 1s", func() {
		fmt.Println(time.Now(), "1秒一次")
	})

	cronId2, err := c.AddFunc("@every 2s", func() {
		fmt.Println(time.Now(), "2秒一次")
	})

	fmt.Println("执行定时任务id", cronId1, err)
	fmt.Println("执行定时任务id", cronId2, err)
	c.Start()
	defer c.Stop()
	time.Sleep(8 * time.Second)
}
=== RUN   TestCrons
执行定时任务id 1 <nil>
执行定时任务id 2 <nil>
2022-08-23 17:08:20.0011193 +0800 CST m=+0.390331301 1秒一次
2022-08-23 17:08:21.000471 +0800 CST m=+1.389683001 2秒一次
2022-08-23 17:08:21.0004908 +0800 CST m=+1.389702901 1秒一次
2022-08-23 17:08:22.0006538 +0800 CST m=+2.389865901 1秒一次
2022-08-23 17:08:23.0008043 +0800 CST m=+3.390016301 2秒一次
2022-08-23 17:08:23.0008207 +0800 CST m=+3.390032701 1秒一次
2022-08-23 17:08:24.0009363 +0800 CST m=+4.390148301 1秒一次
2022-08-23 17:08:25.0010462 +0800 CST m=+5.390258201 2秒一次
2022-08-23 17:08:25.0010754 +0800 CST m=+5.390287401 1秒一次
2022-08-23 17:08:26.0004696 +0800 CST m=+6.389681701 1秒一次
2022-08-23 17:08:27.0005977 +0800 CST m=+7.389809701 2秒一次
2022-08-23 17:08:27.0006388 +0800 CST m=+7.389850801 1秒一次
--- PASS: TestCrons (8.00s)
PASS
ok      eth2-lighthouse/test    8.002s

2.3、多定时任务Job(也可以单独执行,可带参数执行)

func TestCronsJob(t *testing.T) {
	c := cron.New(cron.WithSeconds())

	//不带参
	cronJob1, err := c.AddJob("@every 1s", &CronJob1{})

	//带参数执行
	cronJob2, err := c.AddJob("@every 2s", &CronJob2{Name: "任务2"})

	fmt.Println("执行定时任务id", cronJob1, err)
	fmt.Println("执行定时任务id", cronJob2, err)
	c.Start()
	defer c.Stop()
	time.Sleep(8 * time.Second)
}

type CronJob1 struct {
}

func (t CronJob1) Run() {
	fmt.Println(time.Now(), "执行定时任务: CronJob1")
}

type CronJob2 struct {
	Name string
}

func (t CronJob2) Run() {
	fmt.Println(time.Now(), "执行定时任务: CronJob2", t.Name)
}
=== RUN   TestCronsJob
执行定时任务id 1 <nil>
执行定时任务id 2 <nil>
2022-08-23 17:15:51.0010691 +0800 CST m=+0.646762301 执行定时任务: CronJob1
2022-08-23 17:15:52.0002512 +0800 CST m=+1.645944501 执行定时任务: CronJob1
2022-08-23 17:15:52.0002304 +0800 CST m=+1.645923601 执行定时任务: CronJob2 任务2
2022-08-23 17:15:53.0005753 +0800 CST m=+2.646268601 执行定时任务: CronJob1
2022-08-23 17:15:54.0006843 +0800 CST m=+3.646377601 执行定时任务: CronJob2 任务2
2022-08-23 17:15:54.0006994 +0800 CST m=+3.646392601 执行定时任务: CronJob1
2022-08-23 17:15:55.0009107 +0800 CST m=+4.646603901 执行定时任务: CronJob1
2022-08-23 17:15:56.0010091 +0800 CST m=+5.646702301 执行定时任务: CronJob2 任务2
2022-08-23 17:15:56.0010264 +0800 CST m=+5.646719801 执行定时任务: CronJob1
2022-08-23 17:15:57.0002019 +0800 CST m=+6.645895101 执行定时任务: CronJob1
2022-08-23 17:15:58.0008982 +0800 CST m=+7.646591401 执行定时任务: CronJob2 任务2
2022-08-23 17:15:58.0009412 +0800 CST m=+7.646634601 执行定时任务: CronJob1
--- PASS: TestCronsJob (8.00s)
PASS
ok      eth2-lighthouse/test    8.003s

3、一些常用类型说明和函数解释

3.1、cron.New(cron.WithLocation())

指定时区:所有时间都是基于当前时区的

  • 1、在时间字符串前面添加一个CRON_TZ= + 具体时区, 比如:东京时区为Asia/Tokyo,纽约时区为America/New_York;上海时区为Asia/Shanghai;香港时区为Asia/Hong_Kong
  • 2、创建cron对象时增加一个时区选项cron.WithLocation(location),location为time.LoadLocation(zone)加载的时区对象,zone为具体的时区格式。
	loc, _ := time.LoadLocation("Asia/Shanghai")
	c := cron.New(cron.WithLocation(loc))
  
  或者
  
  c := cron.New()
	c.AddFunc("CRON_TZ=Asia/Shanghai * 1 * * * *", func() {
	})
  
 
  

3.2、cron.New(cron.WithLocation())

Job 包装器可以在执行实际的Job前后添加一些逻辑:

  • 捕获panic;
  • 如果Job上次运行还未结束,推迟本次执行;
  • 如果Job上次运行还未介绍,跳过本次执行;
  • 记录每个Job的执行情况。
//跳过本次执行 log可以写自己的。。。。
c := cron.New(cron.WithChain(cron.SkipIfStillRunning(cron.DefaultLogger)))

//推迟本次执行
c := cron.New(cron.WithChain(cron.DelayIfStillRunning(cron.DefaultLogger)))

//捕获异常啥的
c := cron.New(cron.WithChain(cron.Recover(cron.DefaultLogger)))


3.3、cron.New(cron.WithSeconds())

让时间格式支持秒,实际上内部调用了WithParser。

	c := cron.New(cron.WithSeconds())

3.4、cron.New(cron.WithLogger())

让时间格式支持秒,实际上内部调用了WithParser。

	c := cron.New(cron.WithLogger(cron.VerbosePrintfLogger(log.New(os.Stdout, "cron: ", log.LstdFlags))))

4、Cron时间常用表达式

  • @yearly:也可以写作@annually,表示每年第一天的 0 点。等价于0 0 1 1 *;
  • @monthly:表示每月第一天的 0 点。等价于0 0 1 * *;
  • @weekly:表示每周第一天的 0 点,注意第一天为周日,即周六结束,周日开始的那个 0 点。等价于0 0 * * 0;
  • @daily:也可以写作@midnight,表示每天 0 点。等价于0 0 * * *;
  • @hourly:表示每小时的开始。等价于0 * * * *。
  • @every :会调用time.ParseDuration()函数解析,例如1s ,1m,1d,1h30m
"* * * * * *"
分别对应:
分 时 天 月 星期

每隔5秒执行一次:*/5 * * * * ?

每隔1分钟执行一次:0 */1 * * * ?

每天23点执行一次:0 0 23 * * ?

每天凌晨1点执行一次:0 0 1 * * ?

每月1号凌晨1点执行一次:0 0 1 1 * ?

每周一和周三晚上22:30: 00 30 22 * * 1,3 

在15分、25分、35分执行一次:0 15,25,35 * * * ?




# go