【go】异步任务解决方案Asynq实战

文章目录

一.Asynq介绍

Asynq 是一个 Go 库,一个高效的分布式任务队列。

Asynq 工作原理:

  • 客户端(生产者)将任务放入队列
  • 服务器(消费者)从队列中拉出任务并为每个任务启动一个工作 goroutine
  • 多个工作人员同时处理任务

git库:https://github.com/hibiken/asynq

二.所需工具

Asynq 使用 Redis 作为消息代理。client 和 server 都需要连接到 Redis 进行写入和读取。

PS:请确保所使用redis >= 5.0

三.代码示例

以记录操作的中间件函数向数据库写数据的情景为例。

  1. 生产者(客户端)函数调用入口:

其中 map 为需向数据库写入的内容

go 复制代码
client.Call("audit:opera", map[string]any{
	"uri":        uri,
	"method":     method,
	"params":     string(paramsByte),
	"headers":    string(headerByte),
	"code":       codeInt,
	"model":      model,
	"action":     action,
	"user_id":    userId,
	"company_id": companyId,
	"user_name":  userName,
	"company":    companyName,
})
  1. 生产者函数
go 复制代码
func Call(t string, payload map[string]any) error {
	// redis连接
	client := asynq.NewClient(asynq.RedisClientOpt{
		Addr:     "127.0.0.1:6379",
		Password: "",
		DB:       1,
	})
	defer client.Close()

	switch t {
	case "audit:opera":
	    // 初始化新任务
		task, err := server.NewOperateSendTask(payload)
		if err != nil {
			return err
		}

       // 任务入队
		_, err = client.Enqueue(task, asynq.Queue("audit"))
		if err != nil {
			log.Err(err).Msg(fmt.Sprintf("task: %v\n", task))
			return err
		}
	}

	return nil
}
go 复制代码
func NewOperateSendTask(data map[string]any) (*asynq.Task, error) {
	payload, err := json.Marshal(data)
	if err != nil {
		return nil, err
	}
	return asynq.NewTask(consts.TypeAuditOpera, payload), nil
}
  1. 消费者函数
go 复制代码
func HandlerAuditOperateTask(ctx context.Context, t *asynq.Task) error {
	var record ent.OperateRecord

	// 队列中取任务
	err := json.Unmarshal(t.Payload(), &record)
	if err != nil {
		log.Err(err).Msg("task.json.Unmarshal")
		return err
	}

	// 真正的数据库操作
	err = dao.OperateRecord.CreateOperateRecord(&record)
	if err != nil {
		log.Err(err).Msg("task.dao.OperateRecord.CreateOperateRecord")
		return err
	}

	return nil
}
  1. asynq初始化(消费者启动入口,项目初始化时自动启动)
go 复制代码
func InitAsynq(ip string, port int, passwd string) {
	addr := fmt.Sprintf("%s:%d", ip, port)
	srv := asynq.NewServer(
		asynq.RedisClientOpt{
			Addr:     "127.0.0.1:6379",
			Password: "",
			DB:       1,
		},
		// 异步队列
		asynq.Config{
			Queues: map[string]int{
				"audit": 3,
			},
		},
	)

	mux := asynq.NewServeMux()
	// 启动消费者
	mux.HandleFunc("audit:opera", server.HandlerAuditOperateTask)
	
	go srv.Run(mux)

}

四.Reference

Go异步任务解决方案之Asynq库详解:
https://www.jb51.net/article/275392.htm

相关推荐
大熊程序猿9 小时前
go 安装依赖超时
开发语言·后端·golang
Au_ust11 小时前
go的结构体、方法、接口
开发语言·golang
techdashen13 小时前
清理Go/Rust编译时产生的缓存
缓存·golang·rust
bugtraq202116 小时前
Fyne ( go跨平台GUI )中文文档-绘图和动画(三)
开发语言·后端·golang
qq_1728055919 小时前
Kafka-Go学习
开发语言·学习·golang·kafka·go
技术卷20 小时前
golang学习笔记4-基本数据类型
笔记·学习·golang
请不要叫我菜鸡21 小时前
Go语言基础学习02-命令源码文件;库源码文件;类型推断;变量重声明
linux·后端·golang·类型推断·短变量·变量重声明·库源码文件
jzpfbpx1 天前
[go] 适配器模式
开发语言·golang·适配器模式
qq_172805591 天前
Go Testify学习与使用
开发语言·golang·go
多思考少编码1 天前
【LGR-200-Div.4】洛谷入门赛 #27 A - H题解,包含(C++, Go语言)
开发语言·c++·golang·洛谷·算法竞赛