go-zero中定时任务的用法

news/2025/2/26 19:35:23

文章目录

  • 使用扩展
  • 定义调度器
  • 测试方法

使用扩展

在go-zero框架中使用定时任务调度的写法示例,首先需要用到的扩展:go get -u github.com/robfig/cron/v3

扩展网址:robfig/cron: a cron library for go (github.com)

定义调度器

gozero/internal 目录下新建 crontab目录,然后首先需要创建一个配置文件:gozero/internal/crontab/config.go ,在这里我写上两个示例的定时任务,分别为“20秒打印一次SayHello”,以及“每一分钟查询一次当前用户总数”:

package crontab

type TaskConfig struct {
	Name      string `json:"name"`      //任务名称
	Scheduler string `json:"scheduler"` //@every表达式中的单位可以是s(秒)、m(分钟)、h(小时)等
	Enabled   bool   // 是否启用
}

func DefaultTask() []TaskConfig {
	return []TaskConfig{
		{
			Name:      "SayHello",
			Scheduler: "@every 20s", //每20秒钟执行一次
			Enabled:   true,
		},
		{
			Name:      "StatisticsUserCount",
			Scheduler: "@every 1m", //每1分钟执行一次
			Enabled:   true,
		},
	}
}

然后,定义定时任务调度器文件:gozero/internal/crontab/scheduler.go,这个文件中,先定义好调度器的结构体和注册方法以及启动方法。代码如下:

type Scheduler struct {
	cron   *cron.Cron
	svcCtx *svc.ServiceContext
}

// NewScheduler creates a new scheduler instance.
func NewScheduler(svcCtx *svc.ServiceContext) *Scheduler {
	return &Scheduler{
		cron:   cron.New(),
		svcCtx: svcCtx,
	}
}

// RegisterTask registers a task with the scheduler.
func (s *Scheduler) RegisterTask(name, schedule string, task func(ctx context.Context, svcCtx *svc.ServiceContext)) {
	_, err := s.cron.AddFunc(schedule, func() {
		task(context.Background(), s.svcCtx)
	})
	if err != nil {
		log.Fatalf("Failed to register task %s: %v", name, err)
	}
	log.Printf("Registered task %s with schedule %s", name, schedule)
}

func (s *Scheduler) Start() {
	s.cron.Start()
	log.Println("Scheduler started")
}

func (s *Scheduler) Stop() {
	s.cron.Stop()
	log.Println("Scheduler stopped")
}

上面的 Start() 和 Stop() 方法,分别实现了 vendor/github.com/robfig/cron/v3/cron.go 中的 Start() 和 Stop() 方法。

接下来,需要初始化定时任务调度器,对于config.go中配置好的定时任务,分别实现不同的业务逻辑。

// InitScheduler 初始化定时任务调度器
func InitScheduler(svcCtx *svc.ServiceContext) (*Scheduler, error) {
	log.Println("Initializing scheduler...")
	scheduler := NewScheduler(svcCtx)
	if scheduler == nil {
		return nil, fmt.Errorf("failed to create scheduler")
	}
	taskConfigs := DefaultTask()
	if taskConfigs == nil {
		return nil, fmt.Errorf("failed to load task configurations")
	}
	for _, taskConfig := range taskConfigs {
		if !taskConfig.Enabled {
			log.Printf("Task %s is disabled, skipping...", taskConfig.Name)
			continue
		}

		log.Printf("Registering task %s...", taskConfig.Name)

		switch taskConfig.Name {
		case "SayHello": //SayHello
			scheduler.RegisterTask(taskConfig.Name, taskConfig.Scheduler, hello.SayHello)
		case "StatisticsUserCount": //统计用户总数
			scheduler.RegisterTask(taskConfig.Name, taskConfig.Scheduler, user.StatisticsUserCount)
		case "xxxx":
			// todo 注册其他定时任务
		default:
			log.Printf("Unknown task: %s", taskConfig.Name)
		}
	}
	return scheduler, nil
}

接下来, 在入口文件gozero/gozero.gomain方法中调用上面定义好的调度器:

func main() {
	//....

	// 定时任务调度
	scheduler, err := crontab.InitScheduler(ctx)
	if err != nil {
		fmt.Printf("Failed to initialize scheduler: %v", err)
	}
	scheduler.Start()

	fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
	server.Start()
}

