Skip to content

进程拓扑与职责切分

BigWorld 服务端不是单进程游戏服务器,而是多进程 MMO 运行时。理解它的第一步,是把“玩家会话”“全局实体”“空间模拟”“数据库”“登录入口”“控制面”和“故障恢复”拆开看。

核心结论

BigWorld 的进程拓扑体现了典型 MMO 服务器分层:

  • LoginApp 面向客户端登录入口。
  • BaseApp 承载玩家会话、Base 实体、全局逻辑和与客户端的连接关系。
  • CellApp 承载空间内实体、AOI、物理/位置、Cell 实体逻辑。
  • DBApp 承载数据库交互、实体持久化、账号/实体查询。
  • BaseAppMgrCellAppMgrDBAppMgr 是控制面和注册中心的一部分。
  • Reviver 负责监控关键组件并请求 machined 拉起恢复进程。

这不是现代微服务式按业务域切分,而是围绕 MMO 的运行时权威域切分。

进程拓扑

LoginApp

处理外部登录请求,完成挑战、认证、分配后续连接目标。

BaseApp

管理玩家在线会话、Base 实体、跨 Cell 协调和客户端通信。

CellApp

负责空间模拟、实体位置、AOI、Ghost、Cell 内逻辑。

DBApp

封装数据库任务,把阻塞数据库操作隔离到后台任务模型中。

Mgr 组件

负责注册、发现、负载信息、扩展接纳、恢复协调和全局控制。

Reviver

通过 ping、birth/death 消息和 machined 交互做进程级恢复。

BigWorld 服务端进程关系
 flowchart LR Client[Client] Login[LoginApp] Base[BaseApp] Cell[CellApp] DB[DBApp] BAM[BaseAppMgr] CAM[CellAppMgr] DBM[DBAppMgr] Rev[Reviver] Machined[machined] 

Client --> Login Client <--> Base Base <--> Cell Base <--> DB Cell <--> DB Base --> BAM Cell --> CAM DB --> DBM BAM <--> CAM DBM <--> BAM DBM <--> CAM Rev --> Machined Rev -. ping/death .-> BAM Rev -. ping/death .-> CAM

启动与注册链路

概述: BigWorld 服务端进程启动后,需要向 machined 注册,并与 Mgr 组件建立连接。这是进程发现和负载均衡的基础。

源码入口: baseappmgr.cpp:389

cpp
// baseappmgr.cpp:389 - BaseAppMgr 注册
bool BaseAppMgr::init( bool isReload )
{
    // 1. 注册 Mercury 接口
    if (!this->BaseAppMgrInterface::registerWithInterface())
    {
        ERROR_MSG( "BaseAppMgr::init: Failed to register interface\n" );
        return false;
    }
    
    // 2. 向 machined 注册
    if (!this->registerWithMachined())
    {
        ERROR_MSG( "BaseAppMgr::init: Failed to register with machined\n" );
        return false;
    }
    
    // 3. 监听其他组件 birth/death
    this->BaseAppMgrInterface::registerBirthListener( 
        &BaseAppMgr::onBaseAppBirth );
    this->BaseAppMgrInterface::registerDeathListener(
        &BaseAppMgr::onBaseAppDeath );
    
    return true;
}

流程图:

进程启动与注册流程
 sequenceDiagram participant Process as 服务进程 participant Machined as machined participant Mgr as Mgr 组件 participant Other as 其他进程 
Process->>Process: 初始化
Process->>Process: registerWithInterface()
Process->>Machined: 注册 (birth 消息)
Machined->>Mgr: 广播 birth
Mgr->>Mgr: addApp()
Mgr->>Process: 注册成功
Process->>Other: 监听 birth/death

详细讲解:

  1. 接口注册registerWithInterface() 注册 Mercury 消息处理器,让进程可以接收和处理消息。

  2. machined 注册registerWithMachined() 向 machined 发送 birth 消息,machined 会广播给其他进程。

  3. Mgr 接纳:Mgr 组件收到 birth 消息后,调用 addApp() 接纳新进程,更新进程列表和负载信息。

  4. birth/death 监听:进程监听其他组件的 birth/death 消息,用于服务发现和故障检测。

BaseAppMgr 启动流程

源码入口: baseappmgr.cpp:389

cpp
// baseappmgr.cpp:389 - BaseAppMgr 启动
bool BaseAppMgr::init( bool isReload )
{
    // ... 其他初始化 ...
    
    // 注册接口
    if (!this->BaseAppMgrInterface::registerWithInterface())
    {
        return false;
    }
    
    // 向 machined 注册
    if (!this->registerWithMachined())
    {
        return false;
    }
    
    // 监听 BaseApp birth
    this->BaseAppMgrInterface::registerBirthListener(
        &BaseAppMgr::onBaseAppBirth );
    
    // 监听 CellAppMgr birth
    this->CellAppMgrInterface::registerBirthListener(
        &BaseAppMgr::onCellAppMgrBirth );
    
    return true;
}

