Golang 完成一个 Crontab定时器(1)

前言

Linux的Crontab定时器似乎已经足够强大,但是我认为还是没有办法满足我们所有的需求,例如定时器某一瞬间需要动态添加/删除任务的功能,例如定时器只能在指定的节点上启动(主节点),其他节点不需要定时服务,这种情况Linux自带的Crontab就不能够满足我们的需求了,所以这次要徒手定义一个Crontab定时器,作为自己的备用。

需求分析

看我博客的基本也都知道,做任何事,都要进行一个需求分析。既然是一个定时器,那么应该支持的功能如下

  1. 定时启动任务(废话)
  2. 支持基础的Crontab语法
  3. 支持将时间转换为Crontab语法
  4. 支持Crontab语法校验
  5. 记录日志的功能
  6. 支持crontab任务到秒级

综合上面的需求,不难看出,其实最重要的功能就是实现一个定时启动任务的玩意儿,在Go开发当中,也就是在某个时间点执行某个Go函数。说的简单点,就是,定时跑Go函数。也就是定时go func而已。

robfig/cron 包的使用

安装robfig/cron包

我这里默认你们都有go 基础,先安装个包,这玩意儿是驱动Golang 驱动 Crontab的重要框架。

go get github.com/robfig/cron

robfig/cron的使用举例

启动一个定时任务其实很简单

job := cron.New()
job.AddFunc("* * * * *", func() {fmt.Println("Start job....")})
job.Start()

一个定时任务就这样被写好了,其实仔细琢磨一下,添加任务的方式就是

// 新任务
job := cron.New()
///任务添加
job.AddFunc("Cronta 语句", func() {执行函数()})
//任务开始
job.Start()

这样就完成了一个定时任务的添加

支持crontab任务到秒级

估计你们看到这里一脸懵逼,为啥你个单独到秒级的也要整出来呢?其实我也表示,我也不想啊!奈何一点,robfig/cron这玩意有个很奇葩的一点,它只支持的分钟级别的任务,不支持到秒级别!!!!它只支持的分钟级别的任务,不支持到秒级别!!!!它只支持的分钟级别的任务,不支持到秒级别!!!!,重要的事儿说三遍!这里需要你自己定义秒级别的任务,在翻了一下它的test源码之后,拉到最底下,看到这么一行代码。

// newWithSeconds returns a Cron with the seconds field enabled.
func newWithSeconds() *Cron {
    return New(WithParser(secondParser), WithChain())
}

这行代码啥意思呢,意思就是启用返回seconds字段的任务,说白了就是,你要加这个,才能开启秒级别的任务
网上好多博客写的,都是你抄我,我抄你,抄来抄去,没一个代码能用的,大家如果发现抄网上那帮人的代码,跑不起来,那绝对就是这个原因!人家只支持到分钟,网上给出的例子全都是秒级别的,并且没打开秒级别任务定义,还能跑起来?我都怀疑你们怎么写的代码。
定义秒级别任务代码
这段代码主要的意思就是,开放到秒级别的任务支持,看到了second么,这段代码在源码包的test下有,你们可以自己去看看。

func newWithSeconds() *cron.Cron {
    secondParser := cron.NewParser(cron.Second | cron.Minute |
        cron.Hour | cron.Dom | cron.Month | cron.DowOptional | cron.Descriptor)
    return cron.New(cron.WithParser(secondParser), cron.WithChain())
}
func main() {
    // 使用秒级别任务
    job := newWithSeconds()
    // 任务定义,3s输出一个j1 start job,不停循环
    job.AddFunc("0/3 * * * * ? ", func() {
        fmt.Println("j1 start job....", time.Now().Format("2020-03-20 15:04:05"))
    })
    // 任务定义,每分钟的第三秒执行任务
    job.AddFunc("3 * * * * ? ", func() {
        fmt.Println("j2 start job....", time.Now().Format("2020-03-20 15:04:05"))
    })
    //开始任务
    job.Start()
    select {}
}

输出的结果

j1 start job.... 2020-03-21 17:09:36
j1 start job.... 2020-03-21 17:09:39
j1 start job.... 2020-03-21 17:09:42
j1 start job.... 2020-03-21 17:09:45

总结

初步完成了crontab的基础功能,这篇文章默认,你们都比较懂crontab语法和go开发了,如果不懂就请期待下一篇,实现crontab语法自动生成和自动加载任务吧。

原文地址:https://www.cnblogs.com/Yemilice/p/12540258.html

时间: 2024-09-29 16:31:30

Golang 完成一个 Crontab定时器(1)的相关文章

写的一个简单定时器(非独立线程)

