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

108 lines
4.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# BaseModule
**公共运行时库**:被 `ServerModule``CrossModule` 依赖。包含 **Netty TCP 帧编解码**、**CmdRpc 分发管线**、**Proto 元数据注册表**、**Spring 命令扫描** 以及与跨服调用相关的 **`CrossRpcInvoker` 接口**。
本模块 **不是** 可执行 Spring Boot 应用;随区服或跨服进程一起加载。
## 网络分层(逻辑)
```mermaid
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`**(含 `ChannelHandlerContext``CrossRpcInvoker`、解码结果等)。
5. **`CmdRpcDispatch.dispatchEnvelope(in, lookup, cctx)`** → 执行具体 **`GameCommand`**。
```mermaid
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>` | 依赖 `ProtoInfo``run(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` 与自动注册
- **`ProtoRegistry`**`register(ProtoInfo)` / `resolve(source, serviceId, methodId)`
- **`ProtoRegistryAutoConfigurer`**`SmartInitializingSingleton`):扫描带 `@Cmd``GameCommand`,若继承 **`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` 等)、**Netty**、**protobuf-java**、**slf4j-api**、**Lombok**(可选)。
- 生成的 proto Java 类来自 **ProtoBufModule**
## 包结构(主要)
```text
com.huangzj.base
├── cmd # 分发、上下文、注册表、Proto 反射、CrossRpcInvoker
├── frame # 长度前缀、Buf 工具
├── net # CmdRpcTcpFrameHandler
└── spring # SpringGameCommandRegistry、其它 Spring 辅助
```