【Golang】定时任务Cron指南-毫秒级任务支持

文章目录

  • Cron
    • Cron快速使用
    • 时间表达式
      • 最小分钟级任务
      • 最小秒级任务
      • 预定义的时间表
    • 时区
    • Job
    • 选项
      • Job 包装器
      • WithLogger
    • 支持毫秒级任务

Cron

版本:v3.0.0
仓库:https://github.com/robfig/cron

cron是golang实现定时任务比较好的库, 这个库提供了一个简单而强大的接口,用于创建和管理基于cron表达式的定时任务。cron库的主要特点有:

  • 基于cron表达式的任务调度
  • 多任务支持
  • 容错和错误处理
  • 可靠性
  • 易用的API
  • 灵活性
  • 并发安全

Cron快速使用

package mainimport ("fmt""github.com/robfig/cron/v3"
)func main() {job := cron.New()job.AddFunc("@every 1s", func() {fmt.Println("hello world")})job.Start()select {}
}

上述简单的示例表示,每秒钟执行一次hello world打印。其中容易让人产生困惑的是"@every 1s"的含义,这是一条描述定时任务执行的时间表达式,下面将会具体介绍。

时间表达式

cron库支持用 6 个空格分隔的域来表示时间(在v3版本中新增了对秒级任务的支持):

# ┌────────────── second (0–59)
# │ ┌───────────── minute (0–59)
# │ │ ┌───────────── hour (0–23)
# │ │ │ ┌───────────── day of the month (1–31)
# │ │ │ │ ┌───────────── month (1–12)
# │ │ │ │ │ ┌───────────── day of the week (0–6) (Sunday to Saturday;
# │ │ │ │ │ │                                   7 is also Sunday on some systems)
# │ │ │ │ │ │
# │ │ │ │ │ │
# * * * * * * <command to execute>
Field name   | Mandatory? | Allowed values  | Allowed special characters
----------   | ---------- | --------------  | --------------------------
Seconds      | Yes        | 0-59            | * / , -
Minutes      | Yes        | 0-59            | * / , -
Hours        | Yes        | 0-23            | * / , -
Day of month | Yes        | 1-31            | * / , - ?
Month        | Yes        | 1-12 or JAN-DEC | * / , -
Day of week  | Yes        | 0-6 or SUN-SAT  | * / , - ?
  • 星号 (*):星号表示 cron 表达式将匹配该字段的所有值;例如,在第 5 个字段(月份)中使用星号将表示每个月。
  • 斜杠 (/):斜杠用于描述范围的步长。例如,第2个字段(分钟)中的 3-59/15 表示该小时的第 3 分钟以及此后每 15 分钟一次。
  • 逗号 (,):逗号用于分隔列表中的项目。例如,在第 6 个字段(星期几)中使用“MON,WED,FRI”将表示星期一、星期三和星期五。
  • 连字符 (-):连字符用于定义范围。例如,在第 3 个字段(小时)9-17 表示上午 9 点到下午 5 点之间的每小时(含)。
  • 问号(?):只能用在月和周的域中,用来代替*,表示每月/周的任意一天。

最小分钟级任务

使用这种以空格分隔的域来表示时间的方式默认情况下只能支持到分钟级任务:

package mainimport ("fmt""github.com/robfig/cron/v3"
)func main() {job := cron.New()job.AddFunc("* * * * *", func() {fmt.Println("hello world")})job.Start()select {}
}

表示每分钟执行一次
注意:实测在v3.0.1版本6个*是不会执行任务的。
查看表达是是否正确:https://crontab.guru/

最小秒级任务

如果想要支持秒级任务,则需添加cron.WithSeconds选项:

package mainimport ("fmt""github.com/robfig/cron/v3"
)func main() {job := cron.New()job.AddFunc("* * * * * *", func() {fmt.Println("hello world")})job.Start()select {}
}

表示每秒执行一次
注意:添加了cron.WithSeconds后6个*可以正确执行。

预定义的时间表

可以使用几个预定义计划之一来代替 cron 表达式。

Entry                  | Description                                | Equivalent To
-----                  | -----------                                | -------------
@yearly (or @annually) | Run once a year, midnight, Jan. 1st        | 0 0 0 1 1 *
@monthly               | Run once a month, midnight, first of month | 0 0 0 1 * *
@weekly                | Run once a week, midnight between Sat/Sun  | 0 0 0 * * 0
@daily (or @midnight)  | Run once a day, midnight                   | 0 0 0 * * *
@hourly                | Run once an hour, beginning of hour        | 0 0 * * * *