//Callback.h #ifndef __CALLBACK_H__ #define __CALLBACK_H__ typedef void (*T_CallBack)(void *); typedef struct { T_CallBack cb; void *obj; }ST_CallBack; int __NewTimer(void* obj, int interval, bool isloop, T_CallBack cb); void __DeleteTimer(int handle

我的第一个java定时器

在开发中,我们经常需要一些周期性的操作,例如每隔几分钟就进行某一项操作.这时候我们就要去设置个定时, 接下来就去开发我的第一个java定时器吧,Java计时器实用程序允许您执行线程或任务在一个预先确定的将来的时间,并根据一组这些任务可以重复频率. 设计和实现一个计时器,会用到model-control-view(MVC)设计模式. 开始: 首先来构w建一个最简单的java web 项目吧.这里我用的是最myeclipse,好处自然不必多说,谁用谁知道,当然如果 你要用其他IDE也可以. 在mye

为什么STM32同时开启2个通用定时器,TIM2和TIM3,其中有一个TIM3定时器进不了中断。

TIM2和TIM3配置一样,NVIC优先级设置不同. 原来的: int main(void){   sys_init(); systick_config(); TIM3_init(); TIM2_init(); } 解决方法是:修改了mian程序中: int main(void) { sys_init(); systick_config(); TIM2_init(); TIM3_init(); } 为什么只调换了TIM2和TIM3的初始化程序就可以了呢?好奇怪. 为什么STM32同时开启2个通用

go的变量redeclare的问题,golang的一个小坑

go的变量声明有几种方式: 1 通过关键字 var 进行声明 例如:var i int   然后进行赋值操作 i = 5 2 最简单的,通过符号 := 进行声明和赋值 例如: i:=5 golang会默认它的类型 下面看一段代码,我们先声明一个变量a,然后再重新声明变量a,b,在这个函数中,变量a被声明了2次,成为a的重声明(redeclare),执行结果为23 package main import ( "fmt" ) func main(){ a:=1 a,b:=2,3 fmt.P

golang 高效低精度定时器实现

golang默认定时器是通过time模块提供的,不管是golang,libev,libevent也好,定时器都是通过最小堆实现的,导致加入定时器时间复杂度为O(lgn),在需要大量定时器时效率较低,所以Linux提供了基于时间轮的实现,我们本次提供的 定时器实现就是标准的Linux时间轮实现方式.当然,我是把Skynet(https://github.com/cloudwu/skynet/blob/master/skynet-src/skynet_timer.c)的定时器移植了过来,偷窃无罪..

GoWorld – 用Golang写一个分布式可扩展、可热更的游戏服务器

GoWorld代码:https://github.com/xiaonanln/goworld Golang具有运行效率高.内存安全等优良特性,因此是非常适合用来进行服务器开发.使用Golang开发游戏服务器有如下的优点: 运行效率远高于各种脚本语言,大幅度提升服务器承载能力 内存安全,不会像C++服务器那样出现内存错误导致服务器down机 Goroutine能够很好地利用多核计算能力,提升承载能力 Golang本身非常简单好用,大家都喜欢 然而使用Golang编写游戏服务器也面临一定的困难,主要

使用boost的deadline_timer实现一个异步定时器

概述 最近在工作上需要用到定时器,然后看到boost里面的deadline_timer可以实现一个定时器,所以就直接将其封装成了ATimer类,方便使用,ATimer有以下优点: 可以支持纳秒.毫秒.秒.分.小时定时. 可以随时停止定时器. 支持单次调用. 因为使用了deadline_timer,所以定时比较准确. ATimer和Qt的QTimer使用方法类似,若没有类似的Timer类,使用最原始的方法,我们的代码可能会是这样的: m_timerThread = std::thread([thi

crontab 定时器

cronntab 定时器 crontab -e 编辑定时器 crontab -l 查看定时器 //每十分钟执行一次 */10 * * * * curl http://xxxxx //每天 凌晨 中午12点执行一次 0 0,12 * * * curl http://xxxxx 分 时 日 月 周 命令 第1列表示分钟1-59 每分钟用*或者 */1表示 第2列表示小时1-23(0表示0点) 第3列表示日期1-31 第4列 表示月份1-12 第5列标识号星期0-6(0表示星期天) 第6列要运行的命令

使用Golang开发一个本地代理

引言 最近需要对接一个接口,人家提供了两种调用方式,第一种是基于IE浏览器的Active,第二种是动态链接库dll.我们公司的产品不支持IE,所以只能通过调用dll来完成了. 之前我已经用Java实现了这个代理,但是感觉很笨重,依赖于容器还有JVM一大堆,这个代理要安装在客户端电脑上,基于Http协议来调用,然后透传参数调用dll,将返回的结果转换为Json. 如今我想用Golang来实现这个功能,它不依赖特定的运行环境,而且天然高并发,适合做网络通信相关,结合了Java的高效和C的高性能. 一