hibiken/asynq 基于 Redis 的轻量级异步任务队列
概述
Asynq是一个基于Go语言的异步任务处理解决方案,它提供了轻量级的、易于使用的API,并且具有高可扩展性和高可定制化性。Asynq主要由以下几个组件组成:
- 任务(Task):需要被异步执行的操作。
- 处理器(Processor):负责执行任务的工作进程。
- 队列(Queue):存放待执行任务的队列。
- 调度器(Scheduler):根据一定的规则将任务分配给不同的处理器进行执行。
- 通过使用Asynq,我们可以非常轻松地实现异步任务处理,同时还可以提供高效率、高可扩展性和高自定义性的处理方案。
安装
- 注意:redis的版本需要大于5.0
安装asynq
go get -u github.com/hibiken/asynq
基础使用
- 生产者
r := asynq.RedisClientOpt{
Addr: "", // redis连接地址
Password: "", // redis连接密码
DB: "", // redis使用的库
DialTimeout:"", // 连接超时时间 默认5秒
ReadTimeout:"", // 读取数据的超时时间。当读取操作达到这个时间限制时,如果没有完成读取,将会返回一个超时错误而不是继续阻塞等待 默认3秒 设置-1表示没有超时限制
WriteTimeout:"", // 写入数据的超时时间。当写入操作达到这个时间限制时,如果没有完成写入,将会返回一个超时错误而不是继续阻塞等待 默认等于ReadTimeout的值 设置-1表示没有超时限制
}
// 连接redis
client := asynq.NewClient(r)
defer client.Close()
// 创建一个任务
// 任务负载信息
type payload struct{
Id int
...
}
var payloadInfo payload
payloadByte, _ := json.Marshal(payloadInfo)
task := asynq.NewTask("此处为任务路由,和消费者路由对应", payloadByte)
// 发送任务(即时消费)
_, err := client.Enqueue(task)
if err != nil{
fmt.Println("enqueue failed:", err)
}
- 消费者
srv := asynq.NewServer(
// redis连接信息 同生产者
asynq.RedisClientOpt{
Addr: "",
Password: "",
DB: "",
},
asynq.Config{
Concurrency: 1 // 定义了可以并发处理的任务数量 如果设置为零或负数,NewServer 方法会将其重置为当前进程可使用的 CPU 数量
Queues: map[string]int{
"queue1": 4,
"queue2": 6,
}, // 设置多个队列并配置队列的占比
},
)
// 设置路由信息
mux := asynq.NewServeMux()
mux.HandleFunc("任务路由,和生成者对应", consumerfunc)
// 消费方法
func consumerfunc(ctx context.Context, t *asynq.Task) error {
// 解析负载
var info payload
_ = json.Unmarshal(t.Payload(), &info)
// 后续操作
...
}
// 启动服务
if err := srv.Start(mux); err != nil {
log.Fatalf("could not start server: %v", err)
}
// Wait for termination signal.
c := make(chan os.Signal, 1)
// 退出操作
signal.Notify(c, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM,syscall.SIGQUIT)
for {
s := <-c
switch s {
case syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT:
fmt.Println("Program Exit...", s)
srv.Shutdown()
srv.Stop()
return
default:
fmt.Println("other signal", s)
}
}
其它功能
- 指定消费的队列
info, err = client.Enqueue(task, asynq.Queue("queue1"))
- 指定任务被消费的时间
info, err = client.Enqueue(task, asynq.ProcessIn(1*time.Hour)) // 任务1小时后被消费
- 设置超时、重试次数
res, err := c.Enqueue(task, asynq.MaxRetry(3), asynq.Timeout(10*time.Second), asynq.Deadline(time.Now().Add(20*time.Second)))
// asynq.MaxRetry(3): 这个参数指定了当任务执行失败时的最大重试次数。在这个例子中,如果任务执行失败,它将最多重试 3 次
// asynq.Timeout(10 * time.Second): 这个参数设置了任务执行的超时时间。如果任务在 10 秒内没有完成,它将被标记为超时并可能重新调度
// asynq.Deadline(time.Now().Add(20 * time.Second)): 这个参数定义了任务的截止时间。在这个例子中,任务必须在当前时间之后的 20 秒内完成。如果任务在这个时间之前没有完成,它将被视为超时
队列监控
// 安装
go install github.com/hibiken/asynq/tools/asynq@latest
// 执行
asynq --uri 127.0.0.1:6379 --db 5 dash