Sohara

Sohara 分布式管理层与 Dashboard 设计

状态:v2(已按 challenge 修订)。范围对齐既有定稿:单机优先、分布式为高层实现、AI agent 不实现(见 redesign-and-roadmap.md §3 与 extension-points.md)。

0. 决策记录(challenge 后定稿)

# 决策点 结论 理由
D1 实例间通信总线 内置中转(PlaneRelayBus)起步,NATS 作为后期选项 零外部依赖、保持单二进制部署体验;NATS 规模价值在小集群不兑现。EventBus trait 不变,后期可无痛替换
D2 agent 管理实例方式 进程级(spawn sohara serve --admin 隔离与崩溃安全最好,复用 release 二进制与全部单机能力;重启恢复语义显式化(见 §5)
D3 Gateway 默认分发模式 proxy 为主,bus 显式声明 默认同步请求-响应;mode: bus 的路径才走总线(异步语义,发布即返回)

0.1 目标与非目标

目标(对应需求 1–5):

  1. 上层控制多台机器上的 sohara 单机实例(任务下发/启停/重启/暂停),并支持实例间通信。
  2. 上层把外部请求调度到不同实例。
  3. 上层管理 sohara 生命周期,基于运行状态(监控)决定启动/停止/重启。
  4. 上层暴露统一出口(Gateway)与管理界面(Manager)。
  5. sohara 以 server 模式运行时自带 Dashboard,可查看本实例工作状态与任务详情;全局 Manager 提供跨实例 Dashboard。

非目标(明确排除):控制面多副本 HA/选举、自动扩缩容、分布式事务、agent 自治编排、AI agent。

1. 总体架构

                        ┌────────────────────────────────────────────┐
  外部请求 ──────────▶  │  sohara-plane(控制面,单实例进程)          │
                        │  ┌──────────┐  ┌──────────┐  ┌───────────┐ │
                        │  │ Gateway  │  │ Manager  │  │ Scheduler │ │
                        │  │ 统一入口  │  │ API+全局UI│  │ 路由/生命周期│ │
                        │  └────┬─────┘  └────┬─────┘  └─────┬─────┘ │
                        │       └──────┬─────┴───────────────┘       │
                        │         Registry(期望状态唯一来源)          │
                        └──────┬───────┴───────────┬─────────────────┘
                    控制通道(agent 拨出:心跳+指标上报、命令拉取;HTTP/JSON+token)
                ┌──────────────┴──────┐    ┌───────┴──────────────┐
                │  sohara-agent (机器A)│    │  sohara-agent (机器B) │
                │  实例进程管理/健康检查│    │  同左                  │
                │   ┌──────────────┐  │    │   ┌──────────────┐   │
                │   │sohara serve  │  │    │   │sohara serve  │   │
                │   │ --admin 9528 │  │    │   │ --admin 9528 │   │
                │   └──────┬───────┘  │    │   └──────┬───────┘   │
                └──────────┼──────────┘    └──────────┼───────────┘
                           │       数据通道(D5a:plane 中转;D5b:NATS)│
                           └─────────────────────────────────────────┘

组件职责:

组件 职责
sohara-agent(每机一个守护进程) 管理本机 sohara 实例进程;本地健康检查(1s 节拍);心跳/指标上报(5s);执行 plane 命令;转发总线消息
sohara-plane Registry(期望状态唯一来源)+ Manager API(部署/生命周期/监控查询)+ Scheduler(路由、健康策略)+ Gateway(统一入口)+ 总线中转(D5a)
数据通道 实例间通信(§2.2):D5a 内置中转,D5b NATS(后期)
单机 Dashboard serve 模式内嵌 /admin/ui(§6)
全局 Dashboard Manager 提供的 Web UI(§7)

2. 通信设计

2.1 控制通道(agent ↔ plane)

2.2 数据通道(实例 ↔ 实例)

3. 核心模型(Registry)

nodes:
  - { id: n1, addr: 10.0.0.11:9529, tags: [zone-a, gpu] }

flows:
  - id: flow-orders
    name: orders
    yaml: ./flows/orders.yaml     # plane 持有内容并分发

instances:
  - id: orders-1
    node: n1
    flow: flow-orders
    desired: running              # running | paused | stopped
    policy: { restart: always, max_restarts: 5, backoff: 2s, health_failures: 3 }
    routing: { weight: 2, sticky_key: order_id }
    bindings:
      - { path: /webhook/orders, mode: proxy }        # 缺省即 proxy(决策 D3)
      - { path: /tasks/orders, mode: bus, topic: orders.events }  # 显式异步

4. 调度(Gateway 路由)

模式语义(决策 D3)

模式 语义 适用
proxy默认,未声明 mode 即此) 反向代理到所选实例的 http 触发器(agent 注册实例端口) 同步请求-响应(webhook)
bus(显式 mode: bus 发布到总线 topic,订阅实例竞争消费;发布即返回,无响应回执 异步任务/作业队列

选择策略

失败处理unknown/failed/stopped 实例摘除;proxy 请求级重试(幂等安全);全挂 503 + 告警。

5. 生命周期与监控

6. 单机 Dashboard(serve 模式,需求 5)

扩展现有 admin API(现在只有 health/metrics/pause/resume):

端点 内容
GET /admin/status flow 元信息、triggers 列表、步骤 + 实时 StepStat、paused、run_id、启动时间、approve 队列概要
GET /admin/history 本实例运行历史(run 记录 + serve 停止时也写一条,D1 补齐)
GET /admin/approvals approve 停放队列列表(步骤 + 数量 + 样例)
GET /admin/errors 近期错误环形缓冲(executor 打点处新增)
--admin-token 管理端点鉴权(D1;agent 与 plane 使用)

GET /admin/ui:内嵌静态单页(vanilla JS/htmx,rust-embed 打进二进制,无前端构建),页面:

数据走上述 JSON API,UI 2–5s 轮询。--admin 未开启时 UI 不可用(保持默认零暴露)。

7. 全局 Dashboard(Manager UI)

同单机 UI 技术栈,静态资源内嵌 plane 二进制。页面:

8. 实施路线(D 阶段,每阶段可独立验收)

阶段 内容 验收
D1 ✅ 单机 Dashboard:admin API 扩展(status/history/approvals/errors/错误环形缓冲/--admin-token)+ 内嵌 /admin/ui;serve 停止写 history;CLI serve --resume 已实现:sohara serve --admin 打开 UI;status/errors/approvals/history 端点可用;无 token 401;暂停期间事件不处理;停机写 history
D2 ✅ sohara-agent:进程管理(spawn/kill/重启退避)、本地 1s 健康检查、心跳上报、命令执行、token;单机 serve --resume 已实现:sohara-agent crate(实例监督状态机/重启策略/HttpTransport 心跳+命令队列+seq 去重);e2e 用真实 sohara 二进制验证拉起/健康/停机;plane stub 测试验证心跳与 pause 命令执行
D3 ✅ sohara-plane 基础:Registry(JSON 原子持久化)、Manager API(instances CRUD/desired 更新/flows)、/agent/heartbeat+/agent/ack 接收端(命令队列+seq 去重)、desired/actual 对账(心跳返回命令+期望实例集,agent 对账成员与状态) 已实现:声明实例 → agent 拉起真实 sohara 进程;desired=stopped → 实例停机;desired=running → 重启;状态持久化跨重启
D4 ✅ Gateway + 调度:路由表(/api/routes,path→flow_id)、proxy 默认模式(bus 显式声明,暂返 501 待 D5a)、round_robin/hash 策略(tags/least-loaded 延后)、健康摘除(仅 running 且带 trigger 地址可路由)、请求级重试(2 候选)、全挂 503、Gateway 免 token(外部统一入口) 已实现:两个真实实例按 round-robin 均分流量;停一个实例后流量全部切到存活实例
D5a ✅ PlaneRelayBus:实例 --relay <plane> 桥接(sink.queue 发布 → plane 邮箱;pull 循环注入本地 InProcessBus → queue 触发器原样消费)、plane /relay/publish|pull(每主题有界 1000 条,超限丢最旧,游标按订阅者独立)、Gateway mode: bus 发布即返回 202 已实现:实例 A(http→queue sink)跨机投递到实例 B(queue trigger→file,优雅停机 flush 落盘);Gateway bus → B 同样到达
D5b (可选,后期)NATS/JetStream:NatsBus + nats 触发器;least-loaded 策略启用 跨机持久化投递;重启不丢消息
D6 ✅ 全局 Dashboard(/ui:节点/实例矩阵、生命周期按钮、声明表单、路由管理、事件历史)+ 实例详情直查代理(/api/instances/:id/status 透传 admin token)+ 集群事件历史(声明/期望变更/状态迁移,200 条环)+ 安全收尾(plane token 覆盖 /api、/agent、/relay 与 /ui;实例 admin token 直查透传;Gateway 前置 LB 与 mTLS 评估:单点已接受,HA 延后——见 §9) 已实现:UI 401/200(token)、状态代理、事件流、三向 token e2e

9. 失败模型与安全

10. 与现有代码的接缝(零破坏)

现有 用途
EventBus trait(core) D5a PlaneRelayBus、D5b NatsBus(同 trait,单机 InProcessBus 不动)
Trigger trait + queue 触发器模式 D5b nats 触发器(复用有界通道/背压/优雅停机);D5a 复用既有 queue 触发器
admin API(S6) agent 健康检查/指标采集;D1 扩展为 Dashboard 数据源
RunReport/StepStat(S6) 心跳指标快照 → Scheduler 决策
run history 文件 D1 补 serve 停止历史;agent 上报 → 全局聚合
PauseGate(S6) plane pause/resume 命令落点
release 二进制 sohara serve --admin agent 进程级管理(决策 D2);单机 CLI 仅增 --admin-token/--resume 两个 flag

新增 cratesohara-agentsohara-planesohara-dashboard(UI 资源,可并入前两者);D5b 时增 sohara-nats