V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
zhengfan2016
V2EX  ›  Go 编程语言

golang 执行长时间的任务的最佳实践是什么?

  •  
  •   zhengfan2016 · 70 天前 · 3528 次点击
    这是一个创建于 70 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如题,比如使用本地 flux1 模型 生成一张需要等待 30 秒的图片

    1.直接 controller 内同步返回,相信 web 框架的并发能力

    2.使用 redis 队列 并且增加 POST /task 和 GET /task/:id 两个接口 post task 创建任务,get task 查询任务结果, 但是这样需要拆 api+worker+comfyui 需要跑三个 docker ,服务有点多

    3.在 controller 内直接用 channel

    35 条回复    2025-06-05 17:54:04 +08:00
    fffq
        1
    fffq  
       70 天前
    30s 接口早 timeout 了
    Vegetable
        2
    Vegetable  
       70 天前
    1. 你的 server 并发能力一定远超你的模型生成能力。
    zhengfan2016
        3
    zhengfan2016  
    OP
       70 天前
    @fffq 不是有长连接吗,keep-alive
    kcross
        4
    kcross  
       70 天前
    先看你们显卡顶不顶得住 1 3 吧
    zeromake
        5
    zeromake  
       70 天前
    @zhengfan2016 #3
    http 的 keep-alive 和你一次请求是否超时没有任何关系,你需要对 http server 对框架设置自定义的超时时间,对服务上层的负载均衡做自定义超时时间,如果还有 cdn 还得去 cdn 看看是否能设置最大超时时间
    vincentWdp
        6
    vincentWdp  
       70 天前
    因为 comfyUI 也是第二点逻辑, 因此我的想法是:
    golang 这块两个进程: 1. 给前端提供服务(创建任务, 轮询结果); 2. 后台执行任务.
    wogogoing
        7
    wogogoing  
    PRO
       70 天前 via iPhone
    非最佳实践:

    1.触发式请求用常规 http request
    2.耗时任务用异步协程处理,结果用 websocket 或 sse 推送给前端。
    w568w
        8
    w568w  
       70 天前
    2 ,但不用搞 redis 那么麻烦,轻量化一点用 SQLite 就行了(比如 goqite )

    1 3 的问题是对中断推理支持不好。最好能弄个 websocket ,POST /task 创建任务,/task/:id 和客户端长通信,实时返回推理状态或者下发新指令(例如中断)。
    Jemini
        9
    Jemini  
       70 天前
    asynq 吧。当普通任务写就好了。也够轻
    zeusho871
        10
    zeusho871  
       70 天前   ❤️ 1
    靠 http 接口的超时 如果你套了 nginx nginx 那边超时也得跟着设置 很麻烦的 不如 redis 然后前端轮询各种都随你
    totoro52
        11
    totoro52  
       70 天前
    方案 2 ,如果是自己的小玩具 无脑等待就好了, 一般生图这种都是任务状态 被动触发的
    guanzhangzhang
        12
    guanzhangzhang  
       70 天前
    websocket 之类的长连接推送进度。进页面查询自己的 taskID ,根据 id 和后端建立 websocket 连接获取实时进度
    BeautifulSoap
        13
    BeautifulSoap  
       70 天前 via Android
    肯定 1 啊,web 框架对每个 controller 调用不还是用的 go 协程。你 controller 等待生成时是直接 io 卡死在那,go 的调度器会自动处理的。你费那么大劲用 redis 或 channel 根本没任何必要(除非有什么持久化或者生成一半要取消之类的需求)

    你唯一要考虑的就是调用请求的客户端还有你 web 服务器前的网关的最大超时时间
    momocraft
        14
    momocraft  
       70 天前
    2

    每个 user agent 每层 gateway 都可能有自己的 timeout ,不像 2 这样 你还要相信别的很多东西
    coefuqin
        15
    coefuqin  
       70 天前
    搞成异步的,完成了之后主动推送一个事件,然后提供图片 URL 。
    kk2syc
        16
    kk2syc  
       70 天前
    你不考虑用户因为网络波动导致直接断开连接吗?那不是一切重来。
    unused
        17
    unused  
       70 天前 via Android
    这首先是一个接口设计问题
    flyingghost
        18
    flyingghost  
       70 天前
    小 demo 就同步,怎么简单怎么来。我写 demo 不爱用 web ,直接命令行跑起来就算。
    生产环境必须异步。
    1 ,负载能力决定了任务需要队列,耗时包含了排队时间,不可能一定是 30s 的。任务的逻辑超时时间取决于业务决策并且可能天天变化。
    2 ,技术上一个链接的超时时间取决于链路中多个组件的设置。客户端、代理、网关、应用。。。远不如短连接+异步来得简洁稳固。
    3 ,API 和 task 资源池解耦,甚至我们 API 和调度也解耦了。这样 API 的可靠性增加,task 计算池的弹性增加。
    4 ,对服务失效有更高的状态恢复能力。
    5 ,接口层 task 状态可推可拉,对客户端也挺灵活挺友好。
    6 ,整个系统的吞吐量瓶颈几乎只剩一个:task 计算池了。API 和调度都很难形成瓶颈了。
    starlion
        19
    starlion  
       70 天前
    如果任务比较多,就搞一个异步任务中心,这种长时间的多个异步任务交给它来执行,异步任务中心执行完了在通知你的 Go 程序,比如用 Go 写个 task cron 异步执行系统或找个开源的
    zoharSoul
        20
    zoharSoul  
       70 天前
    redis 队列是什么? 你是搞 php 的?
    zhenjiachen
        21
    zhenjiachen  
       70 天前
    正在做异步任务相关的功能,用上了 temporal 来做
    ronen
        22
    ronen  
       70 天前
    @zoharSoul 高版本 redis 也开始支持队列了。 我没见公司有人用,但是看到过介绍
    Vaspike
        23
    Vaspike  
       70 天前
    第一个不建议, 如果网络波动或者关闭连接或者就会 broken pipe
    但最佳方案我也等大佬来解答
    Vaspike
        24
    Vaspike  
       70 天前
    @Vaspike “或者“客户端中途关闭连接”就会“
    k9982874
        25
    k9982874  
       70 天前
    这跟语言无关,楼上已经提过 websocket 了
    Keystroke
        26
    Keystroke  
       70 天前
    30s 的同步接口?
    inframe
        27
    inframe  
       70 天前   ❤️ 1
    走 http event stream 下发,类似 ws
    fffq
        28
    fffq  
       70 天前
    sse or ws
    koujianshusheng
        29
    koujianshusheng  
       70 天前
    任务状态记录下来比较好,走 mysql 也行啊,搭配上 go 的 for select +子协程 ,再写个回调函数岂不美滋滋
    testliyu
        30
    testliyu  
       70 天前
    我这边也有处理长任务的需求,但我这个不需要响应,拷贝 db 的,我做成了 controller 触发内部异步调用
    zhengfan2016
        31
    zhengfan2016  
    OP
       70 天前
    @zoharSoul 还真是,我 21 年带专毕业就入职 php 公司,后端基本就是 mysql 和 redis 那一套,工作中接触了 vue ,后面读了两年本科,转成了前端,前端行情不好,现在研究 go ,打算转 go 了
    czsas
        32
    czsas  
       69 天前
    temporal
    yuwangG
        33
    yuwangG  
       69 天前   ❤️ 1
    hf 早期用的 websocket 现在用的 sse
    zoharSoul
        34
    zoharSoul  
       69 天前
    @zhengfan2016 #31
    哈哈 我也是无意中注意到的, 好像只有 php 习惯用 redis 搞队列..
    别的 go java 什么的都没有这个习惯
    ca2oh4
        35
    ca2oh4  
       56 天前
    http server push
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5458 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 33ms · UTC 03:05 · PVG 11:05 · LAX 20:05 · JFK 23:05
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.