Skip to content

服务端代码热更新调研与设计 ​

状态 ​

Proposed(调研完成,设计定稿,分阶段实施)。P0 通道已落地(热更包托管 + agent 下发确认),框架适配器 P1 起逐个接入。

1. 问题与边界 ​

游戏服在维护窗口外修 bug/改数值/调逻辑,需要不重启进程把新代码换进去。这与两个既有系统相关但不同:

  • 版本发布系统(release-management-design.md):面向客户端资源包(玩家设备下载);
  • 本文热更新:面向游戏服务器进程内部代码(skynet 的 lua、KBE 的 python、JVM 的 class、Node 的 JS)。

平台层不碰框架内部魔法(那需要每框架深度适配),而是提供统一的热更通道:包托管、下发、确认、回滚、审计——框架各自的 reload 机制作为可插拔适配器。

2. 各框架热更新机制全面对比 ​

2.1 Lua 系 ​

方案机制粒度热更限制评价
skynet官方无内置 hotfix;社区惯例 require 新模块文件 + clearcache,或云风 inject(inject.lua 遍历替换函数 upvalue)函数级闭包 upvalue/协程栈内旧引用替换复杂;C 模块不可热更手游服务端事实标准;inject 方案成熟但约定大于框架
xLua(Unity 客户端)lua_hotfix 替换函数函数级仅客户端;服务端无关列出供对照
OpenResty/lua-nginxcontent_by_lua + reload worker文件级平滑重启 worker,非进程内替换客户端接入层场景
tlua/srlua 变体自行开发沙箱替换--少数自行开发引擎

2.2 Python 系 ​

方案机制粒度热更限制评价
kbengine无官方热更;社区做法 reload(module) + CellApp/BaseApp 手动重绑;KBE 的 Entity 脚本层理论上可 importlib.reload模块级已实例化 Entity 持旧类引用,需遍历 __class__ 重指;C 扩展不可国内 MMO 常用;操作危险系数高,通常只热数值
BigWorld(KBE 前身)官方支持 Entity 脚本重载(bigworld.reloadScript),引擎级重绑 __class__类级商用引擎已停更;机制最完善的历史方案设计参考价值高
PurePython(gunicorn --reload / watchdog + importlib)进程外重启或模块 reload进程/模块数据序列化桥接小型服常用"软重启"替代热更

2.3 Java 系 ​

方案机制粒度限制评价
Arthas redefine/retransformInstrumentation API 字节码替换类级不能改字段签名;新类需 retransformClasses;调试向阿里系,事实标准;但定位线上诊断而非常态热更
Spring Boot DevToolsclassloader 重启进程级(快重启)丢失堆内状态开发期工具
OSGi/SoFAArk模块 classloader 隔离+替换bundle 级架构侵入大重架构,新项目少用
热部署 agent(自行开发 Instrumentation premain)attach 替换 jar类级同 Arthas 限制平台需对接的就是这类 agent

2.4 JavaScript/TypeScript 系 ​

方案机制粒度限制评价
Node.js无内置;require.cache 删除重载(CommonJS)或 --experimental-vm-modules 隔离 context模块级ESM 缓存不可删;闭包引用同 Lua 问题H5/小游戏服常见;Pomelo/裸 Node 均此路
jsb/WebSocket 引擎(Cocos Creator 服务端)自行开发模块管理器替换模块级少量自行开发-
QuickJS 嵌入式(skynet-js 等)重建 JS contextcontext 级状态迁移需显式新兴,量少

2.5 C++/其他 ​

方案机制评价
动态库 dlopen/dlsym 替换.so 重载危险,极少生产使用;Plywood/自行开发引擎
etcd/配置驱动"热逻辑"逻辑外置为数据(表达式/规则/DSL)不是代码热更但达成同一目的,见配置热更新设计文档
Go 游戏服不可热更(静态编译);社区方案是 so 插件/热重启(graceful + fd 传递)croupier 自身即 Go,运维面用滚动重启

2.6 横向总结 ​

