多语言插件演进统一规划(Rust 优先)
背景:团队技术栈杂糅,Python 在部分计算密集场景性能有限。
目标:在不破坏现有体系的前提下,开放进程插件多语言实现能力,
Rust 优先落地,为后续其他语言(Go / C++ 等)铺路。
配套文档:进程插件线协议规范(语言无关)、
进程插件开发指南(Python)
1. 总体原则
| # |
原则 |
说明 |
| P1 |
规范先行,协议是唯一契约 |
网关与插件之间只认线协议(plugin-wire-protocol.md)。任何语言实现均以规范为准,不得依赖其他语言 SDK 的内部行为 |
| P2 |
网关零改动起步 |
阶段 1 的 Rust 插件按协议实现即可对接,网关代码不允许为适配单语言做改动 |
| P3 |
混合部署兼容 |
同一 <type> 下可混布 Python 与 Rust 副本(协议相同、负载均衡透明);但流式语义、错误格式、超时行为必须与规范完全一致 |
| P4 |
契约校验不旁路 |
Python SDK 的进程内契约校验(TOML ↔ 注册 ↔ 模型)是 Python 特有能力;其他语言实现须提供等价的自检(描述符字段完整性),网关侧强校验在阶段 2 补齐 |
| P5 |
修改即更新规范 |
任何实现侧改动触及协议语义时,必须同步修订规范(含附录 A 事实来源索引) |
| P6 |
性能收益只认实测 |
语言选型以基准测试为准(见 §6),不凭直觉切换 |
2. 阶段划分总览
| 阶段 |
内容 |
产出 |
状态 |
| 0 |
协议规范定稿 |
docs/plugin-wire-protocol.md |
✅ 已完成 |
| 1 |
Rust 参考实现 |
chongming-worker-rs(utils/worker-rs/)+ demo 参考插件,端到端验证通过 |
✅ 已完成(见 §3.4 验证结果) |
| 2 |
工具链与治理 |
build_plugin 支持非 Python、网关描述符强校验、跨语言互操作测试 |
⏳ 未开始 |
| 3 |
推广与最佳实践 |
团队规范、性能基准、Go 等其他语言按需跟进 |
⏳ 未开始 |
每阶段有明确的 Done 定义(见 §5),未达验收标准不得进入下一阶段。
3. 阶段 1:Rust 参考实现(chongming-worker-rs)
3.1 目标
用 Rust 实现一个最小但完整的进程插件 SDK 与参考插件,证明:
路由注册、RPC、流式、摘除、自愈、混合部署全链路可用,且与 Python SDK 行为等价。
参考实现(两形态,均已完成):
- SDK 内示例:
utils/worker-rs/examples/demo.rs(--type rsdemo / --type demo 混布对拍)
- 独立插件形态:
workers/rsdemo/(与 Python 示例 workers/demo/ 对位的完整插件 crate,
含生成模型与说明文档,新插件以此为模板)
3.2 crate 结构建议
3.3 与协议规范的对应(实现对照)
| 协议项(规范章节) |
Rust 实现要点 |
| §2 路由描述符 |
descriptor.rs 构造 + publisher.rs PUT/DELETE;route_id = subject.replace('.','_') + "__" + METHOD |
| §3 服务发现 |
session.liveliness().declare_token("worker/<type>/<id>"),--count 多副本 id 互异 |
| §4 RPC |
declare_queryable("worker/<type>/<id>/<subject>") 异步 handler;信封解析 + 分派;流式多次 query.reply() |
| §4.3 异常 |
非流式:{"result":0.0,"operation":"error","error":...,"worker":...};流式:{"error":...} 收尾块 |
| §5 配置 |
config.rs:TOML + JSON5 双重解析 |
| 生命周期 |
publisher.rs 10s tokio interval 重发布;tokio::signal 监听 SIGTERM/SIGINT → DELETE 全部 key |
3.4 端到端验收场景(已全部通过 ✅)
| # |
场景 |
结果 |
| 1 |
路由注册 + HTTP 端点可用 |
✅ 描述符 keyexpr/字段 15 项断言全过;网关动态挂载后 GET /api/v1/rsdemo/hello 返回 200 |
| 2 |
GET/POST RPC + user_info 透传 |
✅ 信封分派、worker_id 注入、user_info 经 meta 透传(协议层验证);网关层 echo 端点按配置要求认证头(预期行为) |
| 3 |
流式 SSE 逐块 + 流中异常收尾 |
✅ tokens=5 逐块 5 块;tokens=60 第 26 块后 SSE 收到 {"error":...} 收尾块并终止 |
| 4 |
SIGTERM 摘除 + 重启自愈 |
✅ 退出码 0、DELETE 全部描述符;重启后 ≤10s 重发布恢复 |
| 5 |
混布(Python + Rust 同 type) |
✅ 描述符内容 hash 完全一致(网关幂等去重零告警);双副本统一 liveliness 发现;网关 HTTP 10 次调用 6:4 随机打到两实现(worker-0-54257=Rust / worker-0-54258=Python);互不干扰 |
| 6 |
错误描述符健壮性 |
✅ Rust SDK 发布前自检跳过无 subject 描述符(不发布残缺路由);网关侧非法 JSON 丢弃为既有行为 |
验证命令(见 utils/worker-rs/README.md):
3.5 与 Python SDK 的差异(有意为之)
| 差异 |
说明 |
| 契约校验 |
Python 进程内三方校验(硬失败退出);Rust 降级为发布前自检:无 handler 端点告警跳过,不发布残缺路由 |
| 模型生成 |
Rust 有 gen_models 等价物(--bin gen_models,命名/类型映射对齐 Python):从端点 TOML 生成强类型结构体,并做启动时指纹校验(TOML 变更未重生成即告警,比 Python 只查模型存在性更强) |
| handler 注入 |
worker_id / user_info 经 Request 结构注入(Python 为函数参数注入) |
4. 阶段 2:工具链与治理
4.1 build_plugin 支持非 Python 插件
- 现状:
build_plugin 产物为 pyproject.toml + start.sh(uv run worker_serve --type <name>),纯 Python 链路
- 目标:支持声明插件语言/入口,允许打包任意可执行产物 + 自定义 start.sh
(Rust 插件 = 编译产物 +
--type 参数约定),--type 语义跨语言保持一致
- 约束:打包结构(zip 根 = 容器工作目录)不变
4.2 网关侧描述符强校验(补齐契约旁路)
- 现状:描述符健壮性只有"非法 JSON 丢弃 / 缺字段取默认",字段语义错误会挂载错误路由
- 目标:
route_registry 对必填字段(subject / method / path)做校验,缺必填字段的
描述符丢弃并告警;为 schema_version 未知版本预留拒绝策略
- 收益:非 Python 插件(无契约校验)的错误在网关侧被兜底,两端受益
4.3 跨语言互操作测试
- 复用
test_process_mode_e2e.py 模式,新增协议一致性测试矩阵:
Python SDK ↔ Rust SDK 对同一描述符/信封的序列化结果一致性(黄金样本对比)
- 纳入 CI:任何实现侧协议改动,先跑互操作测试再合入(配合原则 P5)
5. 验收标准(Done 定义)
| 阶段 |
Done 定义 |
| 0 |
规范文档覆盖:描述符字段、信封、三种响应形态、生命周期、演进规则;任一语言实现者可仅凭规范写出插件 |
| 1 |
§3.4 六个场景全部通过;Rust 插件与 Python 插件行为对拍一致(普通/流式/错误/超时) |
| 2 |
build_plugin 可打包 Rust 插件并部署运行;网关描述符强校验生效;互操作测试入 CI |
| 3 |
性能基准文档发布;团队多语言插件开发规范定稿 |
6. 选型指引(何时用 Rust)
| 场景 |
建议 |
依据 |
| 个别计算热点慢(加解密/编解码/大体积处理) |
Python + PyO3 扩展(网关 jwt/password 已有先例) |
保留 Python 全部工具链,改动最小 |
| 整个插件即高性能计算服务 / 高吞吐短请求 |
Rust 进程插件(本规划主线) |
消除 GIL 与解释器开销,收益在 handler 侧 |
| 纯 I/O 编排(HTTP/DB/存储调用) |
维持 Python |
瓶颈在外部服务,换语言边际收益小 |
| 团队语言偏好 / 组件复用(已有 Rust 库) |
Rust 进程插件 |
混合部署兼容,可渐进替换 |
性能收益只发生在 handler 执行侧;Zenoh 传输与 JSON 序列化开销各语言相同。
落地前先做基准:同端点 Python vs Rust 的 p99 / 吞吐对比,以数据决策。
7. 风险与缓解
| 风险 |
等级 |
缓解 |
| 协议漂移(双实现维护) |
高 |
规范为唯一契约 + 附录 A 事实索引 + P5 强制更新 + 阶段 2 互操作测试入 CI |
| 行为差异导致混布异常(流式/错误/超时) |
中 |
§3.4 场景 5/6 混布对拍;各实现须通过同一互操作测试矩阵 |
| 契约校验旁路 |
中 |
阶段 2 网关强校验兜底;Rust SDK 提供描述符自检(等价 contracts.py 的必填校验) |
| 网关被不规范描述符影响 |
低 |
现有健壮性处理已覆盖(非法 JSON 丢弃、冲突保留先到者、防抖) |
| 多语言 SDK 维护成本 |
中 |
阶段 1 只做最小 SDK(协议层),业务框架(路由/模型/契约)不复制,避免重复投入 |
8. 相关文档