全栈直通车-王世彪的博客
关注公众号
  • 开发桌面程序
  • javascript教程
  • css样式
  • vuejs
  • 部署免费CDN
  • SEO搜索引擎优化
  • vuepress教程
  • redis分布式缓存
  • Golang
  • PHP
  • Python
  • Java
  • NodeJs
  • tomcat
  • ELK
  • Mysql数据库
  • Nosql数据库
  • C/C++底层开发
  • 音视频/流媒体
  • linux服务器
  • nginx服务器
  • 容器技术
  • 负载均衡
  • 项目管理
  • 持续集成
  • 大数据
  • 微信公众号运营
  • markdown用法
赞一个
友链
联系作者

王世彪

努力做个影响他人滴人
关注公众号
  • 开发桌面程序
  • javascript教程
  • css样式
  • vuejs
  • 部署免费CDN
  • SEO搜索引擎优化
  • vuepress教程
  • redis分布式缓存
  • Golang
  • PHP
  • Python
  • Java
  • NodeJs
  • tomcat
  • ELK
  • Mysql数据库
  • Nosql数据库
  • C/C++底层开发
  • 音视频/流媒体
  • linux服务器
  • nginx服务器
  • 容器技术
  • 负载均衡
  • 项目管理
  • 持续集成
  • 大数据
  • 微信公众号运营
  • markdown用法
赞一个
友链
联系作者
  • 分布式缓存

  • 分布式存储

  • mysql

  • postgresql

  • mongodb

  • c或c++

  • golang

    • 环境配置

    • 基础

      • golang基于雪花算法生成分布式ID
      • golang常见的语法错误
      • golang自动生成struct json tag
      • golang逐行读取文本文件
      • golang定时任务
        • 1. 封装 1 个通用的定时任务处理文件
        • 2. 初始化
        • 3. 创建定时任务
        • 4 参考资料
      • golang json转struct在线工具
      • golang生成pretty格式的json
    • 单元测试

    • 后台管理脚手架

    • web框架gin

    • web框架echo

    • web框架GoFrame

    • 微服务框架go-micro

    • 微服务

    • 接口管理

    • orm框架gorm

    • go-zero

    • 开源论坛

    • 爬虫

  • php

  • java

  • nodejs

  • python

  • tomcat

  • elk

  • 音视频流媒体

  • 后台
  • golang
  • 基础
王世彪
2021-01-06

golang定时任务

# golang 定时任务

本文讲述 golang 中如何管理定时任务。原生的定时任务功能不好用也不强大,这里推荐 github.com/rfyiamcool/cronlib,该库支持动态添加、修改、删除定时任务,最具特色的功能是可以为每个定时任务指定唯一的标识 ID,该功能很实用,然而在当前最火的定时任务库 github.com/robfig/cron 上却没有(实际上 cronlib 就是基于 robfig 开发的)。所以本文强烈推荐 github.com/rfyiamcool/cronlib。

# 1. 封装 1 个通用的定时任务处理文件

为了方便调用,创建一个 cron_task.go 文件,里面封装了通用的定时任务处理逻辑。

package cron

import (
	"apiproject/config"
	"apiproject/log"
	"errors"

	"github.com/rfyiamcool/cronlib"
	"go.uber.org/zap"
)

type CallbackTask func(paraMap *map[string]interface{})

var MyCronSchduler *cronlib.CronSchduler

/**
启动定时任务列表
*/
func Init() {
	//任务开关是否开启
	if !config.GlobalConfig.TaskSwitchOn {
		log.Logger.Info("启动定时任务列表, 任务开关没有开启")
		return
	}

	MyCronSchduler = cronlib.New()
	MyCronSchduler.Start()
}

/**
注册定时任务
*/
func RegisterTask(jobName string, jobSpec string,
	callbackTask CallbackTask, callbackParaMap *map[string]interface{}) error {
	//检测定时任务是否已存在
	if IsExistTask(jobName) {
		log.Logger.Error("注册定时任务, 定时任务已存在", zap.Any("jobName", jobName))
		return errors.New("定时任务已存在")
	}

	//创建定时任务
	job, err := cronlib.NewJobModel(
		jobSpec,
		func() {
			log.Logger.Info("定时任务开始执行", zap.Any("jobName", jobName), zap.Any("jobSpec", jobSpec))
			callbackTask(callbackParaMap)
			log.Logger.Info("定时任务执行完成", zap.Any("jobName", jobName), zap.Any("jobSpec", jobSpec))
		},
	)
	if err != nil {
		return err
	}

	//注册定时任务
	err = MyCronSchduler.DynamicRegister(jobName, job)
	if err != nil {
		return err
	}

	log.Logger.Info("注册定时任务", zap.String("jobName", jobName), zap.String("jobSpec", jobSpec))
	return nil
}

