执行器 (Executor)

执行器是 OOMOL 中执行区块代码的运行时引擎。

什么是执行器

执行器是负责加载和执行区块代码的运行时组件。它充当 OOMOL 工作流编排系统(OOCANA)与实际代码执行环境之间的桥梁。

每种代码语言环境都有相应的执行器实现。当流程中的节点被触发时,执行器会加载指定的入口文件并调用定义的函数来执行区块的逻辑。

在 OOMOL 架构中的位置

在 OOMOL 系统架构中,执行器在连接多个组件方面发挥着关键作用:

OOMOL Studio (界面层)

OOCANA (工作流引擎)

执行器 (运行时层)

OVM (容器环境)
  • OOMOL Studio 提供可视化界面供用户设计工作流
  • OOCANA 编排执行顺序并管理区块之间的数据流
  • 执行器 加载并执行每个区块的实际代码
  • OVM 提供代码运行的隔离容器环境

执行器类型

OOMOL 目前支持两种类型的执行器,每种都针对特定的编程语言设计:

Python 执行器

  • 执行 Python 代码
  • 默认入口函数: main
  • 支持通过 Poetry 安装的标准 Python 库和包
  • 可以使用变量类型接口在区块之间传递复杂的 Python 对象(如 DataFrame、pandas 实例)

Node.js 执行器

  • 执行 JavaScript/TypeScript 代码
  • 默认入口函数: default export function
  • 支持 npm 包和具有完整类型检查的 TypeScript
  • 可以使用变量类型接口在区块之间传递复杂的 JavaScript 对象

与其他概念的关系

执行器与区块

每个区块都配置了一个执行器,用于指定:

  • 使用哪个语言运行时(Python 或 Node.js)
  • 包含代码的入口文件
  • 要调用的函数名称
  • 是否在独立进程中运行

执行器配置是区块元数据的一部分,可以在区块配置面板中修改。

执行器与 OOCANA

OOCANA(工作流引擎)与执行器协调管理工作流执行:

  1. OOCANA 分析流程以根据数据依赖关系确定执行顺序
  2. 当区块准备执行时,OOCANA 准备输入数据
  3. OOCANA 使用区块的代码和输入数据调用相应的执行器
  4. 执行器运行代码并将输出数据返回给 OOCANA
  5. OOCANA 将输出传递给下游区块或缓存以供将来使用

进程管理

执行器的关键特性之一是智能进程管理,它可以优化资源使用和执行性能。

同进程执行

当 OOMOL Studio 运行工作流时,它会自动检测优化机会。如果连续的区块满足以下条件,它们将在同一进程中执行:

  • 使用相同的编程语言实现
  • 对于共享区块,它们必须属于同一个包

同进程执行的好处:

  1. 资源效率: 减少内存开销和启动时间
  2. 直接变量传递: 上下游区块可以直接传递代码变量,无需序列化/反序列化
  3. 性能提升: 消除进程间通信的开销

独立进程执行

用户可以通过独立进程配置手动配置区块在独立进程中运行。这在以下场景中很有用:

  • 隔离可能不稳定的代码
  • 管理内存密集型操作
  • 强制执行严格的资源限制
  • 独立调试特定区块

执行器之间的数据传递

执行器之间的数据传递取决于它们是否共享相同的进程和语言环境:

JSON 序列化(跨语言或跨进程)

当区块在不同的语言环境或独立进程中运行时,数据通过 JSON 序列化传递:

区块 A (Python) → JSON → 区块 B (Node.js)
区块 A (同语言,独立进程) → JSON → 区块 B

特点:

  • 所有语言之间的通用兼容性
  • 除变量类型外的所有接口类型都可以序列化
  • 序列化/反序列化有轻微的性能开销
  • 数据可以缓存供后续运行使用

直接变量传递(同语言,同进程)

当区块共享相同的语言和进程时,它们可以使用变量类型接口直接传递数据:

区块 A (Python) → 变量引用 → 区块 B (Python)

特点:

  • 最高性能(无序列化开销)
  • 可以传递无法序列化的复杂对象(例如文件句柄、数据库连接)
  • 变量遵循引用传递语义(修改会影响所有区块)
  • 无法缓存(上游区块将始终重新执行)
  • 降低区块的可移植性(仅限于同语言工作流)
信息

变量类型接口无法缓存,因为它们引用的是代码执行环境中仅在运行时存在的对象。这意味着如果下游区块依赖于变量接口,它将始终触发上游区块执行,无论缓存设置如何。

执行器生命周期

了解执行器生命周期有助于调试和优化工作流性能:

  1. 初始化: 当区块首次触发时,执行器初始化运行时环境
  2. 代码加载: 执行器加载区块配置中指定的入口文件
  3. 函数调用: 执行器使用输入参数和 Context 对象调用指定的函数
  4. 执行: 区块代码运行,可能访问文件系统、网络或其他资源
  5. 输出收集: 执行器从区块函数收集输出值
  6. 清理: 执行完成(或失败)后,执行器根据需要执行清理
  7. 进程复用或终止: 根据配置,进程可能被复用于后续区块或终止

配置和最佳实践

有关配置执行器的详细信息,请参阅:

最佳实践:

  1. 尽可能将同语言区块组合在一起,以利用同进程优化
  2. 谨慎使用变量类型接口 - 它们可以提高性能,但会降低区块的可复用性
  3. 为资源密集型或可能不稳定的代码启用独立进程执行
  4. 遵循 OOMOL 提供的代码模板以确保正确的执行器集成: