2. CollectionEvent 定义:核心概念与生命周期
CollectionEvent 是事件驱动架构中数据采集的最小业务单元,它记录了一次“发生了什么”的完整事实。在报告订阅场景中,CollectionEvent 既是触发条件判定的输入源,也是订阅配置最终消费的数据载体。理解其定义、生命周期和元数据结构,是后续配置触发规则与订阅策略的基础。
2.1 什么是 CollectionEvent
CollectionEvent 是一个不可变的事实记录,表示在特定时间点、由特定实体发起的、具有明确业务含义的事件。它与传统日志或消息的区别在于:
- 业务语义明确:每个事件都携带预定义的业务类型(如
order.created、device.offline),而非原始文本。 - 结构化元数据:事件体遵循统一的数据模型,便于下游订阅者按字段过滤和聚合。
- 一次写入、多次消费:事件一旦生成即不可修改,可被多个订阅规则独立消费。
关键认知:CollectionEvent 不是“消息队列中的一条消息”,而是“业务事实的持久化快照”。订阅配置中的触发条件本质上是针对事件元数据的布尔表达式。
2.2 事件生命周期:四个阶段
一个 CollectionEvent 从产生到归档,经历四个明确的阶段。每个阶段对应不同的系统职责和订阅行为。
| 阶段 | 触发动作 | 状态 | 订阅系统行为 |
|---|---|---|---|
| 创建 | 业务系统调用 SDK / API 提交事件 | pending |
事件进入缓冲区,等待校验与路由 |
| 触发 | 事件通过校验,匹配至少一条订阅规则 | triggered |
生成触发记录,准备投递 |
| 消费 | 订阅者拉取或推送接收事件 | consumed |
记录投递成功/失败,支持重试 |
| 归档 | 事件超过保留期或已确认消费 | archived |
移入冷存储,不再参与实时匹配 |
生命周期约束:事件一旦进入
archived 状态,即使后续有新的订阅规则匹配,也不会重新触发。因此,订阅配置的生效时间窗口必须覆盖事件的创建时间。
2.3 事件元数据结构设计
元数据是 CollectionEvent 的核心载荷,决定了订阅配置中“按什么条件触发”的能力边界。一个标准的事件元数据包含以下五个层级:
- 事件头(Event Header):全局唯一 ID、事件类型、版本号、创建时间戳。
- 来源上下文(Source Context):产生事件的系统、服务、租户、环境(prod/staging)。
- 业务主体(Business Entity):事件关联的业务对象 ID 和类型(如订单号、设备序列号)。
- 事件载荷(Event Payload):业务变更的具体字段,通常为 JSON 对象。
- 扩展标签(Tags):用于快速过滤的键值对集合,支持订阅规则中的标签匹配。
设计陷阱:不要在 Payload 中嵌套深层 JSON(超过 3 层),否则订阅规则中的路径表达式(如
payload.details.items[0].sku)会显著增加解析开销。建议将高频过滤字段提升到 Tags 或 Header 层级。
2.4 元数据字段规范表
| 层级 | 字段名 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| Header | event_id |
UUID | 是 | 全局唯一,用于去重和幂等消费 |
| Header | event_type |
string | 是 | 如 order.paid、device.alert |
| Header | event_version |
int | 是 | 元数据 schema 版本,用于向下兼容 |
| Header | created_at |
datetime | 是 | 事件创建时间,UTC 毫秒级 |
| Source | source_system |
string | 是 | 产生事件的系统名称 |
| Source | tenant_id |
string | 否 | 多租户场景下的租户标识 |
| Entity | entity_id |
string | 是 | 业务对象 ID |
| Entity | entity_type |
string | 是 | 业务对象类型,如 order、device |
| Payload | payload |
JSON | 否 | 业务变更详情,最大 64KB |
| Tags | tags |
map[string]string | 否 | 可搜索标签,用于订阅规则快速过滤 |
2.5 事件元数据 JSON 示例
{
"header": {
"event_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"event_type": "order.paid",
"event_version": 2,
"created_at": "2025-03-21T14:30:00.123Z"
},
"source": {
"source_system": "order-service",
"tenant_id": "tenant-001"
},
"entity": {
"entity_id": "ORD-20250321-001",
"entity_type": "order"
},
"payload": {
"total_amount": 299.99,
"currency": "CNY",
"payment_method": "wechat_pay",
"items": [
{"sku": "BOOK-001", "quantity": 2, "price": 99.99}
]
},
"tags": {
"region": "cn-east",
"priority": "high",
"channel": "mobile"
}
}
订阅配置关联:订阅规则中的触发条件可以直接引用上述字段。例如,规则
event_type == "order.paid" && tags.region == "cn-east" 将只匹配华东区域的支付事件。
2.6 生命周期与元数据的协同
元数据中的 event_type 和 created_at 直接决定了事件在生命周期中的流转路径:
- 创建阶段:系统根据
event_type将事件路由到对应的订阅规则匹配器。 - 触发阶段:匹配器读取
tags和payload中的字段,与订阅规则的条件表达式进行比对。 - 消费阶段:订阅者根据
entity_id和source_system决定如何处理事件。 - 归档阶段:系统根据
created_at计算保留时间,超过 TTL 后自动归档。
最佳实践:在订阅配置中,优先使用
event_type + tags 组合作为触发条件,避免在 payload 深层字段上建立复杂规则。这既能保证匹配性能,也能降低元数据版本升级时的兼容成本。