关键细节:

  • BaseAppMgr 需要知道所有 BaseApp 和 CellAppMgr
  • 通过 birth/death 消息维护进程列表
  • 负载信息通过定期上报收集

CellAppMgr 启动流程

源码入口: cellappmgr.cpp:238

cpp
// cellappmgr.cpp:238 - CellAppMgr 启动
bool CellAppMgr::init( bool isReload )
{
    // ... 其他初始化 ...
    
    // 注册接口
    if (!this->CellAppMgrInterface::registerWithInterface())
    {
        return false;
    }
    
    // 向 machined 注册
    if (!this->registerWithMachined())
    {
        return false;
    }
    
    // 监听 CellApp birth
    this->CellAppMgrInterface::registerBirthListener(
        &CellAppMgr::onCellAppBirth );
    
    return true;
}

关键细节:

  • CellAppMgr 管理所有 CellApp,负责空间分配和负载均衡
  • 收到 CellApp birth 后,调用 addApp() 接纳
  • 收到 CellApp death 后,触发实体恢复流程

职责边界

LoginApp

LoginApp 的职责是入口而不是长期会话承载。它注册外部 LoginInterface 和内部 LoginIntInterface,并监听 DBAppMgr 出生消息。源码入口在 loginapp.cpp

设计取舍:

  • 优点:登录入口与游戏会话隔离,便于限流和认证。
  • 代价:登录成功后的连接迁移、挑战协议、DB 查询链路更复杂。

BaseApp

BaseApp 是玩家在线会话和 Base 实体的核心进程。它需要知道 BaseAppMgrCellAppMgr,并处理其他 BaseApp 的 birth 消息。源码入口:

CellApp

CellApp 是空间模拟进程。它向 CellAppMgr 注册,由 CellAppMgr 统一做空间、Cell、负载均衡和恢复协调。CellApp 接入 CellAppMgr 的网关请求在 cellappmgr_gateway.cpp

Manager 组件

Mgr 组件不是业务微服务,而是控制面:

  • BaseAppMgr 管理 BaseApp 集合、负载和 BaseApp 之间的发现。
  • CellAppMgr 管理 CellApp、空间、Cell 边界、负载均衡和恢复。
  • DBAppMgr 管理 DBApp、数据库组件出生死亡、与 Base/Cell 管理器协调。

CellAppMgr::addApp() 是运行时接纳新 CellApp 的关键入口,见 cellappmgr.cpp

动态扩展的真实含义

BigWorld 支持运行中接纳新 BaseApp / CellApp,但源码里的扩展入口是进程注册、Mgr 接纳、负载再平衡和状态迁移,不是单纯拉起无状态副本。

更准确的模型是:

外部启动进程->向 machined / Mgr 注册->Mgr 接纳->负载再平衡->实体/Cell 迁移

这种设计的重点是运行时迁移和控制面协调,而不是只增加进程数量。

源码取舍

BigWorld 的进程拆分服务于明确的运行时职责边界:

  • 多进程天然隔离崩溃域,比单进程多线程更容易定位故障。
  • C++ 主循环加 Python 脚本嵌入,适合把性能敏感路径留在引擎层。
  • Manager 作为权威控制面,避免每个 App 都维护全局复杂状态。
  • machinedReviver 形成进程级发现、启动和恢复能力。
  • BaseApp、CellApp、DBApp、LoginApp 的进程角色和内部接口在源码中分别注册,便于按职责排查。

源码代价也很清楚:

  • 组件间耦合强,进程拓扑必须和 Mercury 接口、birth/death 通知、Mgr 状态一致。
  • 扩容是否有效取决于 Base/Cell 负载迁移,不取决于进程是否已经启动。
  • DBApp、BaseAppMgr、CellAppMgr 等控制面异常会影响多个业务路径。
  • 排障必须跨 machined、Manager、App 自身日志和 watcher 状态一起看。

源码验证重点

进程拓扑验证应覆盖注册、接纳和状态传播:

  • 各进程启动时必须注册对应 Mercury interface。
  • App 向 machined 注册的 component 类型、地址、pid 和 watcher nub 信息应正确。
  • CellAppMgr::addApp() 在缺少 BaseApp 或 Alpha DBApp 时不能接纳新 CellApp。
  • 新 BaseApp/CellApp 接纳后,Mgr watcher 中的数量、负载和 App 列表应同步更新。
  • birth/death 通知应能传播到依赖方,不能只在本地进程可见。
  • Reviver 或 machined 层面的重启不能绕过 BigWorld 自身的状态恢复流程。

后续研究入口

进程拓扑只是外壳。真正决定性能和扩展边界的是:

按源码证据链、源码取舍和验证边界组织,而不是按目录机械罗列。