APM 预计算适配共享数据源
0x01 背景
a. Why
共享数据源把一个 data_id 与多个 APM 应用关联。BMW 预计算任务在 data_id 维度静态绑定单应用上下文:
Processor.baseInfo:MetadataCenter.GetBaseInfo(dataId),构造期注入。MetricProcessor.appName:baseInfo.AppName,构造期注入。MetricDimensionsHandler.promClient的 token:MetadataCenter.GetToken(dataId),构造期注入。
直接复用现状会导致:
- 多应用的应用元数据在 Consul 互相覆盖。
- 所有 Span 归属到 Consul 最后写入的应用。
- 上报 Token 绑定首应用,其余应用指标走错租户。
- 历史 Span 回补仅按
trace_id查 ES,跨应用偶发trace_id撞库读到对方 Span。
b. 目标
- BMW 任务模型保持:
taskUniId仍按data_id派生,共享data_id单点绑定一份 Kafka 消费。 - 任务内多应用感知:
Processor/MetricProcessor按应用实例化,每应用独立持有应用上下文。 - 持久化键不变:子窗口
sync.Map、布隆过滤器、预计算结果表 ES_id保留裸trace_id。 - 独占模式行为完全保留。
0x02 实现路线
a. 建议的方案
方案 4「单任务多应用窗口」。
- 在
KafkaNotifier与DistributiveWindow之间插入Dispatcher,按 Span 顶层(bk_biz_id, app_name)路由到对应应用的appBundle。 appBundle是应用维度的三元组(DistributiveWindow, Processor, MetricProcessor),每应用一份。Proxy仍是单实例,仅prometheusMetricsHandler字段升级为map[AppKey]*MetricDimensionsHandler。
详细方案见 PLAN.md。
b. 约束
- 共享池规模上限由 SaaS 侧控制,BMW 侧不再考虑
M的上限。 Processor.traceEsQueryLimiter每Processor独立,与共享池大小线性。- 依赖父 issue 的 Consul 协议扩展:共享模式 Value 包含
apps[],元素见 PLAN.md0x02.e。 - 依赖父 issue 的数据写入约定:共享场景下,bk-collector 在 Span 顶层注入
bk_biz_id与app_name,来源是应用上报 Token 解析得到的应用上下文。
0x03 参考
- 父 issue:APM 支持跨应用共享数据源
- 实施方案:PLAN.md
- BMW 预计算模块:
pkg/bk-monitor-worker/internal/apm/pre_calculate/** - bk-collector 共享场景 Span 顶层字段注入:
pkg/collector/exporter/converter/traces.go