GeWuYou a79f02c987 docs(api): 添加 Core API 参考文档与事件系统接口文档
- 新增 Core API 参考文档,涵盖架构与模块、数据模型与系统、命令与查询等核心组件
- 添加事件系统接口详细文档,包括 IEvent、IEventBus、IUnRegister 等接口说明
- 提供完整的 API 使用示例路径、最佳实践与性能建议
- 包含架构图、依赖关系图与故障排查指南
- 添加测试用例参考与扩展方法说明
- [skip ci]
2026-01-21 23:45:10 +08:00

18 KiB
Raw Blame History

事件溯源模式

**本文引用的文件** - [GFramework.Core\events\EasyEvent.cs](file://GFramework.Core/events/EasyEvent.cs) - [GFramework.Core\events\EasyEventGeneric.cs](file://GFramework.Core/events/EasyEventGeneric.cs) - [GFramework.Core\events\EasyEvents.cs](file://GFramework.Core/events/EasyEvents.cs) - [GFramework.Core\events\EventBus.cs](file://GFramework.Core/events/EventBus.cs) - [GFramework.Core.Abstractions\events\IEventBus.cs](file://GFramework.Core.Abstractions/events/IEventBus.cs) - [GFramework.Core\model\AbstractModel.cs](file://GFramework.Core/model/AbstractModel.cs) - [GFramework.Core\state\StateMachine.cs](file://GFramework.Core/state/StateMachine.cs) - [GFramework.Core\state\StateChangedEvent.cs](file://GFramework.Core/state/StateChangedEvent.cs) - [GFramework.Game\storage\FileStorage.cs](file://GFramework.Game/storage/FileStorage.cs) - [GFramework.Core.Abstractions\storage\IStorage.cs](file://GFramework.Core.Abstractions/storage/IStorage.cs) - [docs\tutorials\advanced-patterns.md](file://docs/tutorials/advanced-patterns.md) - [docs\api-reference\core-api.md](file://docs/api-reference/core-api.md) - [GFramework.Core.Tests\events\EventTests.cs](file://GFramework.Core.Tests/events/EventTests.cs) - [GFramework.Core.Tests\tests\SyncArchitectureTests.cs](file://GFramework.Core.Tests/tests/SyncArchitectureTests.cs) - [GFramework.Core.Tests\architecture\ArchitectureContextTests.cs](file://GFramework.Core.Tests/architecture/ArchitectureContextTests.cs)

目录

  1. 简介
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖分析
  7. 性能考量
  8. 故障排查指南
  9. 结论
  10. 附录

简介

本教程围绕事件溯源Event Sourcing在 GFramework 中的应用展开,结合现有事件总线、状态机与存储设施,系统讲解事件存储设计、事件流版本控制、快照策略、聚合根重建、事件应用与重放、并发控制(版本检查)、事件流分片与索引等主题。同时给出面向游戏开发的实际场景:玩家状态变更记录、游戏进度跟踪、审计日志等。

项目结构

GFramework 的事件系统由“事件基础设施”“事件总线”“状态机”“存储层”组成;事件溯源所需的“事件存储”“聚合根”“快照”等概念在现有模块基础上可直接扩展实现。

graph TB
subgraph "事件基础设施"
E1["EasyEvent.cs"]
E2["EasyEventGeneric.cs"]
E3["EasyEvents.cs"]
end
subgraph "事件总线"
EB["EventBus.cs"]
IEB["IEventBus.cs"]
end
subgraph "状态机"
SM["StateMachine.cs"]
SCE["StateChangedEvent.cs"]
end
subgraph "存储层"
FS["FileStorage.cs"]
IS["IStorage.cs"]
end
E1 --> EB
E2 --> EB
E3 --> EB
EB --> SM
SM --> SCE
EB --> FS
FS --> IS

图示来源

章节来源

核心组件

  • 事件基础设施:提供简单事件、泛型事件与全局事件管理器,支撑事件注册、注销与触发。
  • 事件总线:基于类型分发事件,支持同步/异步处理器,可与事件存储集成实现事件持久化。
  • 状态机:内置状态切换、历史记录与回退能力,可作为聚合根重建过程的参考实现。
  • 存储层:提供键值存储的抽象与文件系统实现,可作为事件存储的持久化载体。

章节来源

架构总览

事件溯源在 GFramework 中的落地路径如下:

  • 命令/查询驱动业务,产生领域事件;
  • 事件总线负责分发事件,可选地将领域事件持久化至事件存储;
  • 聚合根根据事件重建状态(可参考状态机的历史机制);
  • 快照定期截断事件流,加速重建;
  • 查询侧通过投影或读模型提供高效查询。
sequenceDiagram
participant Cmd as "命令/查询"
participant Bus as "事件总线"
participant Store as "事件存储"
participant Agg as "聚合根"
participant Proj as "投影/读模型"
Cmd->>Bus : "发布领域事件"
Bus->>Store : "可选:保存事件流"
Store-->>Bus : "确认保存"
Bus->>Agg : "分发事件"
Agg->>Agg : "应用事件重建状态"
Agg-->>Proj : "更新投影"
Proj-->>Cmd : "查询结果"

图示来源

详细组件分析

事件基础设施与事件总线

  • EasyEvent/EasyEventGeneric提供事件注册、注销与触发支持无参与单/双参数事件。
  • EasyEvents全局事件管理器按类型缓存事件实例支持获取或创建。
  • EventBus基于类型分发事件提供 Send/Register/UnRegister可与事件存储集成。
classDiagram
class EasyEvent {
+Register(onEvent) IUnRegister
+UnRegister(onEvent) void
+Trigger() void
}
class Event_T_ {
+Register(onEvent) IUnRegister
+UnRegister(onEvent) void
+Trigger(t) void
}
class Event_T_TK_ {
+Register(onEvent) IUnRegister
+UnRegister(onEvent) void
+Trigger(t, k) void
}
class EasyEvents {
+GetOrAddEvent<T>() T
+GetEvent<T>() T
}
class EventBus {
+Send<T>()
+Send<T>(e)
+Register<T>(onEvent) IUnRegister
+UnRegister<T>(onEvent) void
}
EventBus --> EasyEvents : "使用"
EasyEvents --> EasyEvent : "管理"
EasyEvents --> Event_T_ : "管理"
EasyEvents --> Event_T_TK_ : "管理"

图示来源

章节来源

状态机与聚合根重建(参考实现)

状态机具备状态切换、历史记录与回退能力,可作为聚合根重建过程的参考:

  • 历史记录限制最大长度;
  • 回退时跳过未注册状态;
  • 切换前后触发进入/退出与变更事件。
flowchart TD
Start(["进入 ChangeInternal"]) --> CheckSame["是否相同状态?"]
CheckSame --> |是| End(["结束"])
CheckSame --> |否| PushHistory["压入历史记录(受长度限制)"]
PushHistory --> ExitOld["旧状态 OnExit"]
ExitOld --> SetCurrent["设置 Current=next"]
SetCurrent --> EnterNew["新状态 OnEnter"]
EnterNew --> FireChanged["触发状态变更事件"]
FireChanged --> End

图示来源

章节来源

事件存储与持久化(基于现有存储设施)

事件存储可基于 IStorage/FileStorage 实现:

  • 键空间规划:以聚合标识符为前缀,事件序号为后缀,形成有序事件流;
  • 并发控制:使用键级锁(类似 FileStorage 的 keyLocks保障同一聚合的写入串行
  • 序列化:事件对象序列化为文本/二进制,配合压缩与批量化提升吞吐;
  • 分片与索引:按聚合类型/时间维度分片,建立事件索引(起止偏移、时间戳索引)便于快速定位。
classDiagram
class IStorage {
+Exists(key) bool
+Read<T>(key) T
+Read<T>(key, default) T
+ReadAsync<T>(key) Task<T>
+Write<T>(key, value) void
+WriteAsync<T>(key, value) Task
+Delete(key) void
}
class FileStorage {
-_keyLocks : ConcurrentDictionary
-ToPath(key) string
+Read<T>(key) T
+Write<T>(key, value) void
+Exists(key) bool
}
IStorage <|.. FileStorage

图示来源

章节来源

事件流版本控制与并发控制(版本检查)

  • 版本号在事件头中携带期望版本号ExpectedVersion提交时校验
  • 并发冲突:若版本不匹配,拒绝写入并提示重试;
  • 重试策略:指数退避+超时,避免活锁;
  • 乐观锁:适用于低冲突场景;高冲突建议引入分片或分区。
flowchart TD
A["准备提交事件流"] --> B["读取当前版本号"]
B --> C{"版本匹配?"}
C --> |是| D["写入事件并递增版本"]
C --> |否| E["抛出并发异常并重试"]
D --> F["提交成功"]
E --> A

(本图为概念流程,无需图示来源)

快照策略与性能优化

  • 快照周期:每 N 个事件生成一次快照N 可配置),减少重建开销;
  • 快照格式:序列化聚合当前状态,附带快照时间戳与事件索引;
  • 重建流程:先加载快照,再按顺序应用其后的事件,提升启动速度;
  • I/O 优化:批量写入、异步读写、压缩事件与快照、预读策略。
flowchart TD
S0["事件流"] --> S1["达到快照周期?"]
S1 --> |否| S0
S1 --> |是| S2["生成快照(状态+索引)"]
S2 --> S3["写入快照存储"]
S3 --> S4["裁剪事件流(保留快照后事件)"]
S4 --> S0

(本图为概念流程,无需图示来源)

事件应用方法与重放机制

  • 事件应用:聚合根暴露 Apply 方法族,接收事件并更新内部状态;
  • 重放顺序:严格按事件时间戳/序号顺序应用;
  • 错误处理:单个事件失败不影响整体重放,记录失败事件并继续;
  • 审计日志记录事件元数据时间、聚合ID、版本、应用者
sequenceDiagram
participant Reader as "读取器"
participant Agg as "聚合根"
participant Store as "事件存储"
Reader->>Store : "按聚合ID读取事件流"
Store-->>Reader : "事件列表(有序)"
loop "逐条应用"
Reader->>Agg : "Apply(事件)"
Agg-->>Reader : "状态更新"
end
Reader-->>Reader : "重放完成"

(本图为概念流程,无需图示来源)

实际游戏应用场景

  • 玩家状态变更记录:角色等级、属性变化、装备穿戴等事件可被持久化与重放,用于回溯与审计;
  • 游戏进度跟踪:关卡通关、成就解锁、排行榜更新等事件驱动投影;
  • 审计日志:记录关键操作(如充值、封禁)的完整历史,满足合规要求。

章节来源

依赖分析

事件溯源在 GFramework 中的耦合关系:

  • 事件总线依赖事件基础设施与存储接口;
  • 状态机与事件总线解耦,可通过事件驱动状态切换;
  • 存储层提供统一抽象,便于替换实现(内存/文件/数据库)。
graph LR
IEB["IEventBus.cs"] --> EB["EventBus.cs"]
EB --> EFS["EasyEvents.cs"]
EFS --> EE["EasyEvent.cs"]
EFS --> EEG["EasyEventGeneric.cs"]
EB --> FS["FileStorage.cs"]
FS --> IS["IStorage.cs"]
EB --> SM["StateMachine.cs"]
SM --> SCE["StateChangedEvent.cs"]

图示来源

章节来源

性能考量

  • 写入性能:批量化事件、异步写入、压缩;对同一聚合使用键级锁避免争用;
  • 读取性能:事件索引、快照、投影;按需加载与惰性重建;
  • 存储成本:事件不可变,长期增长;通过快照裁剪与归档降低热数据体积;
  • 查询复杂性:事件存储不利于复杂查询;建议通过投影/物化视图提供查询接口。

(本节为通用指导,无需章节来源)

故障排查指南

  • 事件未触发:检查事件注册/注销是否正确,确认事件类型与处理器签名一致;
  • 并发冲突:检查版本号期望值与实际版本是否一致,必要时增加重试与退避;
  • 存储异常:核对键路径合法性、文件权限与磁盘空间,关注锁竞争问题;
  • 重放失败:定位失败事件,记录并隔离,确保后续事件继续应用。

章节来源

结论

事件溯源在 GFramework 中具备良好的扩展基础:事件总线提供事件分发与持久化入口,状态机体现聚合重建思路,存储层提供统一持久化抽象。结合版本控制、快照与索引策略,可在保证数据完整性与审计能力的同时,兼顾性能与可维护性。

附录