golang实现简单流畅的定时任务调度插件库gocron的使用

Golang实现简单流畅的定时任务调度插件库gocron的使用

简介

gocron是一个Golang作业调度包,它允许你在预定时间间隔内运行Go函数。

快速开始

首先安装gocron:

go get github.com/go-co-op/gocron/v2

下面是一个基本使用示例:

package main

import (
	"fmt"
	"time"

	"github.com/go-co-op/gocron/v2"
)

func main() {
	// 创建调度器
	s, err := gocron.NewScheduler()
	if err != nil {
		// 处理错误
	}

	// 向调度器添加任务
	j, err := s.NewJob(
		gocron.DurationJob(
			10*time.Second,
		),
		gocron.NewTask(
			func(a string, b int) {
				// 执行任务
				fmt.Printf("任务执行 - 参数a: %s, 参数b: %d\n", a, b)
			},
			"hello",
			1,
		),
	)
	if err != nil {
		// 处理错误
	}
	// 每个任务都有唯一ID
	fmt.Println("任务ID:", j.ID())

	// 启动调度器
	s.Start()

	// 阻塞直到准备关闭
	select {
	case <-time.After(time.Minute):
	}

	// 完成后关闭调度器
	err = s.Shutdown()
	if err != nil {
		// 处理错误
	}
}

核心概念

  • Job(任务):任务封装了一个"task(任务)",由Go函数和任何函数参数组成。然后任务向调度器提供下次应该调度运行的时间。
  • Scheduler(调度器):调度器跟踪所有任务,并在任务准备运行时将其发送给执行器。
  • Executor(执行器):执行器调用任务的任务函数,并管理不同任务执行时序要求的复杂性。

功能特性

任务类型

任务可以在各种时间间隔运行:

  • Duration(固定间隔):任务可以在固定的time.Duration间隔运行。
  • Random duration(随机间隔):任务可以在最小和最大之间的随机time.Duration间隔运行。
  • Cron:任务可以使用crontab运行。
  • Daily(每日):任务可以每隔x天在特定时间运行。
  • Weekly(每周):任务可以每隔x周在每周的特定天数和特定时间运行。
  • Monthly(每月):任务可以每隔x月在每月的特定天数和特定时间运行。
  • One time(一次性):任务可以在特定时间运行(一次或多次)。

并发限制

任务可以单独限制或在整个调度器中限制:

  • 单例模式:任务可以限制为单个并发执行,要么重新调度(跳过重叠的执行),要么排队(等待前一次执行完成)。
  • 限制模式:任务可以限制为在整个调度器中的一定数量的并发执行,使用重新调度(达到限制时跳过)或排队(任务添加到队列以等待限制可用)。

分布式gocron实例

可以运行多个gocron实例:

  • 选举器:可以使用选举器选举单个gocron实例作为主实例运行,其他实例检查是否需要选举新的领导者。
  • :可以使用锁将每个任务的运行锁定到单个gocron实例。

事件

任务事件可以触发操作:

  • 监听器:可以添加到任务中,使用事件监听器,或通过调度器监听所有任务的事件并触发操作。

日志记录

可以启用日志:

  • 可以使用您想要的日志库实现Logger接口。提供的NewLogger使用标准库的log包。

监控

可以从每个任务的执行中收集指标:

  • Monitor(监控器):可以使用监控器从调度器中收集每个任务的指标。

完整示例

下面是一个更完整的示例,展示各种任务类型:

package main

import (
	"fmt"
	"time"

	"github.com/go-co-op/gocron/v2"
)

func main() {
	// 创建调度器
	s, err := gocron.NewScheduler()
	if err != nil {
		panic(err)
	}

	// 固定间隔任务
	_, err = s.NewJob(
		gocron.DurationJob(5*time.Second),
		gocron.NewTask(func() {
			fmt.Println("固定间隔任务执行:", time.Now().Format("15:04:05"))
		}),
	)
	if err != nil {
		panic(err)
	}

	// 随机间隔任务
	_, err = s.NewJob(
		gocron.DurationRandomJob(3*time.Second,7*time.Second),
		gocron.NewTask(func() {
			fmt.Println("随机间隔任务执行:", time.Now().Format("15:04:05"))
		}),
	)
	if err != nil {
		panic(err)
	}

	// Cron表达式任务
	_, err = s.NewJob(
		gocron.CronJob("*/10 * * * * *", false), // 每10秒
		gocron.NewTask(func() {
			fmt.Println("Cron任务执行:", time.Now().Format("15:04:05"))
		}),
	)
	if err != nil {
		panic(err)
	}

	// 启动调度器
	s.Start()

	// 运行5分钟
	time.Sleep(5 * time.Minute)

	// 关闭调度器
	err = s.Shutdown()
	if err != nil {
		panic(err)
	}
}

这个示例展示了gocron的基本用法,包括固定间隔、随机间隔和Cron表达式任务。你可以根据需要扩展这个示例,添加更多功能如并发限制、事件监听等。


更多关于golang实现简单流畅的定时任务调度插件库gocron的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang实现简单流畅的定时任务调度插件库gocron的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


GoCron - 简单流畅的定时任务调度库

GoCron 是一个轻量级的 Golang 定时任务调度库,它提供了简单易用的 API 来安排周期性任务。下面我将详细介绍如何使用 GoCron 实现定时任务调度。

安装

首先安装 GoCron 库:

go get github.com/go-co-op/gocron

基本使用

1. 创建调度器

package main

import (
	"fmt"
	"time"
	
	"github.com/go-co-op/gocron"
)

