With replicas, concurrent `.stream()` events pile onto one app process

在使用进程执行器并开启多副本( executor="process" + GRADIO_PROCESS_REPLICAS=2 )时,多个用户并发调用 .stream() 事件通常会被集中分配到同一个 app 进程,导致进程间负载不均;优先排查副本调度逻辑与 Gradio 版本。

快速结论:在使用进程执行器并开启多副本(executor="process" + GRADIO_PROCESS_REPLICAS=2)时,多个用户并发调用 .stream() 事件通常会被集中分配到同一个 app 进程,导致进程间负载不均;优先排查副本调度逻辑与 Gradio 版本。

适用环境:Gradio 7.0-dev(提交 121688c15),Linux,进程执行器 executor="process",环境变量 GRADIO_PROCESS_REPLICAS=2。Issue 未提供 Python、CUDA、显卡等信息。

最快修复方案:升级到包含 #14022 修复的 Gradio 7.0-dev 或更高版本;该修复已合入 7.0-dev,随 Gradio 7 发布。

注意事项:Issue 中该修复仅合入 7.0-dev,未说明是否回移植到旧版本;如果仍停留在出问题的 7.0-dev 提交,升级前需确认实际版本已包含 #14022。

问题场景

用户在 Linux 上以进程执行器启动 Gradio 应用,并设置 GRADIO_PROCESS_REPLICAS=2,使用 gr.Image(sources=["webcam"], streaming=True) 配合 cam.stream(...) 的 .stream() 事件。当两个浏览器窗口先后开始摄像头推流、或通过 HTTP 并发驱动两个流时,第二个用户的流通常被放到第一个用户所在的 app 进程,另一个进程保持空闲。

报错原文

With replicas, concurrent `.stream()` events pile onto one app process

原因分析

根因在网关的进程槽位计数方式。处理 /stream/{event_id} 的 forward_event 只在一次调用运行期间占用进程槽位,调用返回后即释放;而流在两次 chunk 之间不持有任何进程槽位。于是 Pool.can_start 在两个进程上看到相同的空闲计数,新会话被分配到第一个进程并一直留在那里。调度其他部分则是按流的整个生命周期计数的:队列会一直持有 concurrency_limit 槽位(按 limit × processes 缩放)直到流结束,生成器在两次 yield 之间也会保持进程槽位(link.held)。

另一处相关原因:流后续的 chunk 提交到 /stream/{event_id} 时,body 中没有 event id(浏览器端和 JS 客户端都不带),使 forward_event 无法区分后续 chunk 与新事件,因此无法简单按 body.event_id 保持槽位。

当 concurrency_limit=1 时,两条流在同一个进程内轮流执行,每次调用依次运行,各自吞吐约减半;不过队列本身允许两条流进入,以便每个进程各跑一条。对于在队列调用之外运行的处理程序(如 #13965 中的 gr.WebRTC),按进程的并发上限可能完全不起作用。

环境排查

  • 确认 Gradio 版本是否为 7.0-dev 且提交是否早于 #14022,可升级到包含该修复的版本。
  • 确认是否设置了 executor="process" 与 GRADIO_PROCESS_REPLICAS,以及副本数量是否符合预期。
  • 确认事件是否通过 .stream() 触发,并检查 concurrency_limit 设置。
  • 确认客户端类型:浏览器或 JS 客户端发送的后续 chunk 请求不含 event id,这会影响槽位判定。
  • Issue 未提供 Python、CUDA、PyTorch、显卡等信息,这些项目无法据此排查。

解决步骤

  1. 记录当前 Gradio 版本,确认是否处于受影响的 7.0-dev 提交(Issue 中为 121688c15)。
  2. 升级到已合入 #14022 的 Gradio 版本(7.0-dev 之后或 Gradio 7.0 发布版),不要继续使用出问题的开发提交。
  3. 使用 Issue 中的最小复现脚本,以 GRADIO_PROCESS_REPLICAS=2 python app.py 启动应用。
  4. 打开两个浏览器窗口,先在第一个窗口启动摄像头,再在第二个窗口启动,观察输出中显示的进程 ID 是否不同。
  5. 如果升级后仍复现,收集版本信息与复现日志,回到原 Issue 或新开 Issue 反馈;Issue 中暂无其他已验证的一步修复方案。

验证方法

按复现步骤在两个窗口并发启动摄像头,Textbox 中“Handled by”的进程 ID 应当分别对应两个不同的进程,而不再都落在同一个进程;也可按 Issue 描述通过 HTTP 驱动两条流,确认第二个流未被分配到第一条流所在进程。确认现象消失即说明修复生效。

参考来源

gradio-app/gradio #14021

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 31855

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注