KBEngine 文档KBEngine 文档
首页
源码学习
架构
API
资料
指南
GitHub
首页
源码学习
架构
API
资料
指南
GitHub
  • Part I 为什么长这样

    • 源码学习首页
    • 1. 导读与阅读方法
    • 2. BigWorld:问题、模型与核心概念
    • 3. KBEngine 系统全景
  • Part II 运行骨架

    • 4. 启动流程与进程模型
    • 5. EntityDef 与实体定义系统
    • 6. Python 运行时与脚本桥接
  • Part III 基础设施层

    • 7. 并发模型、线程与内存基础设施
    • 8. 网络基础设施:I/O 模型与进程间通信
    • 9. 分布式基础:ID、发现、注册与一致性
  • Part IV 通信与协作

    • 10. 序列化、Bundle 与网络消息
    • 11. RPC、EntityCall 与通信模式
    • 12. 属性同步与数据包广播
    • 13. 数据库、DBMgr 与持久化
  • Part V 空间、运动与拓扑

    • 14. Space、AOI 与视野系统
    • 15. 空间拓扑与动态扩容
    • 16. 移动、寻路与导航
    • 17. Ghost 系统
  • Part VI 脚本层行为

    • 18. 钩子、回调、定时器与事件
  • Part VII 前后端交互

    • 19. 客户端协议与前后端交互
  • Part VIII 运维、调试与稳定性

    • Ch20 可观测性:监控、性能分析与调试
    • Ch21 热更新、容错与运维工具
  • Part IX 串联与实战

    • Ch22 玩家完整生命周期
    • Ch23 BigWorld 与 KBEngine 对照
    • Ch24 实战源码走读
  • 阅读辅助

    • 全部目录
  • Appendix

    • 附录 A 源码阅读地图与下一步
    • 附录 B 关键算法速查
    • 附录 C 外部参考系统速查
    • 附录 D 专业术语速查
    • 附录 E 引擎适用场景与游戏类型选型指南
    • 附录 F 坐标系约定:BigWorld 与 KBEngine
    • 附录 G 服务器时间管理与世界时钟

附录 C 外部参考系统速查

本书多处将 BigWorld/KBEngine 的设计与外部系统做对比。本章提供这些系统的独立参考,方便读者理解对比的上下文。


C.1 gRPC / Protobuf:req-resp 模式的工业标准

是什么

gRPC 是 Google 开源的高性能 RPC 框架,使用 Protocol Buffers 作为接口定义语言和序列化格式。

核心模型

// .proto 文件定义服务接口
service EntityService {
  rpc GetEntity(EntityRequest) returns (EntityResponse);       // 单向
  rpc StreamEntities(EntityRequest) returns (stream Entity);   // 服务端流
  rpc UploadEvents(stream Event) returns (Ack);                // 客户端流
  rpc Chat(stream Message) returns (stream Message);           // 双向流
}

与 EntityCall 的对比

维度gRPCEntityCall
通信模式4 种(Unary + 3 种 Stream)1 种(Fire-and-forget)
接口定义.proto 文件.def 文件
服务发现DNS / Consul / etcdEntityDef 注册
调用目标无状态服务有状态实体
序列化Protobuf(强 schema)自定义流编码
连接模型HTTP/2 长连接TCP/UDP 长连接
流控HTTP/2 flow control应用层控制

为什么 MMO 不用 gRPC

  1. 有状态 vs 无状态:gRPC 设计目标是微服务(无状态),MMO 的 EntityCall 是有状态的实体间通信
  2. 延迟预算:HTTP/2 的帧复用和流控增加延迟,MMO 需要极致低延迟
  3. 序列化开销:Protobuf 的 tag-length-value 编码比引擎自定义流编码大
  4. 连接模型:gRPC 一个连接上多路复用,游戏服务器更倾向于一个 Channel 对应一个实体对
  5. 无实体概念:gRPC 的 service/method 不适合表达"对某个实体调用某个方法"

可以借鉴的

  • 接口定义语言(.proto → .def 的设计灵感来源)
  • 代码生成(protoc → EntityDef 代码生成)
  • 流式 RPC(在特定场景下,如大地图数据流,可借鉴)

C.2 nng:多模式通信

是什么

nng (Nanomsg Next Generation) 是一个轻量级消息传递库,提供多种通信模式。

通信模式

模式拓扑典型用途
Pair1:1两个组件直接通信
Req/Rep1:N请求-响应(同步)
Pub/Sub1:N主题订阅广播
Push/Pull1:N任务分发/收集
SurveyN:1一次查询,所有节点回复
BusN:N多方广播

与游戏服务器的对应

nng 模式游戏场景
PairBase ↔ Cell 的 EntityCall 通道
Pub/Sub属性同步(一个实体 → N 个客户端)
Push/Pull任务分发(BaseAppMgr → BaseApp 分配)
SurveyForwardingWatcher(一次查询所有 CellApp)
Req/Rep客户端登录(Login → DBMgr 查询)

Survey 模式的特殊价值