维度Lua(skynet)Python(KBE)JavaJS(Node)
成熟热更生态★★★★(inject 惯例)★★(BigWorld 血统有但社区弱)★★★★(Arthas)★★
推荐粒度函数/模块模块(仅数值类安全)类(不改签名)模块(CJS)
状态保持难点upvalue/协程__class__ 重指字段签名require.cache/闭包
平台对接面agent 上放包+触发 reload RPC同左attach agent jar同 Lua
安全热更范围逻辑函数;数值必安全数值/纯函数方法体纯函数模块

3. 设计 ​

3.1 总体:通道平台化,机制适配器化 ​

管理台(croupier)                     游戏服宿主
┌─────────────────┐   ①上传热更包    ┌──────────────────────┐
│ Hotpatch 管理     │ ─────────────▶ │ croupier agent        │
│ (对象存储+版本+   │   ②按区服灰度   │  └ hotpatch runner     │
│  灰度+审批+回滚)  │ ◀───────────── │     └ adapter(按框架)  │
└─────────────────┘   ③执行结果/心跳   │       skynet|kbe|jvm|js│
                                     └──────────────────────┘

平台职责(框架无关):包托管(复用 release 的 objstore 通道)、目标选择(区服/节点灰度)、两双人审批(复用 approvals)、执行编排(复用 task/jobs)、结果确认与自动回滚、全程审计。

适配器职责(框架相关,agent 内实现):校验包结构 → 备份当前版本 → 调用框架 reload(inject/reload/attach/require)→ 自检(ping/关键接口探活)→ 失败自动还原备份。

3.2 数据模型(平台侧) ​

Hotpatch
├── GameID/Env + TargetSelector(区服/节点标签,复用 assignment 选择器语义)
├── Framework     skynet | kbengine | jvm | nodejs | custom
├── PackageKey    objstore 键 + Checksum(强制 sha256,防中间篡改)
├── EntrySpec     框架适配器参数(如 skynet: {entry: "inject.lua"}; jvm: {classFilter: "com.acme.**"})
├── Status        draft → approved(双人) → rolling(灰度执行) → applied → rolled_back / failed
├── Rollout       复用 release 的分桶思路按「节点」灰度(非设备)
├── 产物          每 agent 执行结果(成功/失败/回滚原因/日志)
└── 关联          BugID(对应缺陷追踪,修复上线闭环)

3.3 适配器契约(agent 内接口) ​

go
type HotpatchAdapter interface {
    // Validate 检查包结构是否符合框架惯例(lua 文件树/jar/zip 模块集)
    Validate(pkg Package) error
    // Apply 应用并返回自检句柄;必须先 Backup 再 Apply
    Apply(ctx, pkg) (Verify func(ctx) error, err error)
    // Rollback 还原 Apply 前快照
    Rollback(ctx) error
}

P1 实现顺序:skynet(lua inject)→ nodejs(require cache)→ jvm(attach)→ kbengine——按使用频率与风险排序。

3.4 安全红线 ​

  • 热更包内容平台不解析不审计语义(无法判断 lua 代码意图),所以:双人审批强制、仅限定目标集合、checksum 端到端校验、执行结果 5 分钟内自检失败自动回滚;
  • 禁止热更框架核心模块(adapter 的 EntrySpec 白名单约束,如 skynet 禁止触碰 skynet.* 内建);
  • 每次热更强制关联缺陷或工单编号(来源可溯),审计链记录操作者/包哈希/目标/结果。

4. 阶段 ​

阶段内容
P0(已落地)平台热更通道:Hotpatch 模型 + 包托管 + agent 下发确认协议(无框架 reload,先打通管理面)
P1skynet 与 nodejs 适配器(社区惯例最成熟、风险最低)
P2jvm attach 适配器;按节点分桶灰度;自检失败自动回滚
P3kbengine 类重指适配器;热更效果验证 DSL(应用后自动调用指定函数比对返回)

5. Review Checklist ​

  • 适配器必须先备份后应用,Rollback 必须可重入;
  • EntrySpec 白名单在平台与适配器双侧校验;
  • 热更包执行前 agent 校验 checksum 与平台记录一致;
  • 未经双人审批的 Hotpatch 不可进入 rolling(复用 approvals 的强制位);
  • 新增 Framework 枚举需同步适配器注册表与文档 §2 对比表。