ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

ComfyUI-zhenzhen 源码解析:30 路并发提交框架,有界线程池如何玩转稳定并发

ComfyUI-zhenzhen 源码解析:30 路并发提交框架,有界线程池如何玩转稳定并发

【免费下载链接】Comfyui-zhenzhen

https://ai.t8star.org/register?aff=dP7j Comfyui的各种平价API调用节点,支持seedance2.0(满血版,支持真人,不排队)

项目地址:https://gitcode.com/gh_mirrors/co/Comfyui-zhenzhen
点击查看免费下载

ComfyUI-zhenzhen 是一款面向 ComfyUI 的平价 AI 模型 API 调用插件,内置并发提交框架:图片任务最多 30 路、视频任务最多 10 路同时提交,靠"有界线程池 + 信号量闸门"保证不压垮服务器。本文用通俗的方式带你读懂它的并发提交机制、30 路上限的设计,以及如何在 ComfyUI 中实际使用这些并发节点。

为什么要做并发提交框架?

在 ComfyUI 里调用一次生图或生视频 API,通常需要提交任务 → 轮询状态 → 下载结果三个步骤,耗时从几秒到几分钟不等。如果你的工作流里要生成 30 张不同提示词的图片,逐个执行会非常漫长。

zhenzhen 插件的解法是:给每个生成节点自动"克隆"一个Concurrent Submit(并发提交)节点,把真正耗时的 API 调用丢进后台线程池,同时最多 30 路图片 / 10 路视频并行跑,最后由一个收集节点按原始顺序把结果收回来。

插件加载时在init.py 里完成节点注册:把Comfly.py中的原始节点,加上 ComflyConcurrent.py 自动生成的并发节点,合并进 ComfyUI 的节点表——整个过程对原有节点零侵入。

三大件:Submit 节点、有界线程池、Collect 节点

整个框架由三部分组成,就像餐厅里的"点单 → 后厨 → 传菜":

组件类比源码位置
ComflyConcurrent_xxx_Submit节点点单:只登记订单,立刻返回_make_submit_class
_BoundedExecutor有界线程池后厨:限流做菜_BoundedExecutor
Concurrent Collect收集节点传菜:按桌号顺序上菜ComflyConcurrentImageAwait / ComflyConcurrentVideoAwait

Submit 节点并不真正执行生成逻辑。它的submit()方法把原始节点类(ORIGINAL_NODE_CLASS)和参数打包后扔进线程池,然后立刻返回一个轻量的任务句柄ConcurrentTask(本质是concurrent.futures.Future)。所以在画布上,一连串 Submit 节点会瞬间跑完,真正的时间花在后台。

有界线程池:为什么叫"有界"?

无界并发看似更快,但对 API 服务器是灾难:几十路请求瞬间涌入,轻则触发限流,重则把服务打挂。zhenzhen 用了一个精巧的"双闸门"设计:

  1. 线程池限宽:ThreadPoolExecutor固定 30(图片)/ 10(视频)个工作线程,同一时刻最多这么多任务在真正执行。
  2. 信号量限量:BoundedSemaphore(max_workers + max_pending)控制"正在执行 + 排队中"的任务总数上限,默认等于线程数,即不额外排队(见 BoundedSemaphore 初始化)。

submit()提交任务时采用非阻塞轮询(每 0.25 秒尝试一次拿锁),拿不到配额就继续等,期间还会检查两件事:

  • 线程池是否已被关闭(比如插件被重新加载);
  • ComfyUI 是否收到Cancel 中断信号(comfy.model_management.processing_interrupted,见 _processing_interrupted)。一旦你点了取消,排队中的任务会被及时放行并抛出中断异常,不会让你干等。

线程数还支持环境变量微调:COMFLY_IMAGE_CONCURRENCY、COMFLY_VIDEO_CONCURRENCY(以及对应的*_PENDING),取值会被限制在 1~128 的合理区间(见 环境变量读取)。

收集节点:槽位顺序与两种失败模式

收集节点ComflyConcurrent_Image_Await有task_1~task_30共 30 个输入槽(视频为 10 个),每个槽接一个 Submit 节点输出的任务句柄。核心逻辑在 _collect:

  • 按槽位还原顺序:用concurrent.futures.wait轮询等待,谁先完成谁先被记录,但最终按task_1、task_2… 的编号放进输出槽image_1、image_2…。第 3 个任务最先跑完,它也会乖乖排到第 3 个输出里。
  • placeholder 占位:每个槽先放一张空白占位图(或空视频适配器),未连接的槽标记为not_connected,不会让整条工作流崩溃。
  • 进度条:通过comfy.utils.ProgressBar实时刷新"已完成 X / 共 N",前端能看到整体进度。

failure_mode提供两种策略:

模式行为适用场景
fail_fast(默认)任一任务失败 → 取消其余排队任务,整节点报错任务相互依赖,宁缺毋滥
placeholder失败槽位保留占位媒体,其余照常输出批量出图,允许个别失败

错误信息还会先经过一层"脱敏"处理:API Key(sk-...)和 URL 会被替换成[REDACTED_API_KEY]/[REDACTED_URL],最多保留 500 字符(见 _sanitize_message),避免敏感信息泄露到界面和日志里。

最后一个输出是status:一段 JSON 字符串,逐槽记录success/failed/not_connected状态、对应节点名和脱敏后的错误摘要,方便排查"30 张里哪张挂了"。

并发上限怎么定的?30 路图片、10 路视频

注册逻辑会扫描插件里所有节点(见 节点注册循环),满足以下条件的才会被自动生成并发版本:

  • 主输出类型是IMAGE或VIDEO(音频、3D 等多媒体节点不适用);
  • 来自插件内置的白名单模块(Comfly、seedance_low_price_nodes、midjourney_low_price_nodes等,见 ALLOWED_MODULES);
  • 分类以zhenzhen开头,且节点未显式声明COMFLY_CONCUNDENT_DISABLED(COMFLY_CONCURRENT_DISABLED)。

30 / 10 这两个上限是刻意保守的:

  • 图片 API 响应相对快,30 路可以在几十秒内消化完一批素材,同时不超过常见服务商的速率限制;
  • 视频 API 单任务耗时长(分钟级)、占用上游队列大,10 路既能显著提升吞吐又不会长时间霸占配额。

新节点接入框架几乎是"自动"的——这也是为什么插件更新日志里反复出现"自动接入现有 30 路图片并发 / 10 路视频并发提交框架"的描述。

实际使用:30 路并发的示例工作流

仓库内置了两份空 Key 示例,可直接导入 ComfyUI:

  • workflow/并发示例-图片多任务(30路上限).json:API Settings → 2 个ComflyConcurrent_Comfly_zhenzhen_image_nb_lowprice_Submit(任务 A / 任务 B)→ComflyConcurrent_Image_Await(最多 30 路)→ SaveImage。
  • workflow/并发示例-视频多任务(10路上限).json:同样的结构换成视频提交与收集节点。

使用步骤很简单:

  1. 把示例里成对的 Submit 节点复制成 N 份(N ≤ 30),分别填入不同的提示词 / 参数;
  2. 依次连到ComflyConcurrent_Image_Await的task_1~task_N槽位;
  3. 运行工作流,提交阶段瞬间完成,随后在进度条上观察后台并发跑完的情况;
  4. 输出端会按槽位顺序给出 N 张图片和一段status汇总。

前端脚本还做了名称兼容:凡是ComflyConcurrent_XXX_Submit形式的节点,会剥掉前后缀还原出原始节点名来匹配动态 UI(例如 web/js/dynamic_widget_ui.js 里的originalNodeName逻辑),所以并发节点和原始节点在界面上的控件表现完全一致。

稳定性验证:测试如何证明"真的并发"

插件的测试套件对并发框架做了三层验证:

  • 上限探测:用假节点 + 屏障(Barrier)确认图片池最大同时在跑数恰好等于 30、视频池等于 10,且槽位顺序不乱(见 test_image_pool_reaches_30_and_preserves_slot_order);
  • 失败与脱敏:注入异常验证fail_fast抛错、placeholder兜底,以及 API Key / URL 不出现在状态输出中(见 test_legacy_future_and_failure_modes_are_supported_and_redacted);
  • 真实付费冒烟:tests/live_concurrent_nodes.py 会真实提交 2 路图片 + 2 路视频任务,记录各请求的时间区间,断言两路请求在时间上有重叠——这直接证明了并发确实发生,而不是排队串行。

此外,底层 HTTP 会话按线程隔离(thread-local)且连接池有尺寸上限,多线程共用不会互相踩踏,这部分同样被测试覆盖(见 test_seedance_sessions_are_thread_local_with_sized_pools)。

小结

ComfyUI-zhenzhen 的并发提交框架可以概括为一句话:Submit 节点秒回任务句柄,有界线程池按 30 / 10 路上限并行执行,Collect 节点按槽位还原顺序并给出状态汇总。有界设计(线程数 + 信号量配额 + 中断检查)让它既快又稳:不会打爆 API 配额,取消操作也能及时生效,敏感信息不会外泄。

对新手来说,你不需要理解每一行实现——找到带Concurrent Submit的节点、参考 workflow/并发示例-图片多任务(30路上限).json 连线,就能把"一张张排队等"变成"一批批同时出"。

【免费下载链接】Comfyui-zhenzhen

https://ai.t8star.org/register?aff=dP7j Comfyui的各种平价API调用节点,支持seedance2.0(满血版,支持真人,不排队)

项目地址:https://gitcode.com/gh_mirrors/co/Comfyui-zhenzhen
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进