测试方法

接下来,在 gozero/internal/crontab/task 目录下,新建两个测试方法,测试一下上面配置的两个定时任务:

  • SayHello方法: gozero/internal/crontab/task/hello/say_hello.go
func SayHello(ctx context.Context, svcCtx *svc.ServiceContext) {
	fmt.Println("SayHello running at:", time.Now())
	return
}
  • 查询用户总数的方法:gozero/internal/crontab/task/user/statistics_user_count.go
package user

func StatisticsUserCount(ctx context.Context, svcCtx *svc.ServiceContext) {
	fmt.Println("StatisticsUserCount running at:", time.Now())

	listLogic := admin.NewUserListLogic(ctx, svcCtx)
	count, err := listLogic.GetUserCount() //调用逻辑层查询数据库
	if err != nil {
		fmt.Println("StatisticsUserCount error:", err)
		return
	}
	if count == 0 {
		fmt.Println("StatisticsUserCount count is 0")
		return
	}
	fmt.Println("StatisticsUserCount count:", count)
	return
}

然后运行一下:

image-20250225113155576

这样就可以轻松的在go-zero中实现定时任务的调度了,可以精确到秒级别。

https://gitee.com/rxbook/go-demo-2025/tree/master/gozero


http://www.niftyadmin.cn/n/5869106.html

相关文章

KIMI K1.5:大规模强化学习在大语言模型中的应用与工程实践

目录 1、核心技术创新:长上下文强化学习 2、策略优化的技术细节 2.1、在线镜像下降变体 2.2、长度惩罚机制 2.3、智能采样策略 3、工程架构创新 3.1、混合部署框架 3.2、代码沙箱与奖励模型 3.3、分布式系统架构 4、实验成果与性能提升 5、结论与未来展望 大语言模…

品融电商解读:小红书KOC打法如何重构品牌增长新路径

品融电商解读:小红书KOC打法如何重构品牌增长新路径 在内容生态高度饱和的今天,品牌若想在小红书等平台实现破局,仅依赖“产品为王”的单一逻辑已远远不够。作为国内头部的小红书代运营公司,品融电商观察到,平台的竞…

Ubuntu搭建esp32环境 配置打开AT指令集 websocket功能

1,搭建前提 环境搭建参考乐鑫官网给的本地编译 ESP-AT 工程方法 因为公司电脑和网络的特殊性,不能正确解析域名(仅在浏览器上可以访问) ,所以这边访问的时候改成了ssh 未了避免使用外网困难的问题,这里用…

一文读懂什么是K8s Admission Controller

#作者:曹付江 文章目录 1、什么是 Admission Controllers?2、如何创建 Admission Controllers?3、Admission 控制器的最佳实践 K8s 中的操作与安全标准执行机制: 1、什么是 Admission Controllers? Admission contro…

LabVIEW形状误差测量系统

在机械制造领域,形状与位置公差(GD&T)直接影响装配精度与产品寿命。国内中小型机加工企业因形状误差导致的返工率高达12%-18%。传统测量方式存在以下三大痛点: ​ 设备局限:机械式千分表需人工读数,精度…

u3d预制件笔记

本文意在整合预制件相关重要信息,将较多的信息量浓缩出精华,并记录个人理解心得 一.预制件的概念和用途 Unity 的预制件系统允许创建、配置和存储游戏对象及其所有组件、属性值和子游戏对象作为可重用资源。预制件资源充当模板,在此模板的基…

OkHttp、Retrofit、RxJava:一文讲清楚

一、okHttp的同步和异步请求 Call 是 OkHttp 的核心接口,代表一个已准备好执行的 HTTP 请求。它支持 同步 和 异步 两种模式: enqueue——>okHttp异步 OkHttpClient client new OkHttpClient();Request request new Request.Builder().url("…

UIAutomation开发常用方法的参考文档

简介 由于UIAutomation的官方文档只有一个github中的readme文件,只是简单的使用示例,具体使用还需要在代码中查找,非常不方便。经过我多年使用UIAutomation开发的经验和整理,把常用的功能梳理成本文档,作为我的开发参考使用,这样就不用每次都翻代码了,同时也可以使用AI…