异构广告数据接入:把变化收进配置,但保留发布边界
设计 JSON、CSV、Protobuf 共用的接入内核,讨论动态映射、回放与灰度发布。
Read in English →工程学习与设计笔记。示例使用合成场景;适用版本与参考资料见正文。
不同来源可能给出 Kafka 消息、对象存储文件或 HTTP 回调,内容又可能是 JSON、CSV、Protobuf。为每个来源复制一套作业,初期很快,后面修一次时间解析错误却要改十几个分支。更稳妥的方向是共用加工内核,把来源差异收在适配层和映射规则里。
“配置化”仍然是软件发布:一行错误配置也能影响整批事件。下面讨论一种参考设计。
统一的是加工语义,不是来源游标
可以把链路拆成:读取 → 解码 → 映射 → 校验 → 增强 → 输出。每一步返回结果或结构化错误,尽量不直接操作来源 offset。这样离线回放和实时消费能调用同一套映射与校验代码。
读取层仍需保持自己的语义。Kafka 使用分区与 offset,文件使用对象身份、版本及记录位置;它们不适合被压成一个含糊的 lastPosition。比如 S3 事件通知是至少一次投递,重复通知不等于新文件,文件处理必须有自己的幂等记录。AWS S3 Event Notifications
一个实用的来源信封可以包含:source_id、来源定位信息、读取时间、原始内容摘要和解析版本。这里摘要用于定位与校验,不能取代原始内容的受控保留。敏感原文不进入普通错误日志。
映射规则要像代码一样严格
source: demo_partner
mapping_version: 12
fields:
event_id:
from: $.tracking.id
required: true
event_time:
from: $.timestamp
transform: epoch_millis_to_utc
amount_minor:
from: $.price
transform: decimal_major_to_minor
currency_from: $.currency
这是示意配置,重点是显式声明单位与转换函数。不要允许随意执行脚本,也不要把所有错误都转成空值。配置载入时应检查字段路径、目标类型、枚举值和转换参数;执行时则记录到底是哪条规则失败。
Java 的 DynamicMessage 可以基于 Descriptor 处理动态消息类型,因此能减少目标结构变化导致的生成代码发布。但它解决的是消息结构表达,不会自动保证映射正确、线程安全或无损回滚。Protobuf DynamicMessage
建议把 Descriptor、mapping、校验规则打成不可变版本包。一个事件从开始到结束只引用同一份快照,避免处理中途恰好热更新,导致前半段用旧规则、后半段用新规则。
兼容性和语义正确性分别验证
Protobuf 字段编号不能在删除后随意复用;格式兼容也不代表业务兼容。把“分”改成“元”即使仍是整数类型,下游也会产生一百倍偏差。Protobuf proto3 指南
我会给每个来源维护一个小而稳定的契约样本集:正常输入、缺失字段、非法类型、未知字段、边界金额、时区差异、重复记录和历史版本。结构校验通过后,再比较业务断言,例如金额范围、事件时间、必填 ID 与输出枚举。
LLM 可以辅助生成字段映射建议和补充测试样本,但建议不应直接替换生产规则。最有价值的输出是“候选映射 + 依据 + 不确定项”,随后跑确定性的校验与 diff。拿不到明确单位时返回未决,比模型猜一个合理值更可靠。
发布要能定位,也要能撤回
发布前,把一段受控样本分别送入旧、新版本,比较解析率、缺省率、事件分布和字段级差异。灰度时按来源或固定哈希分组,避免同一事件的重试随机落到不同规则。每条输出记录规则版本,出现问题时才知道哪些结果需要修复。
回滚配置只改变后续处理,不会自动恢复已经写出的错误数据。因此发布记录还要保存影响范围、可重放的来源定位、下游幂等键与修复方案。对外部写入,先证明重复处理不会重复计费或累计,再谈一键重放。
接入完成后的质量看板应按来源和版本切分。某个小来源的必填字段缺失率从零升到百分之十,可能在全局成功率上几乎不可见。除了比例,还应展示绝对错误数、首次出现时间和脱敏样本定位,便于直接找到上游变更。
验收时故意模拟三个故障:加载半份配置、处理中文件被覆盖、输出成功后进程退出。分别确认版本包原子切换、对象身份检查以及重放幂等是否成立。系统能解释这些边界,配置化才真正减少了维护成本。
参考资料
- AWS S3 Event Notifications ,至少一次通知语义。
- Protobuf DynamicMessage Java API ,基于 Descriptor 的消息处理。
- Protobuf proto3 Language Guide ,字段编号、保留字段与演进约束。