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 [ ...
随机推荐
- 【YashanDB知识库】生成迁移报告失败,"报错未知类型错误异常:"
[标题]YMP迁移 [问题分类]迁移报告 [关键字]迁移报告.未知类型错误异常 [问题描述]下载迁移报告时报错"未知类型错误异常:",一长串英文 日志报错: [问题原因分析]jav ...
- 【YashanDB知识库】账号被锁,如何分析具体原因
问题现象 客户刚开始使用YashanDB的时候,经常收到客户反馈账号被锁,但是不知道哪里触发了. 问题的风险及影响 客户环境为测试环境,影响测试业务的开展. 问题影响的版本 YashanDB版本:23 ...
- JavaScript – 理解 Function, Object, Prototype, This, Class, Mixins
前言 JavaScript (简称 JS) 有几个概念 Object, Prototype, This, Function, Class 是比较难理解的 (相对其它语言 C# / Java 而已),这 ...
- GPUStack 0.2:开箱即用的分布式推理、CPU推理和调度策略
GPUStack 是一个专为运行大语言模型(LLM)设计的开源 GPU 集群管理器,旨在支持基于任何品牌的异构 GPU 构建统一管理的算力集群,无论这些 GPU 运行在 Apple Mac.Windo ...
- SpringMVC —— 入门案例执行流程
启动服务器初始化过程 1.服务器启动,执行ServletContainersInitConfig类,初始化web容器 2.执行createServletApplicationContext方法, ...
- Hadoop完全分布式搭建,基于乌班图系统
因为现在集成的工具很多,建议在接触这一块的过程中还是自己找几个主机,亲手搭一遍集群,更好的熟悉底层!本文只是搭建的过程没有理论!手搭集群时先将各节点网络.ssh配置好!然后在一台机子上操作配置文件,直 ...
- SXYZ-6.26模拟赛
没有爆零,足矣. 发现绍兴一中机房的一个特点:键盘打得贼响!! T1 ctrl 啃臭键在哪里 (中文名我都不好意思大打) 第一遍测T1一分都没得啊! 这跟题目描述自相矛盾有关,导致我只是轻微考虑了一下 ...
- Nuxt.js 应用中的 app:suspense:resolve 钩子详解
title: Nuxt.js 应用中的 app:suspense:resolve 钩子详解 date: 2024/10/6 updated: 2024/10/6 author: cmdragon ex ...
- cpu proc sys文件系统下的含义
proc文件系统(/proc/sys/kernel/) sched_child_runs_first /proc/sys/kernel/sched_child_runs_first是Linux内核中的 ...
- 数据库日常实操优质文章分享(含Oracle、MySQL等) | 2023年2月刊
本文为大家整理了墨天轮数据社区2023年2月发布的优质技术文章,主题涵盖Oracle.MySQL.PostgreSQL等数据库的环境搭建.故障处理等日常实践操作,以及概念梳理.常用脚本等总结记录,分享 ...