golang之异步队列Asynq
Asynq[1]是一个Go实现的分布式任务队列和异步处理库,基于redis,类似Ruby的sidekiq[2]和Python的celery[3]。Go生态类似的还有machinery[4]和goworker
同时提供一个WebUI asynqmon[5],可以源码形式安装或使用Docker image, 还可以和Prometheus集成
docker run --rm --name asynqmon -p 8080:8080 hibiken/asynqmon,如果使用的是主机上的redis,还需加上 --redis-addr=host.docker.internal:6379,否则会报错[6]
即 docker run --rm --name asynqmon -p 8080:8080 hibiken/asynqmon --redis-addr=host.docker.internal:6379
➜ asynq-demo git:(main) ✗ tree
.
├── client.go
├── const.go
├── go.mod
├── go.sum
└── server.go
0 directories, 5 files
其中const.go:
package main
const (
redisAddr = "127.0.0.1:6379"
redisPasswd = ""
)
const (
TypeExampleTask = "shuang:asynq-task:example"
)
client.go:
package main
import (
"encoding/json"
"fmt"
"log"
"time"
"github.com/hibiken/asynq"
)
type ExampleTaskPayload struct {
UserID string
Msg string
// 业务需要的其他字段
}
func NewExampleTask(userID string, msg string) (*asynq.Task, error) {
payload, err := json.Marshal(ExampleTaskPayload{UserID: userID, Msg: msg})
if err != nil {
return nil, err
}
return asynq.NewTask(TypeExampleTask, payload), nil
}
var client *asynq.Client
func main() {
client = asynq.NewClient(asynq.RedisClientOpt{Addr: redisAddr, Password: redisPasswd, DB: 0})
defer client.Close()
//go startExampleTask()
startExampleTask()
//startGithubUpdate() // 定时触发
}
func startExampleTask() {
fmt.Println("开始执行一次性的任务")
// 立刻执行
task1, err := NewExampleTask("10001", "mashangzhixing!")
if err != nil {
log.Fatalf("could not create task: %v", err)
}
info, err := client.Enqueue(task1)
if err != nil {
log.Fatalf("could not enqueue task: %v", err)
}
log.Printf("task1 -> enqueued task: id=%s queue=%s", info.ID, info.Queue)
// 10秒后执行(定时执行)
task2, err := NewExampleTask("10002", "10s houzhixing")
if err != nil {
log.Fatalf("could not create task: %v", err)
}
info, err = client.Enqueue(task2, asynq.ProcessIn(10*time.Second))
if err != nil {
log.Fatalf("could not enqueue task: %v", err)
}
log.Printf("task2 -> enqueued task: id=%s queue=%s", info.ID, info.Queue)
// 30s后执行(定时执行)
task3, err := NewExampleTask("10003", "30s houzhixing")
if err != nil {
log.Fatalf("could not create task: %v", err)
}
theTime := time.Now().Add(30 * time.Second)
info, err = client.Enqueue(task3, asynq.ProcessAt(theTime))
if err != nil {
log.Fatalf("could not enqueue task: %v", err)
}
log.Printf("task3 -> enqueued task: id=%s queue=%s", info.ID, info.Queue)
}
server.go:
package main
import (
"context"
"encoding/json"
"fmt"
"time"
"github.com/davecgh/go-spew/spew"
"github.com/hibiken/asynq"
)
var AsynqServer *asynq.Server // 异步任务server
func initTaskServer() error {
// 初始化异步任务服务端
AsynqServer = asynq.NewServer(
asynq.RedisClientOpt{
Addr: redisAddr,
Password: redisPasswd, //与client对应
DB: 0,
},
asynq.Config{
// Specify how many concurrent workers to use
Concurrency: 100,
// Optionally specify multiple queues with different priority.
Queues: map[string]int{
"critical": 6,
"default": 3,
"low": 1,
},
// See the godoc for other configuration options
},
)
return nil
}
func main() {
initTaskServer()
mux := asynq.NewServeMux()
mux.HandleFunc(TypeExampleTask, HandleExampleTask)
// ...register other handlers...
if err := AsynqServer.Run(mux); err != nil {
fmt.Printf("could not run asynq server: %v", err)
}
}
func HandleExampleTask(ctx context.Context, t *asynq.Task) error {
res := make(map[string]string)
spew.Dump("t.Payload() is:", t.Payload())
err := json.Unmarshal(t.Payload(), &res)
if err != nil {
fmt.Printf("rum session, can not parse payload: %s, err: %v", t.Payload(), err)
return nil
}
//-----------具体处理逻辑------------
spew.Println("拿到的入参为:", res, "接下来将进行具体处理")
fmt.Println()
// 模拟具体的处理
time.Sleep(5 * time.Second)
fmt.Println("--------------处理了5s,处理完成-----------------")
return nil
}
执行redis-server
清除redis中所有的key:
执行docker run --rm --name asynqmon -p 8080:8080 hibiken/asynqmon --redis-addr=host.docker.internal:6379
执行 go run client.go const.go (生产者,产生消息放入队列)
此时能看到redis中多个几个key
同时管理后台能看到队列的信息
执行 go run server.go const.go (消费者,消费队列中的消息)
可以看到都被处理了
此时redis中的key:
此处的业务处理为模拟,实际可能是某个被触发后不需要马上执行的操作
相关文档:
golang之异步队列Asynq的更多相关文章
- .Net中的并行编程-4.实现高性能异步队列
上文<.Net中的并行编程-3.ConcurrentQueue实现与分析>分析了ConcurrentQueue的实现,本章就基于ConcurrentQueue实现一个高性能的异步队列,该队 ...
- jquery ajax 对异步队列defer与XMLHttprequest.onload的依赖
ajax 对异步队列defer与XMLHttprequest.onload的依赖
- 异步队列 Deferred
异步队列 Deferred 背景: 移动web app开发,异步代码是时常的事,比如有常见的异步操作: Ajax(XMLHttpRequest) Image Tag,Script Tag,iframe ...
- [js高手之路]javascript腾讯面试题学习封装一个简易的异步队列
这道js的面试题,是这样的,页面上有一个按钮,一个ul,点击按钮的时候,每隔1秒钟向ul的后面追加一个li, 一共追加10个,li的内容从0开始技术( 0, 1, 2, ....9 ),首先我们用闭包 ...
- .Net中的并行编程-7.基于BlockingCollection实现高性能异步队列
三年前写过基于ConcurrentQueue的异步队列,今天在整理代码的时候发现当时另外一种实现方式-使用BlockingCollection实现,这种方式目前依然在实际项目中使用.关于Blockin ...
- 基于异步队列的生产者消费者C#并发设计
继上文<<基于阻塞队列的生产者消费者C#并发设计>>的并发队列版本的并发设计,原文code是基于<<.Net中的并行编程-4.实现高性能异步队列>>修改 ...
- js异步队列之理解
起因 最近看到一篇关于js异步执行顺序的解答,觉得有所收获,遂记录下来. marcotask和microtask js中异步队列可以分为两类,marcotask队列和microtask队列, marc ...
- jQuery源码分析(九) 异步队列模块 Deferred 详解
deferred对象就是jQuery的回调函数解决方案,它解决了如何处理耗时操作的问题,比如一些Ajax操作,动画操作等.(P.s:紧跟上一节:https://www.cnblogs.com/grea ...
- jQuery 源码解析(八) 异步队列模块 Callbacks 回调函数详解
异步队列用于实现异步任务和回调函数的解耦,为ajax模块.队列模块.ready事件提供基础功能,包含三个部分:Query.Callbacks(flags).jQuery.Deferred(funct) ...
- Laravel异步队列全攻略
最近项目需求,研究了laravel的异步队列.官方文档虽然很是详细,但也有些晦涩难懂,在此记录下步骤,供大家参考. 1.修改/config/queue.php文件 <?php return [ ...
随机推荐
- 淘宝打单发货接口,淘宝打单发货API
许多做系统功能的小伙伴经常面对的一个功能是对接淘宝开放平台,在自己系统中进行打单发货. 但是,目前淘宝开放平台,已经关闭了相关的相关的权限申请,具体可查看相关公告.有需要这个权限的,可以站内信联系我, ...
- windows server 2019 IIS网站属性上没有asp.net标签 ,aspnet_regiis -i 不能安装
在新的服务器版本已经不能通过 aspnet_regiis -i安装了,可以通过以下语句完成: dism /online /enable-feature /featurename:IIS-ASPNET4 ...
- ComfyUI 基础教程(三) —— 应用 Controlnet 精准控制图像生成
一.前言 你是否有见过下面类似这样的图片: 看起来平平无奇,当你站远点看,或者把眼睛眯成一条缝了看,你会发现,这个图中藏有一些特别的元素.这就是利用了 Ai 绘画中的 ControlNet,实现对图片 ...
- 深入理解JavaScript中的箭头函数
箭头函数可以使我们的代码更加简洁,如下: var sum = (a,b) => a+b; JavaScript 充满了我们需要编写在其他地方执行的小函数的情况. 例如: arr.forEach( ...
- MaterialDesignInXamlToolkit 5.0 发布
5.0.0 发布 这是一个重大版本更新,又许多破坏性变化 升级到5.0.0版本,请参考:https://www.cnblogs.com/sesametech-dotnet/p/18028565 变化 ...
- Docker基本概念(LXC?镜像、容器、仓库是什么?容器和虚拟机又是什么?)(一)
学习Docker前,我们有必要了解下Docker的前生LXC(Linux Container). 一.LXC介绍 LXC 可以提供轻量级的虚拟化,用来隔离进程和资源,和我们传统观念中的全虚拟化完全不一 ...
- python 属性装饰器和对应的setter方法,属性的封装和安全性控制
当我们在类中定义属性时,通常希望能够对属性的读取和写入进行控制,以确保数据的完整性和安全性.属性装饰器和对应的setter方法提供了一种实现属性封装和安全性控制的方法. 属性装饰器是Python的一种 ...
- SQL数据库书的配套资源
<SQL基础教程(视频教学版)>代码.课件.教学视频 https://pan.baidu.com/s/1QA5m5HN159wi3FX_KNDQzA 提取码: 4m9e <SQL S ...
- 谷歌浏览器页面乱码问题在浏览器端解决,charset下载安装;
一 下载插件(百度网盘) 链接:https://pan.baidu.com/s/1o9Zuo2m 密码:rrcz 二 将下载好的插件拖到谷歌浏览器中 三 如果谷歌浏览器右下角出现如下图 ...
- ftrace options 中的irq-info
/sys/kernel/debug/tracing/options/irq_info 是 ftrace 中的一个选项,用于启用或禁用有关中断的详细信息的跟踪. options/irq_info 的具体 ...