V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
gansteed
V2EX  ›  分享创造

结合实际业务,整了一个 Go 的异步任务框架

  •  1
     
  •   gansteed ·
    jiajunhuang · 2020-04-15 16:38:58 +08:00 · 3089 次点击
    这是一个创建于 1464 天前的主题,其中的信息可能已经有所发展或是发生改变。

    链接在 https://github.com/jiajunhuang/gotasks


    日常开发中,会发现很多异步任务会变的又大又长,其实其中很多任务是可以拆成 n 个子任务的,所以就整了这个框架,用法很简单,首先把任务分成 n 个子任务(不分用一个自然也是 ok 的),注册进去。接下来生产者 Enqueue 任务, 消费者消费任务。

    注册的子任务会串成一个链,他们共用一个 map 来存储参数,因此第一个子任务可以修改参数并且返回,第二个子任务拿到的就是修改后的参数。

    package main
    
    import (
    	"time"
    
    	"github.com/jiajunhuang/gotasks"
    )
    
    const (
    	uniqueJobName = "a-unique-job-name"
    	redisURL      = "redis://127.0.0.1:6379/0"
    	queueName     = "job-queue-name"
    )
    
    func worker() {
    	gotasks.Run(queueName)
    }
    
    func main() {
    	go worker()
    
    	// register tasks
    	handler1 := func(args gotasks.ArgsMap) (gotasks.ArgsMap, error) {
    		time.Sleep(time.Duration(1) * time.Second)
    		return args, nil
    	}
    	handler2 := func(args gotasks.ArgsMap) (gotasks.ArgsMap, error) {
    		time.Sleep(time.Duration(1) * time.Second)
    		return args, nil
    	}
    	gotasks.Register(uniqueJobName, handler1, handler2)
    
    	// set broker
    	gotasks.UseRedisBroker(redisURL, 100)
    
    	// enqueue
    	gotasks.Enqueue(queueName, uniqueJobName, gotasks.MapToArgsMap(map[string]interface{}{})) // or gotasks.StructToArgsMap
    }
    
    8 条回复    2020-04-17 19:33:08 +08:00
    lasuar
        1
    lasuar  
       2020-04-15 17:22:29 +08:00
    看的我有点蒙,uniqueJobName 和 queueName 的区别是什么?另外直接用 redis 的 pubsub 不行吗?你这个不也是用的 redis 吗,套娃?
    gansteed
        2
    gansteed  
    OP
       2020-04-15 17:34:16 +08:00
    @lasuar 如果没有 queueName,那么意味着所有的任务都会放到一个队列里; queue 就是分流。举个例子:如果是学校的管理系统(假设是一个单体应用)。处理书籍的异步任务和处理学生信息的异步任务肯定不希望放在同一个队列里进行消费。这样也不利于多队列并发消费。可以用 pub/sub,我更喜欢用 lpush/brpop
    lasuar
        3
    lasuar  
       2020-04-15 19:21:17 +08:00
    ok ;你都说了 lpush 。那可以直接用 redis 的 lpush 和 brpop 啊,就是把 list 当队列用。看到这里我得出的结论就是 gotasks 的主要内容就是把 lpush 和 brpop 封装了一下,以及 list 的管理,so==
    gansteed
        4
    gansteed  
    OP
       2020-04-15 20:12:25 +08:00
    @lasuar 额,你可以看看 python-rq 的实现。如果一定要这么说的话,Web 框架岂不是就封装了一个

    GET / HTTP/1.1
    Host: blabla

    的报文?
    lasuar
        5
    lasuar  
       2020-04-15 20:20:35 +08:00
    @gansteed 我和我的朋友们确实这么看 web 框架的,使用 web 框架是因为更多的时 web 框架封装了已很多插件化的东西,简单好用,就类似脚手架;不过 web 框架的实现也有一些亮点的东西,比如不同的 web 框架内部使用的 IO 模型不一样,有的是 select 有的是 epoll ;我并不是完全否定你的作品,只是在我看来目前哈这个项目的确没什么技术亮点(请原谅我的直接),你可以添加一些亮点进去,更容易得到 star 和认可
    Aether
        6
    Aether  
       2020-04-16 16:03:14 +08:00
    感觉可能有用,先码了。

    先说,我是一个小白。

    我个人其实特别想要一个极其简单的,类似 Python Celery (但部署不要那么复杂)的任务序列,可以有节奏地控制,把任务付诸实施(比如忽然来了 1000 个任务,我可以限定每分钟执行 100 个,避免对外部 API/内部资源的挤压消耗,直到自然耗尽。可能再有就是保证队列不会丢)。而我只需要 addTask(object/param) 就完了。

    目前我看到的 Go 体系下任务序列都很繁杂(相对我能理解的能力而言),覆盖的各种独特性太多,或者实施比较麻烦,不能一目了然,看了 demo 就能用。缺少 Python 那种简洁的感受。
    gansteed
        7
    gansteed  
    OP
       2020-04-16 20:23:49 +08:00
    @Aether +1,我也不喜欢很复杂的
    OakScript
        8
    OakScript  
       2020-04-17 19:33:08 +08:00
    各种 goworker 不要太多啊,同样轮子没有特色,个人练个手就好
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3226 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 14:07 · PVG 22:07 · LAX 07:07 · JFK 10:07
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.