Entity Migration — 实体迁移
实体迁移是 theseed 分布式架构的核心能力:实体可以在不同 CellApp 之间安全迁移。
来源源头:BigWorld Offload / Cell 迁移 / 退役迁出机制。 参考实现:KBEngine teleport + Ghost 路由窗口。 当前实现基线以 0-foundation/01-mvp-architecture-baseline 为准。
0.5 引擎实现对照与取舍
BigWorld 是怎么实现的
BigWorld 的迁移不是单纯的 teleport:
- 有 offload / retire / controlled shutdown 语义
- 有跨 Cell 迁移窗口
- 有更完整的负载均衡和退役链条KBEngine 是怎么实现的
KBEngine 更偏向 teleport 和 ghost 路由窗口:
- 迁移路径更直接
- 系统级退役链条更轻
- 适合先把实体可迁移跑通优缺点
BigWorld 的优点:
- 迁移和退役体系完整
- 能支撑更复杂的集群调度
KBEngine 的优点:
- 简单
- 容易先落地
共同缺点:
- 迁移快照和窗口期控制都很敏感
- 一旦和脚本 I/O、协程绑死,复杂度会迅速上升theseed 的取舍
theseed 先实现单 Realm 内迁移和跨 Space 传送,
把脚本调用栈和外部 I/O 明确排除在快照之外,
避免把 BigWorld 的 HA 复杂度一次性吞进 MVP。0. MVP 边界
MVP 只支持:
- 单 Realm 内 Cell 迁移
- 跨 Space 传送
MVP 不支持:
- 跨机房 / 跨 Realm 实体迁移
- 脚本调用栈迁移
- 挂起协程 / Future continuation 迁移
- 外部 I/O 上下文迁移1. 迁移场景
场景 1: Teleport(跨 Space 传送)
玩家从 Space A 传送到 Space B
可能跨 CellApp
场景 2: Cell 边界移动
Space 拓扑变化导致 Cell 边界移动
实体需要迁移到新的 CellApp
场景 3: 负载均衡
CellApp 过载,部分实体迁移到其他 CellApp
场景 4: 跨服(远期)
实体从一个 Realm 迁移到另一个 Realm
不属于 MVP 范围2. 迁移流程
Phase 1: Prepare
├─ 源 CellApp: 冻结实体收件箱
├─ 标记 entity epoch / migration token
├─ 设置 GhostManager 路由(转发窗口期的消息)
└─ 通知目标 CellApp 准备接收
Phase 2: Serialize
├─ 序列化实体状态:
│ - PropertyBlock(持久化 + 运行时必要属性)
│ - 位置 / 朝向 / Space 信息
│ - 定时器列表
│ - 控制器状态
│ - Witness 基础状态
└─ 发送到目标 CellApp
不进入迁移快照:
- Python / Lua 调用栈
- yield 挂起中的 continuation
- 正在执行的 HTTP / DB / 跨服请求上下文
Phase 3: Restore
├─ 目标 CellApp: 创建新实体
├─ 反序列化属性
├─ 恢复定时器
├─ 加入 Space / CoordinateSystem
├─ 恢复 Witness(如果有客户端)
└─ 建立新的 entity epoch
Phase 4: Route Update
├─ 更新 EntityCall 路由:旧 CellApp → 新 CellApp
├─ 通知 BaseApp 更新 cellEntityCall 目标
├─ GhostManager 路由窗口期:将运行时消息转发到新位置
└─ 通知已知持有方更新地址
Phase 5: Cleanup
├─ 旧 CellApp: 销毁旧实体(callScript=false)
├─ 清理 GhostManager 路由
└─ 丢弃旧 epoch 的迟到回调3. 迁移窗口期的消息处理
问题:迁移过程中,运行时消息可能发到旧的 CellApp
KBEngine 的解决方案(来自源码注释):
"如果期间有base的消息发送过来,entity的ghost机制能够转到real上去"
theseed 的设计:
GhostManager.setRoute(target, ttl=10s)
→ 旧 CellApp 在路由窗口期内,把运行时消息转发到新位置
→ 路由过期后,如果还有消息发来,说明路由表没更新完,记录告警
覆盖范围:
- EntityCall
- Ghost / Witness 同步
- 迁移窗口内的运行时控制消息
不覆盖:
- 已经发出的外部 HTTP 请求
- 已提交的 DB 异步请求
- 跨 Realm 异步任务的远端执行上下文
因此:
迁移窗口机制的目标是“运行时消息无感切换”,
不是对所有异步副作用承诺绝对零丢失。