func main() {
	// 创建调度器实例
	s := gocron.NewScheduler(time.UTC)
	
	// 添加任务
	_, err := s.Every(1).Seconds().Do(task)
	if err != nil {
		panic(err)
	}
	
	// 启动调度器
	s.StartBlocking()
}

func task() {
	fmt.Println("任务执行:", time.Now().Format("2006-01-02 15:04:05"))
}

2. 多种时间间隔设置

// 每5秒执行一次
s.Every(5).Seconds().Do(task)

// 每1分钟执行一次
s.Every(1).Minute().Do(task)

// 每2小时执行一次
s.Every(2).Hours().Do(task)

// 每天执行一次
s.Every(1).Day().Do(task)

// 每周一执行
s.Every(1).Monday().Do(task)

// 每月1号执行
s.Every(1).Month(1).Do(task)

3. 指定具体时间执行

// 每天10:30执行
s.Every(1).Day().At("10:30").Do(task)

// 每周一10:30执行
s.Every(1).Monday().At("10:30").Do(task)

// 每月1号10:30执行
s.Every(1).Month(1).At("10:30").Do(task)

高级功能

1. 带参数的任务

func greet(name string) {
	fmt.Printf("Hello, %s! Time: %s\n", name, time.Now().Format("15:04:05"))
}

func main() {
	s := gocron.NewScheduler(time.UTC)
	
	// 传递参数给任务
	_, err := s.Every(2).Seconds().Do(greet, "Alice")
	if err != nil {
		panic(err)
	}
	
	s.StartBlocking()
}

2. 任务标签与移除任务

func main() {
	s := gocron.NewScheduler(time.UTC)
	
	// 添加带标签的任务
	_, err := s.Every(1).Second().Tag("task1").Do(task)
	if err != nil {
		panic(err)
	}
	
	// 5秒后移除任务
	time.AfterFunc(5*time.Second, func() {
		err := s.RemoveByTag("task1")
		if err != nil {
			fmt.Println("移除任务失败:", err)
		} else {
			fmt.Println("任务已移除")
		}
	})
	
	s.StartBlocking()
}

3. 单例模式(防止任务重叠)

func main() {
	s := gocron.NewScheduler(time.UTC)
	
	// 设置单例模式 - 如果前一个任务还在运行,则跳过本次执行
	_, err := s.Every(1).Second().SingletonMode().Do(longRunningTask)
	if err != nil {
		panic(err)
	}
	
	s.StartBlocking()
}

func longRunningTask() {
	fmt.Println("长任务开始:", time.Now().Format("15:04:05"))
	time.Sleep(3 * time.Second)
	fmt.Println("长任务结束:", time.Now().Format("15:04:05"))
}

4. 并发限制

func main() {
	s := gocron.NewScheduler(time.UTC)
	
	// 设置最大并发任务数为2
	s.SetMaxConcurrentJobs(2, gocron.RescheduleMode)
	
	// 添加多个任务
	for i := 0; i < 5; i++ {
		_, err := s.Every(1).Second().Do(taskWithID, i)
		if err != nil {
			panic(err)
		}
	}
	
	s.StartBlocking()
}

func taskWithID(id int) {
	fmt.Printf("任务 %d 开始: %s\n", id, time.Now().Format("15:04:05"))
	time.Sleep(3 * time.Second)
	fmt.Printf("任务 %d 结束: %s\n", id, time.Now().Format("15:04:05"))
}

5. Cron 表达式支持

func main() {
	s := gocron.NewScheduler(time.UTC)
	
	// 使用标准cron表达式
	_, err := s.Cron("*/5 * * * *").Do(task) // 每5分钟执行一次
	if err != nil {
		panic(err)
	}
	
	s.StartBlocking()
}

实际应用示例

package main

import (
	"fmt"
	"time"
	
	"github.com/go-co-op/gocron"
)

func main() {
	// 创建调度器
	scheduler := gocron.NewScheduler(time.UTC)
	
	// 添加多个任务
	_, _ = scheduler.Every(5).Seconds().Do(monitorSystem)
	_, _ = scheduler.Every(1).Hour().Do(cleanTempFiles)
	_, _ = scheduler.Every(1).Day().At("02:00").Do(backupDatabase)
	
	// 启动调度器
	fmt.Println("定时任务调度器启动...")
	scheduler.StartBlocking()
}

func monitorSystem() {
	fmt.Printf("[%s] 监控系统状态...\n", time.Now().Format("2006-01-02 15:04:05"))
	// 实际监控逻辑...
}

func cleanTempFiles() {
	fmt.Printf("[%s] 清理临时文件...\n", time.Now().Format("2006-01-02 15:04:05"))
	// 实际清理逻辑...
}

func backupDatabase() {
	fmt.Printf("[%s] 数据库备份开始...\n", time.Now().Format("2006-01-02 15:04:05"))
	// 实际备份逻辑...
	time.Sleep(10 * time.Second) // 模拟耗时操作
	fmt.Printf("[%s] 数据库备份完成\n", time.Now().Format("2006-01-02 15:04:05"))
}

注意事项

  1. 默认情况下,GoCron 使用 UTC 时区,可以通过 NewScheduler 指定本地时区
  2. 长时间运行的任务可能会影响调度精度,考虑使用单例模式
  3. 在生产环境中,建议添加适当的错误处理和恢复机制
  4. 对于分布式系统,需要考虑分布式锁机制

GoCron 是一个简单但功能强大的定时任务调度库,适合大多数定时任务场景。对于更复杂的需求,可以考虑结合其他工具如消息队列或专门的作业调度系统。

回到顶部