goCron源码阅读

goCron是一个go程序调度包,通过简单的语法即可让程序在按照指定时间间隔运行。

简介

源码地址

https://github.com/jasonlvhit/gocron

使用场景

  • 单机定时任务
  • 分布式定时任务

使用demo

package main

import (
    "fmt"
    "time"

    "github.com/jasonlvhit/gocron"
)

func task() {
    fmt.Println("I am running task.")
}

func taskWithParams(a int, b string) {
    fmt.Println(a, b)
}

func main() {
    // Do jobs without params
    gocron.Every(1).Second().Do(task)
    gocron.Every(2).Seconds().Do(task)
    gocron.Every(1).Minute().Do(task)
    gocron.Every(2).Minutes().Do(task)
    gocron.Every(1).Hour().Do(task)
    gocron.Every(2).Hours().Do(task)
    gocron.Every(1).Day().Do(task)
    gocron.Every(2).Days().Do(task)
    gocron.Every(1).Week().Do(task)
    gocron.Every(2).Weeks().Do(task)

    // Do jobs with params
    gocron.Every(1).Second().Do(taskWithParams, 1, "hello")

    // Do jobs on specific weekday
    gocron.Every(1).Monday().Do(task)
    gocron.Every(1).Thursday().Do(task)

    // Do a job at a specific time - 'hour:min:sec' - seconds optional
    gocron.Every(1).Day().At("10:30").Do(task)
    gocron.Every(1).Monday().At("18:30").Do(task)
    gocron.Every(1).Tuesday().At("18:30:59").Do(task)

    // Begin job immediately upon start
    gocron.Every(1).Hour().From(gocron.NextTick()).Do(task)

    // Begin job at a specific date/time
    t := time.Date(2019, time.November, 10, 15, 0, 0, 0, time.Local)
    gocron.Every(1).Hour().From(&t).Do(task)

    // NextRun gets the next running time
    _, time := gocron.NextRun()
    fmt.Println(time)

    // Remove a specific job
    gocron.Remove(task)

    // Clear all scheduled jobs
    gocron.Clear()

    // Start all the pending jobs
    <- gocron.Start()

    // also, you can create a new scheduler
    // to run two schedulers concurrently
    s := gocron.NewScheduler()
    s.Every(3).Seconds().Do(task)
    <- s.Start()
}

代码阅读

主要包含两个结构体Scheduler和Job. Job为需要执行的任务,详细结构如下:

Job

// Job struct keeping information about job
type Job struct {
    interval uint64                   // pause interval * unit between runs
    jobFunc  string                   // the job jobFunc to run, func[jobFunc]
    unit     timeUnit                 // time units, ,e.g. 'minutes', 'hours'...
    atTime   time.Duration            // optional time at which this job runs
    err      error                    // error related to job
    loc      *time.Location           // optional timezone that the atTime is in
    lastRun  time.Time                // datetime of last run
    nextRun  time.Time                // datetime of next run
    startDay time.Weekday             // Specific day of the week to start on
    funcs    map[string]interface{}   // Map for the function task store
    fparams  map[string][]interface{} // Map for function and  params of function
    lock     bool                     // lock the job from running at same time form multiple instances
    tags     []string                 // allow the user to tag jobs with certain labels
}

参数解释:

  • interval、unit: 两个参数共同决定了job两次执行的时间间隔interval*unit
  • jobFunc: job函数名称
  • atTime: job第一次运行时刻, 需要注意的是只有unit为days、weeks才生效, unit为seconds、minustes、hours时可以使用From方法设置nextRun来设置第一次运行时间.
  • loc: 时区
  • lastRun: 上次Job执行日期
  • nextRun: 下次Job执行日期
  • startDay: unit为days时生效, 周几开始执行Job
  • funcs: 存储执行函数
  • fparams: 执行函数所需要的参数
  • lock: 相同任务不允许同时执行时设置lock=true, 包含单机和分布式, 分布式时使用分布式锁即可
  • tags: 给任务添加标签

Scheduler

// Scheduler struct, the only data member is the list of jobs.
// - implements the sort.Interface{} for sorting jobs, by the time nextRun
type Scheduler struct {
    jobs [MAXJOBNUM]*Job // Array store jobs
    size int             // Size of jobs which jobs holding.
    loc  *time.Location  // Location to use when scheduling jobs with specified times
}

参数解释:

  • jobs: 存储Job的数组
  • size: 存储的Job个数
  • loc: 时区

方法介绍:

  • NewScheduler: 创建调度器
  • Start: 开启调度器

调度策略

调用start后, scheduler启动一个goroutine, goroutine中开启一个秒级别定时器, 每秒钟遍历检查一次jobs, 选择出可以执行的job之后,对每个需要执行的job各自开辟新的goroutine执行. 选择job方法为:

  • 按照job的nextRun排序
  • 遍历排序后的jobs数组

你可能感兴趣的:(goCron源码阅读)