ComfyUI-zhenzhen 源码解析:30 路并发提交框架,有界线程池如何玩转稳定并发
【免费下载链接】Comfyui-zhenzhen
https://ai.t8star.org/register?aff=dP7j Comfyui的各种平价API调用节点,支持seedance2.0(满血版,支持真人,不排队)
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 用了一个精巧的"双闸门"设计:
- 线程池限宽:
ThreadPoolExecutor固定 30(图片)/ 10(视频)个工作线程,同一时刻最多这么多任务在真正执行。 - 信号量限量:
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:同样的结构换成视频提交与收集节点。
使用步骤很简单:
- 把示例里成对的 Submit 节点复制成 N 份(N ≤ 30),分别填入不同的提示词 / 参数;
- 依次连到
ComflyConcurrent_Image_Await的task_1~task_N槽位; - 运行工作流,提交阶段瞬间完成,随后在进度条上观察后台并发跑完的情况;
- 输出端会按槽位顺序给出 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(满血版,支持真人,不排队)
相关推荐
Comfyui-zhenzhen 并发节点完全指南:30 路图片 + 10 路视频并发提交搭建与示例工作流
Comfyui zhenzhen 并发节点完全指南:30 路图片 + 10 路视频并发提交搭建与示例工作流 在 ComfyUI 中批量调用大模型 API 时,一
Kstry的并发框架
Kstry的并发框架 Kstry的并发框架是其核心能力之一,通过灵活的任务调度和线程管理机制,实现了高效的流程编排和执行。本文将从设计原理、并行网关与包含网关的
后端任务调度工作流自动化Rust并发代码分析:Flowistry如何处理多线程交互
Rust并发代码分析:Flowistry如何处理多线程交互 在多线程Rust开发中,开发者常面临数据竞争、内存安全和代码可读性的三重挑战。Flowistry作为
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考