ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

iii Engine 与 SDK Worker 的 WebSocket 线级协议全解:端口、消息帧、调用生命周期与可观测性指标

iii Engine 与 SDK Worker 的 WebSocket 线级协议全解:端口、消息帧、调用生命周期与可观测性指标 iii Engine 与 SDK Worker 的 WebSocket 线级协议全解端口、消息帧、调用生命周期与可观测性指标【免费下载链接】iiiEffortlessly compose, extend, and observe every service in real-time for the first time ever.项目地址: https://gitcode.com/GitHub_Trending/mo/iii本文导读本文是 iii 项目中 Engine引擎与各语言 SDK WorkerNode / Python / Rust / Browser之间线级通信协议的权威技术指南。核心内容源自 docs/0-16-0/sdk-reference/engine-sdk.mdx.skill.md并以其为骨架深入 engine/src/protocol.rs 等源码进行验证与扩充。读完本文你将掌握Engine 监听的四个端口各自的职责、Worker 建连与注册的完整流程、全部 11 种消息帧的 JSON 结构与方向、TriggerAction三种路由语义同步 / Void / 入队、ErrorBody的错误码体系、engine::*内置发现函数与发现触发器以及 Engine 侧无条件收集的 OpenTelemetry 指标命名规范——即使不用任何语言 SDK也能手写一个兼容的协议客户端。绝大多数项目通过语言 SDKNode / Python / Rust / Browser与引擎通信从不直接接触协议本身本文档描述的线级 shape 正是这些 SDK 序列化的唯一事实来源source of truth。可观测性内省traces、logs、metrics、采样规则、alerts、rollups由iii-observabilityworker 端到端负责Engine 侧只负责采集与暴露本节所述的底层指标。一、连接端口Engine 自持三个端口 可观测 worker 一个端口Engine 进程自身绑定三个端口另有iii-observabilityworker 提供一个指标端口通常与 Engine 同容器暴露端口绑定方用途3111engineREST API。3112engineStream APIWebSocket消费侧流订阅。49134engineSDK WebSocket即iii_sdk::register_worker打开的端口。9464iii-observabilityworkerPrometheus 指标端点通常从与 engine 相同的容器暴露。Console UI 运行在3113由iii console单独启动。从源码看49134是引擎 SDK WebSocket 的默认端口桥接配置中bridge_url默认值即为ws://localhost:49134见 engine/src/workers/configuration/adapters/bridge.rs远程引擎桥接的 README 也以bridge_url: ${REMOTE_III_URL:ws://localhost:49134}记录engine/src/workers/configuration/README.md。3112是 Stream worker 的默认监听端口其配置默认值同样写为{ port: 3112, host: 127.0.0.1 }engine/src/workers/configuration/README.md。端口与 Worker 网格的关系engine/src/workers/engine_fn/README.md 将 iii 描述为WebSocket 路由的 worker 网格一个 engine 进程默认端口49134持有每个已连接 worker、每个 worker 暴露的函数以及绑定到它们之上的每个触发器的实时注册表。Worker 是独立的 OS 进程打开到 engine 的 WebSocket 并注册 Functionsservice::name处理器与 Triggers触发调用这些函数的事件。不存在直接的 worker 到 worker 流量——每一次调用都经由 engine 路由这使得任何 worker 的语言、运行时和物理位置对调用方完全不可见。二、连接流程注册重放 → 元数据发布 → 双向通信一个 Worker 建立连接的流程如下Worker 打开 SDK WebSocket默认ws://127.0.0.1:49134发送它内存中持有的所有注册项每条RegisterFunction、RegisterTrigger和RegisterTriggerType即它打算暴露的每一个函数、触发器绑定和触发器类型。Worker 调用engine::workers::register发布自身元数据runtime、version、OS、PID、isolation。Engine 回复一个携带已分配 UUID 的WorkerRegistered { worker_id }帧。此后连接变为双向engine 向 worker 推送InvokeFunction帧worker 向 engine 推送InvocationResult、额外的注册或注销。从协议源码看注册消息还带有 namespace 语义protocol.rs 中RegisterTrigger可携带namespace目标函数解析的命名空间缺省即 engine 默认命名空间与trigger_namespace触发器类型提供方的命名空间RegisterTriggerType的namespace缺省时取注册连接的命名空间。默认命名空间常量为defaultprotocol.rs。重连Reattach协议值得一提的协议细节是Reattach消息protocol.rsWorker 重连时作为重连后的第一条消息、在注册重放之前发送携带previous_worker_id和reattach_token——这两个值是 engine 在上一次连接的WorkerRegistered中交给该 worker 的。engine 随即退役旧连接与断连相同的清理流程使重放落在干净状态上而不是与旧连接的清理竞速。token 是必需的worker id 是公开可发现的而 token 只在之前的连接 socket 上发送过。Reattach与WorkerRegistered的 token 字段均为可选Option保证新旧 SDK/engine 的版本错配互操作对应单元测试见 protocol.rs。三、消息类型JSON 对象以message_type判别每一帧都是一个 JSON 对象用message_type字段判别wire 上按小写编码。完整集合定义在 engine/src/protocol.rs 的Message枚举上使用#[serde(tag type, rename_all lowercase)]序列化帧方向用途RegisterFunctionworker → engine使某个函数可被function_id调用。UnregisterFunctionworker → engine撤销先前注册的函数。RegisterTriggerworker → engine将函数绑定到触发器实例。UnregisterTriggerworker → engine撤销触发器绑定。TriggerRegistrationResultengine → worker对RegisterTrigger的确认 / 错误。RegisterTriggerTypeworker → engine声明 worker 宣传的新触发器类型。RegisterServiceworker → engine在 service id 下对相关函数分组。InvokeFunctionengine → worker携带 payload 调用已注册函数。InvocationResultworker → engine回传函数结果或错误。WorkerRegisteredengine → worker确认 worker携带分配的worker_id。Ping/Pong双向存活探测防止空闲连接超时。源码中还包含两个文档表格之外的消息Reattach上文所述重连协议与RegistrationRejected注册被拒携带code与命名空间等上下文见 protocol.rs。RegistrationRejected的 code 常量在源码中定义但尚未正式发射如WORKER_NAMESPACE_CONFLICT、FUNCTION_NAMESPACE_CONFLICT见 protocol.rs代码注释明确说明其推迟到 SDK 学会处理后端到端语义再启用。3.1RegisterFunction{ message_type: register_function, id: math::add, description: Add two numbers., request_format: { type: object, properties: { a: { type: number }, b: { type: number } } }, response_format: { type: object, properties: { c: { type: number } } }, metadata: { owner: math-team }, invocation: null }id必填。description、request_format、response_format、metadata可选供 iii console 与 agent 可读 skills 消费。invocation为外部 HTTP 函数保留HttpInvocationRef进程内处理器置null。从源码看HttpInvocationRef还支持url必填、method默认 POST、timeout_ms、headers映射与auth见 protocol.rs。protocol.rs 的单元测试验证了外部 Lambda 风格的注册invocation携带 URL、timeout_ms: 30000、自定义头与{type:bearer,token_key:LAMBDA_TOKEN}认证配置可完整反序列化。3.2RegisterTrigger{ message_type: register_trigger, id: math::addhttp, trigger_type: http, function_id: math::add, config: { api_path: /math/add, http_method: POST }, metadata: null }config是触发器类型相关的配置其形状由宣传该trigger_type的 worker 定义如http触发器由iii-http提供。engine 以携带可选error: ErrorBody的TriggerRegistrationResult应答。id在 engine 侧是唯一键且与触发类型解析绑定。3.3RegisterTriggerType{ message_type: register_trigger_type, id: webhook, description: HTTP webhook trigger, trigger_request_format: { type: object, ... }, call_request_format: { type: object, ... } }trigger_request_format触发器每个绑定的config的 JSON Schema。call_request_format触发器触发时投递给已绑定函数的 payload 的 JSON Schema。源码中这两个字段均可选skip_serializing_if Option::is_none并支持可选的namespace字段用于声明该提供方服务的命名空间protocol.rs。3.4InvokeFunction{ message_type: invoke_function, invocation_id: 9f3c…, function_id: math::add, data: { a: 2, b: 3 }, traceparent: 00-…, baggage: kv,…, action: { type: void } }invocation_id在Void调用上被省略worker 没有可应答的结果通道。traceparent与baggage携带 W3C 追踪上下文。action是路由标志见下文 Trigger actions缺省 /null表示同步。源码中的InvokeFunction还额外支持两个可选、向后兼容的字段protocol.rsmetadata按调用传递的元数据 sidecar作为独立参数投递给目标 handler不折叠进data相应测试验证了 metadata 与 data 的互不干扰与旧 peer 缺省兼容protocol.rs。namespace目标路由命名空间缺省即默认命名空间default测试验证了命名空间字段的序列化与遗留载荷兼容protocol.rs。3.5InvocationResult成功{ message_type: invocation_result, invocation_id: 9f3c…, function_id: math::add, result: { c: 5 }, error: null, traceparent: 00-…, baggage: kv,… }失败{ message_type: invocation_result, invocation_id: 9f3c…, function_id: math::add, result: null, error: { code: invocation_failed, message: boom, stacktrace: TraceError: … } }ErrorBody结构体由code、message与可选stacktrace组成protocol.rs。engine 今天会发射的ErrorBody.code值包括code含义invocation_failedhandler 抛出异常。invocation_stopped持有方 worker 在调用中途断开engine 取消在途调用并把该 code 透传给调用方。function_not_found函数未注册。function_not_invokable函数当前不可调用。TIMEOUT客户端侧超时。FORBIDDENRBAC 拒绝。invocation_stopped的发射路径在 engine/src/invocation/mod.rshalt_invocation从调用表中移除该 invocation 并向等待方发送ErrorBody { code: invocation_stopped, message: Invocation stopped }。FORBIDDEN在 engine/src/engine/mod.rs 的 RBAC 检查路径如 L1525、L1678、L1717与 engine/src/workers/engine_fn/mod.rs 中生成。此外源码还有引擎自有的NOT_FOUND错误码带歧义提示见 engine/src/workers/engine_fn/mod.rs用于内省函数的解析失败。四、Trigger actions同步 / Void / 入队三种路由语义InvokeFunction.action以type打标签在 wire 上小写编码Wire shape含义omitted /null同步worker 以InvocationResult应答。{ type: void }fire-and-forget无invocation_id无应答。{ type: enqueue, queue: math }经具名队列路由由iii-queue提供。源码中TriggerAction枚举定义为两个变体Enqueue { queue: String }与Void同样使用#[serde(tag type, rename_all lowercase)]protocol.rs。InvokeFunction的action字段是OptionTriggerAction且序列化时空值会被省略skip_serializing_if测试serialize_invoke_function_without_action_omits_field断言 JSON 中不出现action键protocol.rsenqueue 与 void 两种 action 均有专门的反序列化测试protocol.rs。五、调用生命周期Invocation lifecycle同步调用engine 分配invocation_id将InvokeFunction转发给持有方 worker并等待匹配的InvocationResult。Void actionengine 不带invocation_id转发永不期望应答。Enqueue actionengine 将调用交给队列 worker由队列持久化并按队列重试策略在订阅者上重新调用目标函数。从调用处理器看同步语义的实现由InvocationHandler维护一个ArcDashMapUuid, Invocation调用表handle_invocation登记调用、remove按 id 移除、halt_invocation在 worker 断连时主动取消engine/src/invocation/mod.rs。同一个文件中还体现了调用追踪的抑制策略观测类函数engine::traces::*、engine::logs::*等永不被追踪管道不能观测自身内建函数在进程内执行时仅当调用方提供了traceparent才发射callspanworker 路由的外部函数由 worker 自身发射 handler spanengine 侧抑制跨服务重复 span。六、Engine 发现函数Engine discovery functionsengine 在engine::*命名空间下注册一组内建函数用于内省与 worker 生命周期管理。定义于 engine/src/workers/engine_fn/mod.rs函数用途engine::channels::create创建流式 channel 的 reader / writer 对。engine::functions::list列出每个已注册函数可按include_internal过滤。engine::workers::list列出每个已连接 worker 及其指标。engine::triggers::list列出每个已注册触发器可按include_internal过滤。engine::trigger-types::list列出每个已注册触发器类型及其 config 与 call request schema。engine::workers::register发布调用方 worker 的元数据runtime、version、OS、PID、isolation。从源码看这一内省面比文档表格更丰富还包括engine::functions::info单 id 或批量function_ids最多 32 个保持请求顺序去重获取函数详情输出包含namespace、worker_name、request_schema、response_schema、metadata与registered_triggers批量中单个 id 失败不会拖垮整批返回forbidden/not_found标记见 engine_fn/mod.rs 与 L262-L290。engine::trigger-types::info、engine::registered-triggers::list/info、engine::workers::info等细粒度内省函数输入支持search大小写不敏感子串、prefixid 精确前缀、worker、runtime、status、namespace等多种过滤条件engine_fn/mod.rs。engine::workers::register的输入还支持name、description单行摘要会被engine::workers::list展示、telemetry、pid、isolation与路由namespaceengine_fn/mod.rs。搜索排序按命中质量分级id 锚定::段相等或前缀 id 子串 仅描述命中保证state::*排在任何只是描述里提到 state 的函数之上——LLM agent 自上而下阅读搜索结果时纯字母序会把相关命中埋没在偶然命中之下engine_fn/mod.rs。七、Engine 发现触发器Engine discovery triggers触发器触发时机engine::functions-available有函数被注册或注销时。engine::workers-available有 worker 连接或断开时。常量在 engine/src/workers/engine_fn/mod.rs 中定义TRIGGER_FUNCTIONS_AVAILABLE engine::functions-available、TRIGGER_WORKERS_AVAILABLE engine::workers-available。引擎通过EngineFunctionsWorker::fire_triggers按触发器类型筛选并异步触发绑定函数engine_fn/mod.rs。八、Engine 采集的指标Engine-collected metrics以下指标由 engine 无条件发射与 worker 使用哪种语言 SDK 无关。名称与单位来源于 engine/src/workers/observability/metrics.rs。8.1 调用类Invocations指标仪器单位iii.invocations.totalcounterinvocationsiii.invocation.durationhistogramsecondsiii.invocation.errors.totalcountererrors8.2 Worker 类指标仪器单位iii.workers.activegaugeworkersiii.workers.spawns.totalcounterworkersiii.workers.deaths.totalcounterworkersiii.workers.by_statusgaugeworkers8.3 单 worker 资源类Per-worker指标仪器单位iii.worker.memory.heap.bytesgaugebytesiii.worker.memory.rss.bytesgaugebytesiii.worker.cpu.percentgauge%iii.worker.event_loop.lag.msgaugemsiii.worker.uptime.secondsgauges源码中EngineMetrics结构体与上述指标一一对应全部通过 OpenTelemetry meter 构建u64_counter/f64_histogram/i64_gauge/f64_gauge并附带机器可读的描述与单位metrics.rs。此外源码还维护了一个与 OTel 只写指标互补的MetricsAccumulator以原子计数器与DashMapString, u64提供按函数粒度的实时可读计数成功 / 失败 / 延迟调用见 metrics.rs。与 worker 资源指标的对应协议层WorkerMetrics结构protocol.rs覆盖了这些 per-worker 指标的字段来源memory_heap_used/memory_heap_total/memory_rss/memory_external、cpu_user_micros/cpu_system_micros/cpu_percent、event_loop_lag_ms、uptime_seconds、timestamp_ms与runtime。该结构为u64字段的 JavaScript 精度问题附了专门注释内存值需超过约 9 PB 才会丢精度CPU 微秒需连续运行约 285 年时间戳到公元 287396 年都安全——需要绝对精度时可在 JS 侧用 BigInt 解析protocol.rs。九、把协议落到实践从 SDK 到原始 WebSocket对大多数项目而言正确用法是使用语言 SDKNode、Python、Rust、Browser它们负责把本文所述的线级 shape 序列化好。需要直接使用协议的场景包括手写协议客户端 / 诊断调试按message_type判别帧先发送内存中的全部RegisterFunction/RegisterTrigger/RegisterTriggerType再调用engine::workers::register等待WorkerRegistered拿到worker_id。实现自定义触发器类型通过RegisterTriggerType声明新类型并给出两个 JSON Schema绑定config与触发 payload随后其他 worker 即可用RegisterTrigger绑定到它。接入远程/桥接引擎将 SDK WebSocket 指向bridge_url默认ws://localhost:49134或在桥接配置中以REMOTE_III_URL环境变量覆盖engine/src/workers/configuration/README.md。可观测性接入从同容器暴露的9464Prometheus 端点拉取iii.*指标分布式追踪通过InvokeFunction/InvocationResult帧中的 W3Ctraceparent/baggage跨 worker 传播。需要注意的是engine 的内建发现面engine::*函数与触发器在进程内执行其注册信息通过metadata.internal true标记默认的engine::functions::list会隐藏它们传include_internal: true可见见 engine_fn/mod.rs。总结iii 的 Engine 协议是一套简洁、双向、以 JSON 帧为单位的 WebSocket 线级协议四个端口各司其职REST3111、Stream3112、SDK WS49134、指标9464worker 通过注册重放 元数据发布完成接入随后所有调用统一经 engine 路由Message枚举engine/src/protocol.rs是 SDK 序列化的唯一事实来源同步 / Void / 入队三种 action 覆盖了从请求应答到异步队列的全部调用形态engine::*内建发现面与iii.*指标体系让每个 worker 的语言、运行时与隔离方式对调用方透明同时为 console、CLI 与 LLM agent 提供了统一的内省入口。对于需要脱离 SDK 进行协议级集成或深度调试的团队本文的所有 shape 均可直接对照源码验证。【免费下载链接】iiiEffortlessly compose, extend, and observe every service in real-time for the first time ever.项目地址: https://gitcode.com/GitHub_Trending/mo/iii创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表