基于 Worker 子进程的算子物理隔离 (Node Isolation with Workers)
本篇文档是指导开发者将算子库运行在物理隔离 (Isolated) 环境下的权威实操指南:让你的算子库运行在独立的 Python 子进程中,从根源上杜绝你的依赖库版本(如 torch、transformers、diffusers、特定 CUDA 轮子)与画布中其他算子库发生版本冲突。
用户可以在编辑器的算子库设置中通过 Shared (共享/主进程) / Isolated (隔离/子进程) 下拉菜单自主切换;在底层,隔离模式的算子库均由专用的 Worker 子进程托管调度。
核心工程术语 (Vocabulary)
- Orchestrator (主编排进程):Griptape Nodes 的核心 Python 主进程。全面掌控有向无环工作流图 (DAG)、拓扑连线、参数注册表、全局配置以及 Secrets 密钥;图形编辑器直接与编排进程保持长连接;
- Worker subprocess (Worker 独立子进程):专用于执行特定算子库计算逻辑的独立 Python 进程。每个开启隔离模式的算子库均拥有独占的 Worker 进程,并通过 WebSocket 内部总线 (Bus) 与主编排进程双向通信;
process与aprocess:算子计算核心入口。开发者如常重写process(self),底层会自动将其包装为协程挂载至 Worker 进程的事件循环上运行;- Schema probe (静态模式探测):算子库装载时的单次预检阶段。Worker 进程会预先将所有注册的算子类无参实例化一次,以向主编排进程汇报其输入输出端口参数布局。此过程发生在任何实际计算执行之前。
什么时候应该开启 Worker 物理隔离?
✅ 强烈建议开启隔离的场景:
算子库强依赖锁死特定版本的重型深度学习/多媒体包(如 torch==2.4.1、transformers、diffusers、accelerate、peft、特定编译版本的 CUDA Wheels 等),且需要与可能依赖不同版本的其他三方算子库在同一画布中共存。
❌ 建议保持在主进程 (Shared) 的场景:
算子库仅依赖轻量、高向前兼容的标准开源库(标准库、pydantic、griptape 核心包、常规 HTTP 网络请求工具等)。保留在主进程运行可免去跨进程序列化与 IPC 管道通信开销。
如何在算子库清单中声明开启隔离
在 griptape_nodes_library.json 的 metadata.declarations 中声明两个核心标签:
worker_mode_compatibility:声明算子库是否在技术架构上支持 Worker 模式:COMPATIBLE:既能在主编排进程中运行,也能在 Worker 子进程中稳定运行;INCOMPATIBLE:严禁在 Worker 中运行,强制绑定主进程。suggested_worker_mode:声明未手动覆写时的出厂默认启动位置:WORKER:推荐并默认启动在独立 Worker 子进程中;ORCHESTRATOR:默认启动在主编排进程中。
{
"name": "My Diffusion Library",
"library_schema_version": "0.10.0",
"metadata": {
"author": "AI Team",
"description": "专有生图重型算子库",
"library_version": "0.1.0",
"engine_version": "0.85.0",
"declarations": [
{
"type": "worker_mode_compatibility",
"compatibility": "COMPATIBLE"
},
{
"type": "suggested_worker_mode",
"mode": "WORKER"
}
],
"dependencies": {
"pip_dependencies": [
"torch==2.4.1",
"transformers==4.45.2"
],
"pip_install_flags": [
"--extra-index-url",
"https://download.pytorch.org/whl/cu121"
]
}
},
"nodes": []
}
版本锁定原则:开启 Worker 隔离的灵魂在于锁死确定性版本(如 torch==2.4.1 而非模糊的 torch>=2.0),确保跨机器装载时绝对纯净。
跨进程物理隔离付出的工程代价 (The Trade-offs)
开启隔离意味着接受跨进程网络往返与序列化税 (Serialization Tax)。当 Worker 节点在计算中途需要读取主编排器持有的工作流状态时,必须通过内部 WebSocket 发起网络请求,这会带来微秒至毫秒级的 IPC 开销,且拉取到的数据属于“读后即刻失效的快照 (Stale-by-call)”:
- 通过参数传递数据,严禁在计算时反查画布连线状态:不要在
process()内部试图查询其他节点的状态或画布宏观连线,一切必要素材必须作为标准的输入端口参数拉入; - 所有跨进程操作必须通过解耦请求 (Requests) 边界流转:如需覆写全局状态,必须通过
GriptapeNodes.handle_request(SetParameterValueRequest(...))发起。
传递无法序列化的内存大对象 (Unserializable Values)
GPU 现存中的 Diffusion Pipeline、Latent 潜空间张量、PyTorch Model 句柄等对象根本不存在纯文本序列化形式,绝对无法作为常规参数直接通过 WebSocket 跨进程传输!
官方给出的架构级解决方案:
将产出此类大对象的输出参数标记为 Parameter(serializable=False)。引擎在底层会将该对象牢牢钉在产出它的 Worker 进程内存中,仅向跨进程总线广播一个轻量级的访问 Key (Token);下游在同一进程内接入该 Key 的算子能无感、极速恢复该原生对象——详见 非序列化数据传递指南。
开发者必须铭记的生命周期重大变化
1. __init__ 会在算子库装载时的预检阶段提前执行
Worker 进程启动时会立刻执行一次无参 Schema 预检以探测端口,因此:
- 严禁在 __init__ 中执行任何物理 I/O(严禁发 HTTP 请求、严禁读写大文件、严禁校验数据库连接);超时会导致该算子直接被引擎静默注销丢弃!
- 严禁在 __init__ 中触发内部事件总线请求(会引发死锁并触发 reentrant-bus-in-init 致命错误);
- __init__ 必须且只能用于注册参数:self.add_parameter(...) 是该阶段唯一合法的行为。
2. 算子实例属于无状态瞬态对象 (Stateless Nodes)
每一次执行请求到达时,Worker 都会临时实例化一个全新的干净算子对象,运行完 process() 后立即彻底销毁垃圾回收!
- ❌ 严禁使用 self.my_state = ... 在跨次运行之间记忆状态(下一轮运行该属性复归为空);
- ✅ 跨轮次持久化数据必须托管给主编排进程:在 process() 中通过 SetParameterValueRequest 更新,下一轮运行会自动注入回 self.parameter_values。
3. 计算期间直接修改参数列表无法同步回主进程
在 process() 内部直接调用 self.add_parameter(...) 仅作用于 Worker 本地即将被销毁的临时对象,主编排器完全无法感知!
若需在运行期动态长出端口,必须派发专属请求:
- AddParameterToNodeRequest
- RemoveParameterFromNodeRequest
隔离就绪状态自检清单 (Isolation Checklist)
- [ ] 在
metadata.declarations中声明worker_mode_compatibility: COMPATIBLE并指定suggested_worker_mode: WORKER; - [ ] 确保
__init__内绝对没有任何网络 I/O、磁盘读取或总线请求; - [ ] 严禁在
process()中直接调用add_parameter,必须改用AddParameterToNodeRequest; - [ ] 跨节点计算数据一律通过
Parameter端口流入,绝不在运行时盲目反查外部工作流; - [ ] 不依赖连线回调钩子(
after_incoming_connection等),因为 Worker 模式下连线钩子由主进程哑桩接管,子进程内不执行; - [ ] 强依赖的重型依赖包已锁定具体发布版本号。
严格模式 (Strict Mode) 错误侦测矩阵
本地调试启动引擎时,控制台输出带有 Worker-<id> 前缀的日志行是检验隔离健壮性的金标准:
| 严格模式检查规则 | 编排主进程表现 | Worker 子进程表现 | 违规后果与整改指引 |
|---|---|---|---|
reentrant-bus-in-init |
❌ ERROR | ❌ ERROR | 致命违规:在 __init__ 中调用了总线;该类直接被引擎丢弃卸载! |
parameter-mutation-during-aprocess |
⚠️ WARNING | ❌ ERROR | 致命违规:在计算体内未走请求直接原地修改参数;导致该次运算直接判定失败! |
connection-hooks-inert-on-worker |
⚠️ WARNING | ⚠️ WARNING | 告警:重写的连线生命周期钩子在 Worker 模式下处于静默未激活状态。 |
value-hooks-execute-only-on-worker |
⚠️ WARNING | ⚠️ WARNING | 告警:数值变更钩子仅在 Worker 计算时执行,无法参与前端画布的实时响应。 |
parameter-behaviors-dropped-in-schema |
⚠️ WARNING | ⚠️ WARNING | 提示:挂载的自定义校验器/转换器未同步给主进程,仅在 Worker 本地生效。 |