iii 引擎实战指南:从 Function/Trigger/Worker 三大原语到安装、配置与 WebSocket 协议
【免费下载链接】iiiEffortlessly compose, extend, and observe every service in real-time for the first time ever.项目地址: https://gitcode.com/GitHub_Trending/mo/iii
本指南以仓库 engine/README.md 为主线,深入讲解 iii 引擎的核心抽象、安装启动、配置文件、Docker 部署、端口与 WebSocket 协议,并结合 engine/src 目录下的 Rust 源码(CLI 入口、引擎内核、协议定义、安全配置)进行源码级佐证。读完本文,你将掌握 iii 引擎从零启动到生产部署的完整路径,并理解引擎与 SDK Worker 之间基于 JSON 消息的调用协议。
引擎定位:基于三大原语的实时编排系统
iii 引擎(engine)是一个提供**持久化编排(durable orchestration)、跨语言互操作执行(interoperable cross-language execution)、功能实时发现(live discovery of functionality)、系统实时可扩展(live system extensibility)与系统实时可观测(live system observability)**的进程通信引擎。它只依赖三个简单原语即可组合出完整系统:
- Function(函数):可被调用、可被发现的最小执行单元。SDK Worker 通过 WebSocket 向引擎注册函数,引擎维护全局函数注册表(
FunctionsRegistry),并按(namespace, function_id)路由调用。 - Trigger(触发器):把外部事件(HTTP 请求、定时任务、队列消息、状态变更等)绑定到函数上的机制。引擎维护触发器注册表(
TriggerRegistry),事件到达时驱动目标函数执行。 - Worker(工作进程):承载函数与触发器的运行时进程。可以是 Node.js、Python、Rust 等任意语言的 SDK 进程,通过 WebSocket 长连接接入引擎;也可以是引擎内置的模块 Worker(API、队列、流、可观测性等)。
从源码结构看,引擎内核将这三类原语的注册与路由集中管理:engine/src/engine/mod.rs 中的Engine结构体同时持有worker_registry、functions(FunctionsRegistry)、trigger_registry(TriggerRegistry)、service_registry(ServicesRegistry)与invocations(InvocationHandler)等核心注册表,所有 Worker 连接和函数调用都汇聚于此,构成一个"请求进入 → 路由到 Worker → 响应返回"的实时路由器。
安装 iii 引擎与版本验证
README 提供了一条官方一键安装命令:
curl -fsSL https://install.iii.dev/iii/main/install.sh | sh该命令安装的是包含全部 CLI 命令的 iii 引擎二进制(engine 与 CLI 是同一个iii二进制)。仓库内同时保留了安装脚本本体,可查阅 engine/install.sh 了解其实现逻辑。
自定义安装目录或锁定版本
覆盖安装目录或锁定版本
指定安装到$HOME/.local/bin:
curl -fsSL https://install.iii.dev/iii/main/install.sh | BIN_DIR=$HOME/.local/bin sh锁定具体版本(例如 v0.11.3):
curl -fsSL https://install.iii.dev/iii/main/install.sh | sh -s -- v0.11.3验证安装
command -v iii && iii --versioniii --version会打印CARGO_PKG_VERSION(见 engine/src/main.rs)。该文件是整个 CLI 的入口(iii二进制),基于 clap 解析子命令,并支持--config <path>、--version、--no-update-check等全局参数。
启动引擎:默认模式、配置文件与 Console
直接启动
README 记载了iii --use-default-config的启动方式,但需要说明的是:该标志在当前仓库源码中已被移除。main.rs的单元测试use_default_config_is_no_longer_a_flag明确断言--use-default-config不再可解析(engine/src/main.rs),其职责由"iii在缺少config.yaml时自动创建"取代。因此当前版本直接运行:
iii不带任何子命令时,CLI 进入 serve 模式启动引擎(run_serve,见 engine/src/main.rs)。启动流程为:
- 计算配置文件路径:显式
--config优先,否则默认config.yaml; - 若文件不存在,交互式终端会询问"是否创建"(避免在错误目录静默写入);容器/CI 等非交互会话则自动创建,写入一个空
workers:列表的起始配置(EngineConfig::starter_config_yaml(),见ensure_config_file); - 加载配置、初始化日志,通过
EngineBuilder构建引擎并serve()。
该行为与文档 docs/using-iii/engine.mdx 一致:引擎自带 WebSocket 监听、配置 Worker 与可观测性等内部服务,其余能力通过iii worker add <name>按需开启。
使用项目配置文件
项目化部署时,在工作目录创建config.yaml,或显式指定路径:
iii --config /path/to/config.yaml如果偏好自定义文件名(例如iii-config.yaml),显式传入即可:
iii --config /path/to/iii-config.yaml打开控制台
iii console引擎启动后运行在ws://localhost:49134,HTTP API 位于http://localhost:3111。iii console会拉起 Web 控制台(其前端工程位于 console/packages/console-frontend),用于实时观察函数、触发器和调用链路。
引擎即路由器:config.yaml 配置深度解析
iii 引擎从项目根目录的config.yaml启动,配置结构非常收敛:顶层只有一个workers:键,列出引擎需要加载的 Worker(docs/using-iii/engine.mdx 称其为"first-boot seed"——首次启动种子配置)。
仓库自带的示例配置 engine/config.yaml 展示了完整形态:
registration_namespace_grace_ms: 5000 # Only workers that are part of the engine lifecycle belong here. Project # workers such as http, state, cron, queue, pubsub, and bridge belong in # worker-compose.yaml. workers: - name: iii-stream config: port: ${STREAM_PORT:3112} host: 127.0.0.1 adapter: name: redis config: redis_url: redis://localhost:6379 - name: configuration config: adapter: name: fs config: directory: ./config ttl_seconds: 0 # Ephemeral sandboxes are an engine-managed exception to worker-compose. # - name: iii-sandbox # config: # auto_install: true # image_allowlist: # - python # - node # default_idle_timeout_secs: 300 # max_concurrent_sandboxes: 32 # default_cpus: 1 # default_memory_mb: 512要点解读:
workers:列表:每个条目有name(注册表 slug 或本地 Worker 名)和可选的config块。config块只在该 Worker 首次启动时被读取一次,作为配置种子写入配置存储;此后配置以"每个 Worker 一个文件"的形式存放在./config/下,支持从磁盘、Console 或configuration::set实时修改,引擎会把已消费的config:块从config.yaml中移除并留下注释。registration_namespace_grace_ms: 5000:全局配置,控制 Worker 连接在命名空间确定前的注册缓冲宽限期(默认 5 秒)。引擎内核通过III_NAMESPACE_GRACE_MS环境变量优先、其次是该配置、最后回退 5 秒默认值来解析(见 engine/src/engine/mod.rs)。宽限期内,命名空间相关的注册消息(RegisterFunction、RegisterTrigger等)会被排队缓冲,等待engine::workers::register调用确定连接命名空间后再按到达顺序落位,避免注册被错误归入default命名空间。iii-stream:流模块 Worker,监听端口支持${STREAM_PORT:3112}环境变量展开,默认 3112;其 Redis 适配器对应 engine/src/workers/stream/adapters 下的适配器实现。configuration:配置 Worker,使用文件系统适配器(directory: ./config),ttl_seconds: 0表示条目不过期。- 注释中的
iii-sandbox展示了临时沙箱的示例参数(镜像白名单、空闲超时、并发上限、CPU/内存配额),实际启用时按需取消注释。
环境变量展开
配置值支持${VAR:default}语法:读取环境变量VAR,未设置时回退到default。这允许在不拆分配置文件的前提下按环境切换端口、URL 与功能开关,且该语法同样适用于每个 Worker 的独立配置文件:
workers: - name: http config: port: ${HTTP_PORT:3111} host: ${HTTP_HOST:127.0.0.1}安全配置(HTTP 外部调用)
引擎对外部 HTTP 调用(如registerfunction中的invocation指向外部 Lambda/HTTP 端点)有独立的安全策略,定义于 engine/src/config/mod.rs 的SecurityConfig:
| 字段 | 默认值 | 说明 |
|---|---|---|
url_allowlist | ["*"](空则视为*) | URL 白名单,仅允许调用列表内的地址 |
block_private_ips | true | 阻止调用私网 IP(SSRF 防护) |
require_https | true | 强制要求 HTTPS 端点 |
配置采用deny_unknown_fields严格解析,未知字段会导致加载失败(见 engine/src/config/mod.rs 的测试)。该配置最终转换为UrlValidatorConfig,供调用校验器在每次外部调用前检查目标 URL。
Docker 部署:基础镜像、生产加固与 Compose 全家桶
拉取并运行镜像
docker pull iiidev/iii:latest docker run -p 3111:3111 -p 49134:49134 \ -v ./iii-config.yaml:/app/iii-config.yaml:ro \ iiidev/iii:latest镜像的默认启动命令是["/app/iii", "--config", "/app/config.yaml"](见 engine/Dockerfile):容器内WORKDIR /app,config.yaml挂载为只读。
生产加固示例
docker run --read-only --tmpfs /tmp \ --cap-drop=ALL --cap-add=NET_BIND_SERVICE \ --security-opt=no-new-privileges:true \ -v ./iii-config.yaml:/app/iii-config.yaml:ro \ -p 3111:3111 -p 49134:49134 -p 3112:3112 -p 9464:9464 \ iiidev/iii:latest该命令体现了镜像的安全设计:只读根文件系统 +/tmp临时挂载、丢弃全部 Linux capabilities 仅保留NET_BIND_SERVICE(绑定 80/443 等低端口)、禁止提权。Dockerfile 基于gcr.io/distroless/cc-debian12:nonroot构建,以 UID 65532 的非 root 用户运行、无 shell,且预创建了/app/config与/app/data目录并设置属主,保证配置 Worker 能落盘。CI 中还包含 Trivy 漏洞扫描、SBOM 物料清单证明与构建来源证明(build provenance)。
Docker Compose:Redis + RabbitMQ 全家桶
仓库提供了完整编排文件 engine/docker-compose.yml:
docker compose up -d该栈包含三个服务:iii(映射 49134/3111/3112/9464 四个端口,设置RUST_LOG=info与III_EXECUTION_CONTEXT=docker,依赖 Redis 与 RabbitMQ 健康检查通过后启动)、redis:7-alpine(队列/流模块的存储后端,带redis-cli ping健康检查)、rabbitmq:3-management-alpine(队列模块的 AMQP 后端,默认凭据guest/guest,生产环境请用.env覆盖)。
Docker Compose + Caddy(TLS 反向代理)
docker compose -f docker-compose.prod.yml up -dengine/docker-compose.prod.yml 引入了 Caddy 2 作为 TLS 反向代理,并通过iii compose --namespace production --up --file /app/worker-compose.yaml以 worker-compose 方式启动项目(含nc -z 127.0.0.1 3111健康检查)。配套的 engine/Caddyfile 展示了端口到路径的路由映射:
your-domain.com { handle /api/* { reverse_proxy iii:3111 } handle /streams/* { reverse_proxy iii:3112 } handle /ws { reverse_proxy iii:49134 } handle { reverse_proxy iii:3111 } }即:/api/*走 HTTP API、/streams/*走流 API、/ws走 WebSocket、其余兜底回 HTTP API。TLS 证书的申请与续期由 Caddy 自动完成。
端口一览与网络拓扑
| 端口 | 服务 |
|---|---|
| 49134 | WebSocket(Worker 连接) |
| 3111 | HTTP API |
| 3112 | Stream API |
| 9464 | Prometheus metrics |
- 49134是 SDK Worker 接入引擎的长连接端口,承载 JSON 协议消息与遥测帧(见下节)。
- 3111提供 REST API,同时是 Console 的 HTTP 入口与
iii triggerCLI 的调用目标。 - 3112是流(Stream)通道 API,对应流模块 Worker 的默认端口(
${STREAM_PORT:3112})。 - 9464是 Prometheus 指标抓取端点,配合可观测性模块(engine/src/workers/observability)使用。
WebSocket 协议:消息类型与调用语义
引擎与 SDK Worker 之间通过 WebSocket 传输JSON 消息,协议 schema 完整定义在 engine/src/protocol.rs 的Message枚举中。README 列出的关键消息类型如下,括号内为协议字段名(serderename_all = "lowercase"):
| 消息 | 方向 | 作用 |
|---|---|---|
registerfunction | Worker → 引擎 | 注册函数(含id、description、request_format/response_format、metadata、可选的invocation外部 HTTP 引用) |
invokefunction | 双向 | 调用函数,携带invocation_id、function_id、data、traceparent/baggage、可选的action、metadata、namespace |
invocationresult | 引擎 → Worker | 调用结果,携带invocation_id、result或error(ErrorBody:code+message+ 可选stacktrace) |
registertrigger | Worker → 引擎 | 注册触发器(绑定trigger_type、function_id与config) |
unregistertrigger | Worker → 引擎 | 注销触发器 |
triggerregistrationresult | 引擎 → Worker | 触发器注册结果 |
registerservice | Worker → 引擎 | 注册服务 |
functionsavailable | 引擎 → Worker | 函数可用性广播(实时发现机制) |
ping/pong | 双向 | 心跳保活 |
除此之外,协议还包含引擎在重连场景下使用的高级消息(engine/src/protocol.rs):
reattach:Worker 重连时携带previous_worker_id与reattach_token(引擎在上一条连接上通过workerregistered下发的秘密),引擎据此退役旧连接、让注册重放落在干净状态上,避免与旧连接的清理流程竞争。workerregistered:引擎确认 Worker 身份,并可附带reattach_token。registrationrejected:注册被拒绝(如WORKER_NAMESPACE_CONFLICT——同一命名空间已有同名存活 Worker;FUNCTION_NAMESPACE_CONFLICT——同一命名空间已有 Worker 导出该函数 id;INVALID_NAMESPACE——命名空间为空白)。
Fire-and-forget 语义
调用可以省略invocation_id实现即发即忘(fire-and-forget)。引擎内核对此有明确实现:InvokeFunction.invocation_id为Option<Uuid>(engine/src/protocol.rs);spawn_invoke_function中,invocation_id为Some时调用完成后回送InvocationResult,为None时则以后台任务方式执行且不回送结果(见 engine/src/engine/mod.rs)。TriggerAction枚举也与之呼应:{"type":"enqueue","queue":"..."}表示将调用转投队列,{"type":"void"}表示纯异步执行。
外部 HTTP 函数
registerfunction支持注册"外部函数"——引擎不经过本地 Worker,而是直接对invocation指定的 URL 发起 HTTP 调用。HttpInvocationRef(engine/src/protocol.rs)包含url、method(默认 POST)、timeout_ms、headers与auth(如 Bearer token 引用),协议测试中有完整的注册示例(external.my_lambda)。这类调用受前述SecurityConfig约束。
命名空间:显式路由维度
协议层面每个消息都可携带namespace字段,缺省时落入默认命名空间default(DEFAULT_NAMESPACE,见 engine/src/protocol.rs)。引擎的函数解析策略是显式路由维度,不做跨命名空间搜索:
Some(ns)只在ns中解析;None只在default中解析。不存在"就近匹配",调用方的命名空间不参与目标解析——analytics命名空间里的 Worker 若不显式指定命名空间,拿到的是default中的函数,而不是自己命名空间里的同名函数。
(见 engine/src/engine/mod.rs 中resolve_function的注释与实现。)这样做消除了"调用目标取决于谁在提问"的歧义:函数与 Worker 的注册表均以(namespace, id)为键,例如服务注册表ServicesRegistry就以(namespace, service_name)为键(engine/src/services.rs),保证多个项目在同一引擎上互不覆盖。若函数在目标命名空间缺失,引擎返回function_not_found错误码,并附带"该 id 实际存在于哪些命名空间"的提示。
可观测性:OTLP 帧与 Prometheus
除 JSON 协议消息外,WebSocket 连接还支持三类二进制遥测帧,通过魔数前缀区分(见 engine/src/engine/mod.rs):
| 前缀 | 内容 |
|---|---|
OTLP | Trace 追踪(OTLP JSON) |
MTRC | Metrics 指标(OTLP JSON) |
LOGS | Logs 日志(OTLP JSON) |
SDK 直接将 OpenTelemetry 数据以带前缀的二进制帧推送给引擎,由handle_telemetry_frame分派到ingest_otlp_json/ingest_otlp_metrics/ingest_otlp_logs处理(engine/src/engine/mod.rs)。InvokeFunction与InvocationResult携带 W3Ctraceparent/baggage,实现跨 Worker、跨进程的分布式追踪上下文传播;指标则通过 9464 端口暴露给 Prometheus 抓取。README 提到"引擎内置 in-memory OpenTelemetry 配置,无需先创建 config.yaml 即可获得 traces/metrics/logs"——结合上文可知,当前版本中这一默认能力由引擎内置的可观测性服务承担,启动即具备。
仓库结构与源码导览
README 给出的仓库布局(当前仓库已将其中的src/modules/演进为src/workers/下的多个 Worker 目录):
- engine/src/main.rs – CLI 入口(
iii二进制):trigger(别名t)、console、cloud、project init/project generate-docker、compose、update等子命令,缺省为 serve 模式启动引擎; - engine/src/engine/mod.rs – 引擎内核:Worker 管理、函数/触发器/服务注册表、命名空间解析、调用生命周期(
Engine结构体与EngineTrait); - engine/src/protocol.rs – WebSocket 消息 schema(
Message枚举、ErrorBody、WorkerMetrics、HttpInvocationRef); - engine/src/workers – 核心模块 Worker:
http_functions(HTTP 函数)、queue(队列,含 Redis/RabbitMQ 等适配器)、stream(流,含适配器)、observability(可观测性:OTLP 导出、指标、追踪存储与 UI)、configuration(配置存储)、engine_fn、worker等; - engine/config.yaml – 示例模块配置;
- engine/examples/custom_queue_adapter.rs – 自定义模块与适配器示例;
- engine/tests – 端到端测试集,例如
cli_integration.rs、configuration_e2e.rs、queue_e2e_happy_path.rs、namespace_routing_e2e.rs、worker_ws_handshake_timeout_test.rs,覆盖 CLI、配置加载、队列、命名空间路由与 WebSocket 握手等行为。
各语言 SDK 位于 sdk/packages/node、sdk/packages/python、sdk/packages/rust,README 中的安装命令对应如下:
| 语言 | 包名 | 安装命令 |
|---|---|---|
| Node.js | iii-sdk | pnpm add iii-sdk或npm install iii-sdk |
| Python | iii-sdk | pip install iii-sdk |
| Rust | iii-sdk | 在Cargo.toml中添加依赖 |
本地开发与镜像构建
cargo run # 启动引擎 cargo run -- --config iii-config.yaml # 带配置启动 cargo fmt && cargo clippy -- -D warnings # 格式化与 Lint make watch # 监听模式(文件变更自动重编译)本地构建 Docker 镜像
docker build -t iii:local . # 生产镜像(distroless) docker build -f Dockerfile.debug -t iii:debug . # 调试镜像(Debian + shell)生产镜像的安全基线已在"生产加固"一节说明:distroless 无 shell 运行时、非 root 执行、CI 中的 Trivy 扫描、SBOM 证明与构建来源证明。
快速上手与后续阅读
- 从零开始构建:参阅 docs/quickstart.mdx 与 docs/tutorials 下的分步教程;
- 引擎配置详解:参阅 docs/using-iii/engine.mdx 与 docs/using-iii/configuration.mdx;
- CLI 参考:参阅 docs/cli-reference/index.mdx;
- 函数与触发器开发:参阅 docs/creating-workers 与 docs/using-iii/functions.mdx;
- 多服务编排(worker-compose):参阅 crates/iii-compose 与 docs/upgrading。
许可证
iii 引擎采用 Elastic License 2.0(ELv2),同时包含专利声明(engine/PATENTS)与商标声明(engine/NOTICE),仓库根目录另有一份 SPDX 许可证清单 LICENSE.spdx。
【免费下载链接】iiiEffortlessly compose, extend, and observe every service in real-time for the first time ever.项目地址: https://gitcode.com/GitHub_Trending/mo/iii
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考