golang 实现定时任务
在实际开发过程中,我们有时候需要编写一些定时任务。当然我们可以使用crontab命令实现我们的需求。但是这种方法不满足一些定制化场景,同时会依赖具体的操作系统环境。
定时任务
在golang中我们可以使用cron来实现我们定时任务的需求。他的使用方式非常简单,具体代码如下:
package main
import(
"fmt"
cron "github.com/robfig/cron/v3"
)
func main() {
crontab := cron.New()
task := func() {
fmt.Println("hello world")
}
// 添加定时任务, * * * * * 是 crontab,表示每分钟执行一次
crontab.AddFunc("* * * * *", task)
// 启动定时器
crontab.Start()
// 定时任务是另起协程执行的,这里使用 select 简答阻塞.实际开发中需要
// 根据实际情况进行控制
select {}
}
注:
- New()函数支持多种初始化选项,比如
cron.WithPanicLogger - 定时任务是另起协程执行的
上面就是 cron 的最简单使用示例,如果需要了解更加详细的用法,可以参考官方文档和示例。
自定义封装
在上述的使用方法基础上,基于我的实际需求,我对cron库进行了简单封装,主要为实现下面几个需求:
- 管理所有的定时任务,需要记录定时任务的编号和相关信息
- 停止一个定时任务
- 支持添加函数类型和接口类型任务
话不多说,直接贴代码:
package main
import (
"fmt"
"sync"
"github.com/pkg/errors"
cron "github.com/robfig/cron/v3"
)
// Crontab crontab manager
type Crontab struct {
inner *cron.Cron
ids map[string]cron.EntryID
mutex sync.Mutex
}
// NewCrontab new crontab
func NewCrontab() *Crontab {
return &Crontab{
inner: cron.New(),
ids: make(map[string]cron.EntryID),
}
}
// IDs ...
func (c *Crontab) IDs() []string {
c.mutex.Lock()
defer c.mutex.Unlock()
validIDs := make([]string, 0, len(c.ids))
invalidIDs := make([]string, 0)
for sid, eid := range c.ids {
if e := c.inner.Entry(eid); e.ID != eid {
invalidIDs = append(invalidIDs, sid)
continue
}
validIDs = append(validIDs, sid)
}
for _, id := range invalidIDs {
delete(c.ids, id)
}
return validIDs
}
// Start start the crontab engine
func (c *Crontab) Start() {
c.inner.Start()
}
// Stop stop the crontab engine
func (c *Crontab) Stop() {
c.inner.Stop()
}
// DelByID remove one crontab task
func (c *Crontab) DelByID(id string) {
c.mutex.Lock()
defer c.mutex.Unlock()
eid, ok := c.ids[id]
if !ok {
return
}
c.inner.Remove(eid)
delete(c.ids, id)
}
// AddByID add one crontab task
// id is unique
// spec is the crontab expression
func (c *Crontab) AddByID(id string, spec string, cmd cron.Job) error {
c.mutex.Lock()
defer c.mutex.Unlock()
if _, ok := c.ids[id]; ok {
return errors.Errorf("crontab id exists")
}
eid, err := c.inner.AddJob(spec, cmd)
if err != nil {
return err
}
c.ids[id] = eid
return nil
}
// AddByFunc add function as crontab task
func (c *Crontab) AddByFunc(id string, spec string, f func()) error {
c.mutex.Lock()
defer c.mutex.Unlock()
if _, ok := c.ids[id]; ok {
return errors.Errorf("crontab id exists")
}
eid, err := c.inner.AddFunc(spec, f)
if err != nil {
return err
}
c.ids[id] = eid
return nil
}
// IsExists check the crontab task whether existed with job id
func (c *Crontab) IsExists(jid string) bool {
_, exist := c.ids[jid]
return exist
}
代码实现很简单,每个函数的作用都可以参考注释.下面简单实用一下上面的封装:
type testTask struct {
}
func (t *testTask) Run() {
fmt.Println("hello world")
}
func main() {
crontab := NewCrontab()
// 实现接口的方式添加定时任务
task := &testTask{}
if err := crontab.AddByID("1", "* * * * *", task); err != nil {
fmt.Printf("error to add crontab task:%s", err)
os.Exit(-1)
}
// 添加函数作为定时任务
taskFunc := func() {
fmt.Println("hello world")
}
if err := crontab.AddByFunc("2", "* * * * *", taskFunc); err != nil {
fmt.Printf("error to add crontab task:%s", err)
os.Exit(-1)
}
crontab.Start()
select {}
}
注:
- task id 是唯一的,实际开发可以使用 uuid
- 这个封装是并发安全的
不足:
- 未支持初始化参数
- 定时任务的错误采集,如果某个定时任务出错,应该能够获取到错误信息(这里指的是错误不是 panic)
- panic 恢复操作可以参考
withChain和cron.Recover
后记
下一篇详细解析 cron 的实现原理和更加复杂的用法
golang 实现定时任务的更多相关文章
- golang的定时任务
golang的定时任务使用的是cron这个包来解决的 官方文档地址:https://godoc.org/github.com/robfig/cron cron包的基础知识 字段名 是否必须 允许的值 ...
- golang cronexpr定时任务包使用
包获取 go get -u github.com/gorhill/cronexpr 创建一个定时任务 expr, err = cron.Parse("* * * * *"); 获得 ...
- Golang cron 定时任务使用
1.cron 表达式的基本格式 用过 linux 的应该对 cron 有所了解.linux 中可以通过 crontab -e 来配置定时任务.不过,linux 中的 cron 只能精确到分钟.而我们这 ...
- Golang——Cron 定时任务
开门见山写一个 package main import ( "fmt" "github.com/robfig/cron" "log" &qu ...
- cron表达式的双重人格:星期和数字到底如何对应?
写在前面 cron在希腊语中是时间的意思,而cron表达式(cron expression)则是遵循特定规则,用于描述定时设置的字符串,常用于执行定时任务.本文总结了不同环境(如平台.库等)下,cro ...
- Golang 入门系列(八) cron定时任务
1.cron 表达式的基本格式 Go 实现的cron 表达式的基本语法跟linux 中的 crontab基本是类似的.cron(计划任务),就是按照约定的时间,定时的执行特定的任务(job).cro ...
- Golang定时任务简单实现
下载cron包: go get github.com/robfig/cron 开启一个定时: 根据cron表达式进行时间调度,cron可以精确到秒,大部分表达式格式也是从秒开始. c := cron. ...
- Go 定时任务
本文基于Golang Crontab 实现了一个Crontab Job Manager.更加容易使用,同时也能够满足更加复杂的场景. 仓储地址, 如果有用,欢迎点赞,欢迎讨论,欢迎找茬. 需求 在开发 ...
- Golang mysql 上线的一个坑 Db.close重要性
急冲冲完成的mysql的一个监控自动处理程序上线了,线下处理是正常的,没想到线上才半小时就奔溃了. 现在时间是晚上11点,心慌焦虑涌上心头,需要熬夜?肾上腺素激增. 程序主要是一个定时任务的处理程序, ...
随机推荐
- 前端微信小程序仿菜谱精灵
需求描述及交互分析 设计思路和相关知识点 底部标签导航设计 幻灯片轮播效果设计 菜谱专题列表显示设计 菜谱专题详情设计 菜谱分类设计 幻灯片轮播效果动态切换展示一些美食图片 若本号内容有做得不到位的地 ...
- 前端base64加密
一.Base64编码表 码值 字符 码值 字符 码值 字符 码值 字符 0 A 16 Q 32 g 48 w 1 B 17 R 33 h 49 x 2 C 18 S 34 i 50 y 3 D 19 ...
- XMind配置防火墙
1.打开控制面板,找到防火墙 2. 启用Windows防火墙 3.高级设置,新建入站规则 配置部分一律“下一步”. XMind配置防火墙完成.如果还不行,相同方式设置出站规则.
- CFD-Post批量添加截面
有时候我们需要在一个算例中截取多个面 我们打开CFD-Post 我们编写如下的Python代码来实现在一个算例当中截取多个面 源代码如下: 上述代码完成以后,我们重新打开CFD-Post
- 解决PHP7无法监听9000端口问题/502错误解决办法
问题背景 昨晚帮配置nginx+php服务的时候,发生了一个奇怪的事情netstat -anp|grep 9000查看9000端口,一直没有监听,于是nginx无法通过fastcgi来代理php请求. ...
- 【转】vue中样式被覆盖的问题,vue中的style不生效
转载:http://www.cnblogs.com/shangjun6/p/11416054.html 在我们引入外部的样式时,发现自己无论如何都改不了外部的样式,自己的样式老被覆盖,究其原因还是我们 ...
- bat批处理 取得当前路径 %CD%
在DOS的批处理中,有时候需要知道当前的路径.在DOS中,有两个环境变量可以跟当前路径有关,一个是%cd%, 一个是%~dp0. 这两个变量的用法和代表的内容一般是不同的. 1. %cd% 可以用在批 ...
- c#怎么解决System.UnauthorizedAccessException异常
https://blog.csdn.net/qq_38061677/article/details/81157116 代码: using System;namespace Project2048{ c ...
- odoo开发笔记--定时任务源码分析
场景描述: 处理思路: 参考文章: 定时任务相关: https://www.jianshu.com/p/ad48239f84d6 https://blog.csdn.net/M0relia/artic ...
- ASP程序加密/解密方法大揭密
如今,用ASP技术构建的网站随处可见.由于ASP脚本是在服务器上解释执行的(无法编译),因此你辛苦开发出来的ASP代码,很容易被人拷去任意修改,如何保护ASP源代码呢?这是每个ASP站长都会遇到的 ...