Files
2026-05-07 15:54:43 +08:00
..
2026-05-07 15:54:43 +08:00
2026-05-07 15:54:43 +08:00
2026-05-07 15:54:43 +08:00

BaseModule

公共运行时库:被 ServerModuleCrossModule 依赖。包含 Netty TCP 帧编解码CmdRpc 分发管线Proto 元数据注册表Spring 命令扫描 以及与跨服调用相关的 CrossRpcInvoker 接口

本模块 不是 可执行 Spring Boot 应用;随区服或跨服进程一起加载。

网络分层(逻辑)

flowchart TB
  subgraph TCP["TCP 字节流"]
    F["一帧: 4B length + body"]
  end
  subgraph Net["BaseModule / net & frame"]
    D["LengthPrefixedProtobuf 解码"]
    H["CmdRpcTcpFrameHandler"]
  end
  subgraph Cmd["BaseModule / cmd"]
    CD["CmdRpcChannelDispatch"]
    PR["ProtoRegistry → ProtoInfo"]
    PC["ProtoCommandReflect 解析 CTS / newBuilder STC"]
    DP["CmdRpcDispatch → GameCommand"]
  end
  F --> D --> H --> CD
  CD --> PR
  CD --> PC
  CD --> DP

1. 帧格式:LengthPrefixedProtobuf

  • 编码LengthPrefixedProtobuf.encodeMessage(alloc, CmdRpcEnvelope) — 先写 大端 int32 长度,再写 CmdRpcEnvelope.toByteArray()
  • 解码newTcpFrameDecoder() 返回 Netty 解码器,攒满一帧后向 pipeline 下游抛出 一条 ByteBuf(仅 body

这样 区服客户端 TCP跨服 TCP区服连跨服的 Outbound 三者 帧格式一致,仅 IP/端口与 CommandSource 不同。

2. 入站处理:CmdRpcTcpFrameHandler

  • 读取一帧 byte[],调用 CmdRpcChannelDispatch.dispatch(...)
  • 将返回的 CmdRpcEnvelope 再次 长度前缀编码 写回对端。
  • linkSource 由构造时注入:Client_TCP(区服接客户端)或 CROSS_TCP(跨服接入站)。

注意:默认在 Netty IO 线程 上执行命令;若 roundTrip 同步调跨服会阻塞该连接上的 IO,Demo 场景可接受,生产需评估线程模型。

3. 分发核心:CmdRpcChannelDispatch

步骤简述:

  1. CmdRpcEnvelope.parseFrom(raw)
  2. protoRegistry.resolve(linkSource, serviceId, methodId) → 可选的 ProtoInfo
  3. 若存在 ProtoInfo解析 payload 为 CTS创建 STC 的 Builder(网络层职责,命令内只填字段)。
  4. 构造 CommandContext(含 ChannelHandlerContextCrossRpcInvoker、解码结果等)。
  5. CmdRpcDispatch.dispatchEnvelope(in, lookup, cctx) → 执行具体 GameCommand
flowchart LR
  IN[CmdRpcEnvelope in]
  PI{ProtoInfo 存在?}
  DEC[解码 CTS + STC Builder]
  RAW[decoded=null 由命令自处理]
  EXE[GameCommand.execute]
  OUT[CmdRpcEnvelope out]
  IN --> PI
  PI -->|是| DEC --> EXE
  PI -->|否| RAW --> EXE
  EXE --> OUT

4. 命令模型

类型 说明
GameCommand execute(CommandContext, CmdRpcEnvelope),完全自控 payload。
AbstractTypedPbCommand<C, B> 依赖 ProtoInforun(ctx, cts, stcBuilder);回包信封 复制 service/method/cross_ret/link_seq

CommandSource 与注册

  • @Cmd(source, serviceId, methodId) 标注在命令类上。
  • SpringGameCommandRegistry:按 Spring 容器里 GameCommand Bean 扫描,只收录 source 属于当前进程配置集合的命令(区服只收 Client_TCP,跨服只收 CROSS_TCP)。

5. ProtoRegistry 与自动注册

  • ProtoRegistryregister(ProtoInfo) / resolve(source, serviceId, methodId)
  • ProtoRegistryAutoConfigurerSmartInitializingSingleton):扫描带 @CmdGameCommand,若继承 AbstractTypedPbCommand,则从泛型推断 CTS / STC 类型 并注册 ProtoInfo
  • 继承强类型基类的命令(如路径 3 中继)不注册 ProtoInfo,由命令自行处理 payload。

6. CrossRpcInvoker

  • 接口方法:CmdRpcEnvelope roundTrip(CmdRpcEnvelope request)
  • ServerModule 中由 CrossTcpClient 实现:维护至跨服的 长连接link_seq 多路复用、注册与心跳。

区服业务命令(路径 2/3)通过 CommandContext.crossRpc() 拿到该实例,向跨服发 CrossForward* 对应的信封。

7. 依赖说明

  • Spring Context@Component 等)、Nettyprotobuf-javaslf4j-apiLombok(可选)。
  • 生成的 proto Java 类来自 ProtoBufModule

包结构(主要)

com.huangzj.base
├── cmd          # 分发、上下文、注册表、Proto 反射、CrossRpcInvoker
├── frame        # 长度前缀、Buf 工具
├── net          # CmdRpcTcpFrameHandler
└── spring       # SpringGameCommandRegistry、其它 Spring 辅助