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

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

  •  
  •   zhengfan2016 · 2025 年 5 月 22 日 · 4082 次点击
    这是一个创建于 246 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

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