2. CollectionEvent 定义:核心概念与生命周期

CollectionEvent 是事件驱动架构中数据采集的最小业务单元,它记录了一次“发生了什么”的完整事实。在报告订阅场景中,CollectionEvent 既是触发条件判定的输入源,也是订阅配置最终消费的数据载体。理解其定义、生命周期和元数据结构,是后续配置触发规则与订阅策略的基础。

2.1 什么是 CollectionEvent

CollectionEvent 是一个不可变的事实记录,表示在特定时间点、由特定实体发起的、具有明确业务含义的事件。它与传统日志或消息的区别在于:

  • 业务语义明确:每个事件都携带预定义的业务类型(如 order.created、device.offline),而非原始文本。
  • 结构化元数据:事件体遵循统一的数据模型,便于下游订阅者按字段过滤和聚合。
  • 一次写入、多次消费:事件一旦生成即不可修改,可被多个订阅规则独立消费。
关键认知:CollectionEvent 不是“消息队列中的一条消息”,而是“业务事实的持久化快照”。订阅配置中的触发条件本质上是针对事件元数据的布尔表达式。

2.2 事件生命周期:四个阶段

一个 CollectionEvent 从产生到归档,经历四个明确的阶段。每个阶段对应不同的系统职责和订阅行为。

阶段 触发动作 状态 订阅系统行为
创建 业务系统调用 SDK / API 提交事件 pending 事件进入缓冲区,等待校验与路由
触发 事件通过校验,匹配至少一条订阅规则 triggered 生成触发记录,准备投递
消费 订阅者拉取或推送接收事件 consumed 记录投递成功/失败,支持重试
归档 事件超过保留期或已确认消费 archived 移入冷存储,不再参与实时匹配
生命周期约束:事件一旦进入 archived 状态,即使后续有新的订阅规则匹配,也不会重新触发。因此,订阅配置的生效时间窗口必须覆盖事件的创建时间。
CollectionEvent 生命周期四阶段 创建 pending 触发 triggered 消费 consumed 归档 archived 说明:事件一旦进入“归档”状态,不再参与实时匹配。订阅规则仅对“触发”阶段的事件生效。

2.3 事件元数据结构设计

元数据是 CollectionEvent 的核心载荷,决定了订阅配置中“按什么条件触发”的能力边界。一个标准的事件元数据包含以下五个层级:

  1. 事件头(Event Header):全局唯一 ID、事件类型、版本号、创建时间戳。
  2. 来源上下文(Source Context):产生事件的系统、服务、租户、环境(prod/staging)。
  3. 业务主体(Business Entity):事件关联的业务对象 ID 和类型(如订单号、设备序列号)。
  4. 事件载荷(Event Payload):业务变更的具体字段,通常为 JSON 对象。
  5. 扩展标签(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" 将只匹配华东区域的支付事件。
CollectionEvent 元数据五层结构 CollectionEvent 元数据分层结构 Header event_id | event_type | event_version | created_at Source source_system | tenant_id | environment Entity entity_id | entity_type Payload 业务变更 JSON 对象(最大 64KB) Tags key:value 键值对,用于快速过滤(如 region:cn-east, priority:high)

2.6 生命周期与元数据的协同

元数据中的 event_type 和 created_at 直接决定了事件在生命周期中的流转路径:

  • 创建阶段:系统根据 event_type 将事件路由到对应的订阅规则匹配器。
  • 触发阶段:匹配器读取 tags 和 payload 中的字段,与订阅规则的条件表达式进行比对。
  • 消费阶段:订阅者根据 entity_id 和 source_system 决定如何处理事件。
  • 归档阶段:系统根据 created_at 计算保留时间,超过 TTL 后自动归档。
最佳实践:在订阅配置中,优先使用 event_type + tags 组合作为触发条件,避免在 payload 深层字段上建立复杂规则。这既能保证匹配性能,也能降低元数据版本升级时的兼容成本。