首页 > 其他分享 >Go定时任务实现

Go定时任务实现

时间:2023-11-02 15:59:04浏览次数:26  
标签:go 任务 func time Go 定时 ticker

定时任务调度是常见的场景,从简单点本地任务调度,到分布式定时任务调度,被广泛的使用。本文汇总了 awesome-go 里全部的本地定时任务库,并横向对比其实现原理,以及使用场景和优缺点,欢迎收藏随时参考。

本文收纳的本地定时任务库如下:

  1. onatm/clockwerk
  2. withself/clockwork
  3. kr/go-cron
  4. roylee0704/gron
  5. carlescere/scheduler

1. 定时任务基础

最基础的定时任务

众所周知,go 语言的 time 库提供了 Ticker 方法,可以通过:

ticker := time.NewTicker(duration) 的方式获取到一个定时返回的 chan,此可以用来帮助我们实现基础的定时任务功能,比如如下函数就是基础的实现:

package main

import (
    "fmt"
    "time"
)

func NewCronJob(duration time.Duration, job func()) (stopChan chan bool) {
    ticker := time.NewTicker(duration)
    stopChan = make(chan bool)

    go func(ticker *time.Ticker) {
        defer ticker.Stop()
        // 由于ticker.Stop()内部不会关闭chan,故使用 for range 会内存泄露
        // 推荐使用 for + select + return 的方式,让 ticker 最终被GC
        for {
            select {
            case <-ticker.C:
                job()
            case stop := <-stopChan:
                if stop {
                    close(stopChan)
                    return
                }
            }
        }
    }(ticker)

    return stopChan
}

func main() {
    stopCtr := NewCronJob(2*time.Second, func() {
        fmt.Printf("hello word:%+v\n", time.Now())
    })

    time.Sleep(10 * time.Second)

    stopCtr <- true

    // example output:
    // hello word:2023-02-26 11:10:17.470147 +0800 CST m=+2.001352251
    // hello word:2023-02-26 11:10:19.470141 +0800 CST m=+4.001330084
    // hello word:2023-02-26 11:10:21.470154 +0800 CST m=+6.001327917
    // hello word:2023-02-26 11:10:23.469824 +0800 CST m=+8.000981501
    // hello word:2023-02-26 11:10:25.470273 +0800 CST m=+10.001414209
}

 

使用 time.Sleep() 也可以实现这个功能,但是 Ticker 会更加优雅些。

cron 表达式

time.Ticker() 非常简单好用,但是也有不足,就是难以控制让任务在准确地时间里执行,比如 ticker 可以实现每半个小时执行一次,但是无法直接实现,每个小时 30 分时执行一次。

Linux 系统里的 crontab 可以完美解决这个问题,通过类似如下的字符串,就定义了在每个小时 30 分执行的任务。

30 * * * *

corntab 只有五位

*    *    *    *    *
-    -    -    -    -
|    |    |    |    |
|    |    |    |    +----- 星期几 (0 - 6) (星期天=0)
|    |    |    +---------- 月份 (1 - 12) 
|    |    +--------------- 一个月中的第几天 (1 - 31)
|    +-------------------- 小时 (0 - 23)
+------------------------- 分钟 (0 - 59)

基础 corntab 派生的 corn 有 6 位或者 7 位,多出的一到两位,精确到了秒或者年,具体可参考此文

像开源的 robfig/cron 就是 Go 的知名开源corn库。

2. 定时任务通用实现——基础

如果将上述定时任务的实例代码进行封装,就可以实现一个简单由实用的定时任务。下文将分析并对比,awesome-go 推荐的定时任务库。

经典样例——onatm/clockwerk

先看下使用样例:

type DummyJob struct{}

func (d DummyJob) Run() {
  fmt.Println("Every 30 seconds")
}

func main() {
  var job DummyJob
  c := clockwerk.New()
  c.Every(30 * time.Second).Do(job)
  c.Start()
}

 

使用模式可以总结为如下步骤其他开源库也基本上都是按照这个模式使用。
  1. New 创建一个调度对象
  2. Every 确定的 duration
  3. Do 将任务加入调度对象
  4. Start 启动执行调度对象里的任务

源码非常简洁,直接上流程图:

image.png image.png

其核心控制逻辑是:

func (c *Clockwerk) run() {
    ticker := time.NewTicker(100 * time.Millisecond)
    go func() {
        for {
            select {
            case <-ticker.C:
                // 遍历所有的job,执行到点的任务
                c.runPending()
                continue
            case <-c.stop:
                ticker.Stop()
                return
            }
        }
    }()
}