/**
更新定时任务
*/
func UpdateTask(jobName string, jobSpec string,
	callbackTask CallbackTask, callbackParaMap *map[string]interface{}) error {
	//创建定时任务
	job, err := cronlib.NewJobModel(
		jobSpec,
		func() {
			log.Logger.Info("定时任务开始执行", zap.Any("jobName", jobName), zap.Any("jobSpec", jobSpec))
			callbackTask(callbackParaMap)
			log.Logger.Info("定时任务执行完成", zap.Any("jobName", jobName), zap.Any("jobSpec", jobSpec))
		},
	)
	if err != nil {
		return err
	}

	//更新定时任务
	err = MyCronSchduler.UpdateJobModel(jobName, job)
	if err != nil {
		return err
	}

	log.Logger.Info("更新定时任务", zap.String("jobName", jobName), zap.String("jobSpec", jobSpec))
	return nil
}

/**
反注册定时任务
*/
func UnRegisterTask(jobName string) error {
	if err := MyCronSchduler.UnRegister(jobName); err != nil {
		log.Logger.Error("反注册定时任务, 失败", zap.Any("jobName", jobName), zap.Error(err))
		return err
	}

	return nil
}

/**
是否存在某定时任务
*/
func IsExistTask(jobName string) bool {
	_, err := MyCronSchduler.GetServiceCron(jobName)
	log.Logger.Info("是否存在某定时任务", zap.Any("jobName", jobName), zap.Any("exist", err == nil))

	return err == nil
}

说明:

  • Init函数 需要在应用启动时手动调用该函数,完成全局定时任务管理器的初始化。
  • 定时任务的属性
    可以指定定时任务的 ID、定时表达式、回调函数、传给回调函数的参数。

# 2. 初始化

系统启动时, 调用前文的 Init 方法, 完成全局定时任务管理器的初始化。

# 3. 创建定时任务

此处提供 2 个例子。

# 3.1 例 1

	err := cron.RegisterTask("爬取新闻数据", config.GlobalConfig.TaskCrawnewslistCron, s_spider.SpiderService.CrawNewsListTask, nil)
	if err != nil {
		panic(err)
	}

# 3.2 例 2

/**
注册重访上线定时任务
*/
func (this *revisitService) registerRevisitOnlineTask(distributor *m_distributor.Distributor) error {
	jobName := this.getRevisitOnlineJobName(distributor.ID)
	paraMap := map[string]interface{}{}
	paraMap["did"] = distributor.ID

	//反注册
	if cron.IsExistTask(this.getRevisitOnlineJobName(distributor.ID)) {
		if err := cron.UnRegisterTask(this.getRevisitOnlineJobName(distributor.ID)); err != nil {
			log.Logger.Error("注册重访上线定时任务, 反注册失败", zap.Any("did", distributor.ID), zap.Error(err))
			return errors.New("反注册失败")
		}
		log.Logger.Info("注册重访上线定时任务, 当前任务已存在", zap.Any("did", distributor.ID))
	}

	//注册
	if distributor.RevisitOnlineTime != "" {
		if err := cron.RegisterTask(jobName, distributor.RevisitOnlineTime, this.RevisitOnlineTaskCallback, &paraMap); err != nil {
			log.Logger.Error("注册重访上线定时任务, 失败", zap.Any("jobName", jobName), zap.Any("did", distributor.ID), zap.Error(err))
			return err
		}
		log.Logger.Info("注册重访上线定时任务, 完成", zap.Any("distributor", distributor))
	}

	return nil
}

# 4 参考资料

详细用法详见cronlib 的官网 (opens new window)
cronlib 是基于robfig (opens new window)开发而来。robfig 是最火的定时任务库,但是我觉得封装之后的 cronlib 变得更好用。

#golang#定时任务
上次更新: 2021-03-24 18:12:06
golang逐行读取文本文件
golang json转struct在线工具

← golang逐行读取文本文件 golang json转struct在线工具→

最近更新
01
mysql创建用户
04-09
02
golang错误处理最佳实践
03-17
03
基于proto文件生成rpc接口定义文档
03-11
更多文章>
Theme by Vdoing | Copyright © 2019-2022 王世彪 | MIT License
冀ICP备19016776号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式