还可以安排作业以固定的时间间隔执行,从添加作业或运行 cron 时开始。这是通过格式化 cron 规范来支持的,如下所示:

@every <duration>

其中“duration”time.ParseDuration 接受的字符串(http://golang.org/pkg/time/#ParseDuration)
例子:

c := cron.New()
c.AddFunc("@hourly",      func() { fmt.Println("Every hour") })
c.AddFunc("@every 1h30m", func() { fmt.Println("Every hour thirty") })
c.AddFunc("@every 1s", func() { fmt.Println("Every seconds") })
c.Start()

cron还提供了cron.Every方法,用于直接接收time.Duration来设置任务间隔:

package mainimport ("fmt""time""github.com/robfig/cron/v3"
)func main() {job := cron.New(cron.WithSeconds())job.Schedule(cron.Every(1*time.Second), cron.FuncJob(func() {fmt.Println("hello world")}))job.Start()select {}
}

时区

默认情况下任务是基于当前时区的,cron也可以设置不同的时区:

loLosAngeles, _ := time.LoadLocation("America/Los_Angeles")
job := cron.New(cron.WithLocation(loLosAngeles))
job.AddFunc("0 6 * * ?", func() {fmt.Println("Every 6 o'clock at Los Angeles")
})

或者:

job.AddFunc("CRON_TZ=Asia/Tokyo 0 6 * * ?", func() {fmt.Println("Every 6 o'clock at Tokyo")
})

Job

除了使用无参的回调方式,cron还提供了实现job接口的方式:

type Job interface {Run()
}

实现job接口

package mainimport ("fmt""time""github.com/robfig/cron/v3"
)func main() {job := cron.New(cron.WithSeconds())j := &myJob{}job.AddJob("@every 1s", j)job.Start()select {}
}type myJob struct {i int
}func (j *myJob) Run() {j.i++fmt.Println("hello world:", j.i)
}

执行结果:

hello world: 1
hello world: 2
hello world: 3
hello world: 4
hello world: 5
hello world: 6

选项

  • WithLocation:指定时区
  • WithParser:使用自定义的解析器
  • WithSeconds:让时间格式支持秒
  • WithLogger:自定义日志
  • WithChain:Job 包装器

Job 包装器

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

cron库提供了一些常用的包装器:

  • cron.DelayIfStillRunning: 如果上周期的任务还在执行,则延迟此次并产生一条Info日志
  • cron.SkipIfStillRunning:如果上周期的任务还在执行,则跳过此次并产生一条Info日志
  • cron.Recover:捕获任务异常,并产生error日志

WithLogger

cron提供默认的标准输出日志打印cron.DefaultLogger和丢弃日志cron.DiscardLogger两种:

// DefaultLogger is used by Cron if none is specified.
var DefaultLogger Logger = PrintfLogger(log.New(os.Stdout, "cron: ", log.LstdFlags))// DiscardLogger can be used by callers to discard all log messages.
var DiscardLogger Logger = PrintfLogger(log.New(ioutil.Discard, "", 0))

也可是使用cron.PrintfLoggercron.VerbosePrintfLogger包装:

  • cron.PrintfLogger: 只打印错误日志
  • cron.VerbosePrintfLogger:打印详细日志
package mainimport ("fmt""github.com/robfig/cron/v3"
)func main() {job := cron.New(cron.WithLogger(cron.VerbosePrintfLogger(log.New(os.Stdout, "cron: ", log.LstdFlags),)),)job.AddFunc("@every 1s", func() {fmt.Println("hello world")})job.Start()select {}
}

支持毫秒级任务

cron库给出的方法最小只能支持到秒级任务,如果想要精确到毫秒级任务,则需要重新实现Schedule接口

// Schedule describes a job's duty cycle.
type Schedule interface {// Next returns the next activation time, later than the given time.// Next is invoked initially, and then each time the job is run.Next(time.Time) time.Time
}

自定义一个ConstantDelaySchedule结构体,并给出Every方法(这边我限制最小到200ms)

package cronimport "time"// ConstantDelaySchedule represents a simple recurring duty cycle, e.g. "Every 5 minutes".
// It does not support jobs more frequent than once a second.
type ConstantDelaySchedule struct {Delay time.Duration
}// Every returns a crontab Schedule that activates once every duration.
// Delays of less than a second are not supported (will round up to 1 second).
// Any fields less than a Second are truncated.
func Every(duration time.Duration) ConstantDelaySchedule {min := 200 * time.Millisecondif duration < min {duration = min}return ConstantDelaySchedule{Delay: duration,}
}// Next returns the next time this should be run.
// This rounds so that the next activation time will be on the second.
func (schedule ConstantDelaySchedule) Next(t time.Time) time.Time {return t.Add(schedule.Delay)
}

调用:

package mainimport ("fmt""time""github.com/robfig/cron/v3"
)func main() {job := cron.New(cron.WithSeconds())j := &myJob{t: time.Now(),}job.Schedule(Every(200*time.Millisecond), j)job.Start()select {}
}type myJob struct {i intt time.Time
}func (j *myJob) Run() {j.i++now := time.Now()sub := now.Sub(j.t)j.t = nowfmt.Printf("hello world: %d, duraction : %d ms \n", j.i, sub.Milliseconds())
}

结果:

hello world: 1, duraction : 201 ms 
hello world: 2, duraction : 201 ms 
hello world: 3, duraction : 201 ms 
hello world: 4, duraction : 201 ms 
hello world: 5, duraction : 201 ms 
hello world: 6, duraction : 200 ms 
hello world: 7, duraction : 201 ms 
hello world: 8, duraction : 201 ms 
hello world: 9, duraction : 201 ms 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/675482.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Tomcat 原理分析

1、Tomcat 的组成 如下图&#xff1a; Tomcat组成 Server&#xff1a; Tomcat 封装的、对外提供完整的、基于组件的 web 服务&#xff0c;包含 Connectors、Container 两个核心组件&#xff0c;以及多个功能组件&#xff0c;各个 Service 之间是独立的&#xff0c;但是共享 同…

MoE-LLaVA:具有高效缩放和多模态专业知识的大型视觉语言模型

视觉和语言模型的交叉导致了人工智能的变革性进步&#xff0c;使应用程序能够以类似于人类感知的方式理解和解释世界。大型视觉语言模型(LVLMs)在图像识别、视觉问题回答和多模态交互方面提供了无与伦比的能力。 MoE-LLaVA利用了“专家混合”策略融合视觉和语言数据&#xff0…

B2075 幂的末尾(洛谷)

复制Markdown 展开 题目描述 a的b次方的末 3 位数是多少&#xff1f; 输入格式 两个正整数 a&#xff0c;b。1≤a≤100&#xff0c;1≤b≤10000。 输出格式 从高位到低位输出幂的末三位数字&#xff0c;中间无分隔符。若幂本身不足三位&#xff0c;在前面补零。 输入输出…

【笔记】Helm-5 Chart模板指南-8 命名模板

命名模板 此时需要越过模板&#xff0c;开始创建其他内容了。该部分我们会看到如何在一个文件中定义 命名模板&#xff0c;并在其他地方使用。命名模板&#xff08;有时称作一个部分或一个子模板&#xff09;仅仅是在文件内部定义的模板&#xff0c;并使用了一个名字。有两种创…

打印斐波那契数列

定义&#xff1a; 斐波那契数列是指这样一个数列&#xff1a;1&#xff0c;1&#xff0c;2&#xff0c;3&#xff0c;5&#xff0c;8&#xff0c;13&#xff0c;21&#xff0c;34&#xff0c;55&#xff0c;89……这个数列从第3项开始 &#xff0c;每一项都等于前两项之和。 …

2402d,d引入新的勾挂降级

原文 我正在试为ArrayLiteralExps添加一个降级模板.它应该调用_d_arrayliteralTX1.我在expressionsem.d中引入了以前的所有降级,并打算通过在此处添加它来同样处理该降级. 但是,ArrayLiteralExps比其他式更挑剔,因为编译器干了许多优化,并最终创建了额外的ArrayLiteralExps或…

各种能源折标准煤参考系数

各种能源折标准煤参考系数Conversion Factors from Physical Units to Coal Equivalent能源名称平均低位发热量折标准煤系数EnergyAverage Low Calorific ValueConversion Factor原煤20 908千焦/(5 000千卡)/千克0.7143千克标准煤/千克Raw Coal20 908 kjoule/(5 000 kcal)/kg0.…

k8s-项目部署案例

一、容器交付流程 在k8s平台部署项目流程 在K8s部署Java网站项目 DockerFile 如果是http访问&#xff0c;需要在镜像仓库配置可信任IP 三、使用工作负载控制器部署镜像 建议至少配置两个标签 一个是声明项目类型的 一个是项目名称的 继续配置属性 资源配额 健康检查 五、使…

GraphicsMagick 的 OpenCL 开发记录(三十四)

文章目录 如何写ScaleImage()的硬件加速函数&#xff08;八&#xff09; <2022-05-05 周四> 如何写ScaleImage()的硬件加速函数&#xff08;八&#xff09; 我觉得Y方向的缩放以下面这种ScaleFilter()的方法是实现不了的&#xff0c;我只能添加进X方向的处理&#xff0…

【集合系列】HashMap 集合

HashMap 集合 1. 概述2. 方法3. 遍历方式4. 代码示例15. 代码示例26. 注意事项 其他集合类 父类 Map 实现类 LinkedHashMap 集合类的遍历方式 具体信息请查看 API 帮助文档 1. 概述 HashMap 是 Java 中的一种集合类&#xff0c;它实现了 Map 接口。HashMap 使用键值对存储数据…

手动汉化unity编辑器,解决下载中文语言报错问题

手动汉化unity编辑器&#xff0c;解决下载中文语言报错问题 START 最近在下载支持微信小程序版本的编辑器时&#xff0c;中文语言包&#xff0c;一直无法下载。记录一下 手动汉化unity编辑器的方法 &#xff0c;帮助和我遇到同样问题的人。 解决方案 1. 下载汉化包 https:…

ubuntu22.04@laptop OpenCV Get Started: 005_rotate_and_translate_image

ubuntu22.04laptop OpenCV Get Started: 005_rotate_and_translate_image 1. 源由2. translate/rotate应用Demo3 translate_image3.1 C应用Demo3.2 Python应用Demo3.3 平移图像过程 4. rotate_image4.1 C应用Demo4.2 Python应用Demo4.3 旋转图像过程 5. 总结6. 参考资料 1. 源由…

unity-ios-解决内购商品在Appstore上面已配置,但在手机测试时却无法显示的问题

自己这几天用 unity 2021 xcode 14.2 开发ios内购&#xff0c;appstore上面内购商品都已经配置好了&#xff0c;但是在手机里就是不显示&#xff0c;最后才发现必需得满足以下条件才行&#xff1a; 1. Appstore后台 -> 内购商品 -> 商品状态必需为『准备提交』以上状态…

springboot/ssm大学生就业服务平台就业招聘宣传管理系统Java系统

springboot(ssm大学生就业服务平台 就业招聘宣传管理系统Java系统 开发语言&#xff1a;Java 框架&#xff1a;springboot&#xff08;可改ssm&#xff09; vue JDK版本&#xff1a;JDK1.8&#xff08;或11&#xff09; 服务器&#xff1a;tomcat 数据库&#xff1a;mysql…

基于 Python 的漏洞扫描系统,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

Web 目录爆破神器:DirBuster 保姆级教程(附链接)

一、介绍 DirBuster 是一个用于强制目录浏览的渗透测试工具&#xff0c;它主要用于在Web应用程序中识别隐藏的目录和文件。这个工具被设计成非常灵活&#xff0c;可以根据用户的需求进行配置。以下是 DirBuster 的一些主要特点和用法&#xff1a; 主要特点&#xff1a; 字典爆…

k8s报错记录(持续更新中....)

k8s报错记录(持续更新中…) 1. 部署k8s遇到kube-flannel已经构建&#xff0c;但是coredns一直处于ContainerCreating和pending状态 解决问题&#xff1a; 通过 kubectl describe pod -n kube-system coredns-7ff77c879f-9ls2b 查看pod的详细信息&#xff0c;报错说是cni 配置没…

主动网络安全:成本效率和危机管理的战略方法

如何面对复杂网络攻击的进攻策略以及零信任模型的作用。攻击后反应性网络安全策略的基本步骤&#xff0c;透明度和准备工作。 讨论采用主动网络安全方法的好处&#xff0c;特别是在成本效率和危机管理方面&#xff0c;进攻性安全测试对合规性和零日响应的影响。 组织应该更多…

Python SimpleHTTPServer - Python HTTP 服务器

Python SimpleHTTPServer Python SimpleHTTPServer 模块是一个非常方便的工具。您可以使用 Python SimpleHTTPServer 将任何目录转换为简单的 HTTP web 服务器。 Python SimpleHTTPServer 仅支持两种 HTTP 方法 - GET 和 HEAD。因此&#xff0c;它是一个很好的工具&#xff0…

周总结2024-02-08

文章目录 周总结&#xff1f;&#xff1f;nono……月总结新年计划 周总结&#xff1f;&#xff1f;nono……月总结 2024年第一个月并没有像之前一样直接写博客发布&#xff0c;其实我是一个及其容易受影响的人&#xff0c;别人提的建议我一般都会在意&#xff0c;主要原因有以…