其他开源库对比

项目

最近更新时间

定时声明模式

定时机制

能否中途添加任务

管理任务能力

panic 相关

onatm/clockwerk

2019

时间间隔 time. Duration

100 ms 的 ticker 控制轮询

可停止全部任务

任务 panic 后,会 recover 并重新调度

whiteshtef/clockwork

2020

Every 模式

死循环默认 sleep 333 ms(可设置)

不可停止

参数声明错误 panic,任务不处理

rk/go-cron

2013

corn 表达式

死循环默认 sleep 1 s(不可设置)

不可停止

roylee 0704/gron

2016

Every 模式

由 time. After 触发执行

可停止全部任务

参数声明错误 panic,任务不处理

carlescere/scheduler

2015

Every 模式

由 time. After 触发执行

返回任务对象,可控制停止

综合我们可以总结出来,核心流程:

标签:go,任务,func,time,Go,定时,ticker
From: https://www.cnblogs.com/siyunianhua/p/17805578.html

相关文章

  • Go--cron定时任务
    Cron是Go中用于设置定时任务的一个库,需要注意的是,Cron库分两个大版本,v1.2和v3.0,其功能和goget地址都是不同的,注意区分。v1.2官方文档:https://pkg.go.dev/github.com/robfig/cronv3官方文档:https://pkg.go.dev/github.com/robfig/cron/v3区别:v1.2版本默认支持精确到秒的cron......
  • 分享一个项目:`learning_go_plan9_assembly`, 学习 golang plan9 汇编
    作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢!cnblogs博客zhihuGithub公众号:一本正经的瞎扯近期在学习golangplan9汇编,总算基本做到了手写汇编,并整理了很多笔记。plan9汇编的资料少,难学,难用。可能也有想学习汇编的人会遇到与我一样的问题。于是把笔记进......
  • vue3 google浏览器格式化控制台打印的数据
    ......
  • [ARC159F] Good Division 题解
    [ARC159F]GoodDivision题解首先对于题目要求的划分方式转化一下,转化为划分的每一段都没有绝对众数,可以证明这与题目中的要求是完全等价的,证明如下:充分性:考虑构造一种操作方法,就是每次操作都消去一个出现次数最多的数,按照这样操作可以保证每次操作之后该区间仍然不会出现绝对......
  • mysqld got signal 11
    【1】mysql实例启动故障5.7.21-》5.7.42数据库升级后,启动发现错误日志如下2023-08-10T23:05:53.463377+08:000[Warning]TIMESTAMPwithimplicitDEFAULTvalueisdeprecated.Pleaseuse--explicit_defaults_for_timestampserveroption(seedocumentationformore......
  • google analytics , looker , bigquery的区别
    GoogleAnalytics、Looker和BigQuery是Google提供的三种不同的数据服务,它们各自有不同的用途和功能。GoogleAnalytics:主要用途:GoogleAnalytics是一种网站和应用程序分析服务,它能帮助您理解用户如何与您的网站或应用互动。它收集关于页面浏览量、用户会话、用户行为......
  • TypeError: fit() got an unexpected keyword argument 'nb_epoch'
    model.fit(trainX,trainY,nb_epoch=200,batch_size=2,verbose=2) It'sjust epochs now. nb_epoch wasdeprecatedyearsago. 把nb_epoch......
  • 七牛云 + PicGo
    下载PicGohttps://github.com/Molunerfinn/PicGo/releases/tag/v2.3.1七牛云配置1、AccessKey和SecretKey:可以在七牛云控制台,秘钥管理页面找到你的配置2、存储空间名:填写前面创建的空间名称3、访问地址:你的域名4、存储区域:七牛云的存储区域(华东z0,华北z1,华南z2,北美na0,东......
  • odigos 基于ebpf 以及OpenTelemetry 的分布式tracing 解决方案
    按照odigos官方的介绍是不需要进行代码的修改就可以实现方便的跨应用的分布式trace,目前支持java,python,net,go,js等语言目前看官方的介绍,安装是比较简单的(核心基于了k8s),目前官方文档比较清晰可以试用下说明目前开源分布式trace的工具是越来越多了,同时基于ebpf以及OpenTelemetry......
  • django搭建平台实战教程三:接口编写及权限校验(前后端分离)
    自定义权限校验注册增加group_id字段...@api_view(['POST'])defregister(request:Request):ifDUser.objects.filter(username=request.data["username"]).count()>0:returnResponse({"code":400,&qu......