Survey 模式 = "一次询问,所有节点回复"
                ↓
BigWorld 的 ForwardingWatcher 本质上就是这个模式:
    BaseAppMgr 发 survey → 所有 BaseApp 回复 watcher 值
    CellAppMgr 发 survey → 所有 CellApp 回复负载信息

为什么游戏服务器不用 nng

  1. 延迟:nng 是通用库,没有针对游戏场景的优化
  2. 无实体抽象:nng 只有 socket,没有 Entity/EntityCall 的概念
  3. 无 AOI 集成:消息路由不感知空间位置
  4. 自定义协议:引擎需要深度定制消息格式(alias、压缩等)

C.3 Aeron:高性能 UDP 消息传递

是什么

Aeron 是一个高效的 UDP 消息传递库,设计目标是从日志复制到消息传递的统一传输。

核心设计

Publisher ──→ Media Driver ──→ Subscriber
              (共享内存/UDP)

关键特性:
1. 单播 (Unicast) + 多播 (Multicast)
2. 背压感知 (Back-pressure aware)
3. 零拷贝 (通过内存映射文件)
4. 可靠传输 (重传 + 去重)
5. 流控 (流量控制)

与 BigWorld Mercury 的对比

维度AeronBigWorld Mercury
传输层UDPUDP
可靠性内置(重传 + 去重)自建(PacketSender 重传)
背压显式流控隐式(Bundle 缓冲)
零拷贝内存映射文件无(标准内存拷贝)
多播原生支持无
定位通用消息总线游戏专用网络层

可以借鉴的

  1. 零拷贝:Aeron 通过内存映射避免内核态拷贝,BigWorld/KBEngine 都没用
  2. 背压感知:当消费者跟不上时,Aeron 显式通知生产者减速,游戏服务器通常只是丢包
  3. 多播:AOI 广播场景天然适合多播,但两套项目都没用

C.4 Twisted Deferred:BigWorld 的异步回调模型来源

是什么

Twisted 是 Python 的异步网络框架,其 Deferred 类是一种管理异步操作回调链的模式。

Deferred 的核心模型

from twisted.internet import defer

@defer.inlineCallbacks
def do_something():
    try:
        result1 = yield async_operation_1()
        result2 = yield async_operation_2(result1)
        defer.returnValue(result2)
    except Exception as e:
        handle_error(e)

# 等价于回调链:
d = async_operation_1()
d.addCallback(lambda r1: async_operation_2(r1))
d.addCallback(lambda r2: use_result(r2))
d.addErrback(handle_error)

Deferred 的内部结构

Deferred:
    callback chain: [cb1, cb2, cb3, ...]
    errback chain:  [eb1, eb2, eb3, ...]
    result:         当前值(初始为 None)

当异步操作完成时:
    → d.callback(result)
    → 依次执行 cb1(result) → cb2(cb1_result) → cb3(cb2_result)
    → 任何一步抛异常 → 跳到 errback chain

BigWorld 的 PyDeferred

// BigWorld: lib/entitydef/py_deferred.hpp

class PyDeferred : public PyObjectPlus
{
public:
    PyDeferred();

    // Python 接口
    PyObject* py_addCallback(PyObject* args);   // 添加回调
    PyObject* py_addErrback(PyObject* args);     // 添加错误回调
    PyObject* py_callback(PyObject* args);       // 触发成功
    PyObject* py_errback(PyObject* args);        // 触发失败

private:
    BW::vector<PyObject*> callbacks_;
    BW::vector<PyObject*> errbacks_;
    bool started_;
};

为什么 BigWorld 需要 Deferred

MMO 中的异步操作链:

1. 客户端发起 TwoWay EntityCall
   → d = entity.remoteMethod.twoWay(args)

2. 消息跨进程发送到目标 Entity
   → 目标处理完成,回复

3. 回复到达,Deferred 触发 callback
   → d.addCallback(onResult)
   → onResult 处理结果,可能触发下一个异步操作

4. 任何一步失败,走 errback
   → d.addErrback(onError)

KBEngine 为什么不需要 Deferred

KBEngine 用 CallbackMgr 替代:

# KBEngine 的方式
callbackID = KBEngine.addCallback(self.onResult)
entity.remoteMethod(args, callbackID)

# 回调直接执行,不支持链式
def onResult(self, result):
    # 处理结果
    pass

对比

维度Twisted DeferredCallbackMgr
链式调用d.addCallback().addCallback()无
错误处理内置 errback 链手动 try/catch
组合性可组合多个异步操作扁平回调
学习曲线较陡平缓
代码量更多更少
适用场景复杂异步编排简单回调

BigWorld 选 Deferred:因为 MMO 的很多操作是异步链式的(DB 查询 → 验证 → 创建实体 → 同步),Deferred 让这种链式代码更可读。

KBEngine 选 CallbackMgr:因为大部分操作不需要链式——发起一个请求,收到结果直接处理。简单场景不需要 Deferred 的复杂性。

Prev
附录 B 关键算法速查
Next
附录 D 专业术语速查