在 Jaeger UI 中如何定位一次慢查询的 Map 阶段耗时?
解读
面试官把“CouchDB 视图慢”与“Jaeger 分布式追踪”两个场景强行揉在一起,重点考察两点:
- 你是否真的理解 CouchDB Map 阶段发生在哪一段代码、哪一段进程;
- 你是否能把 Jaeger 的 span 语义与 CouchDB 内部耗时对应起来,而不是泛泛而谈“看耗时长的 span”。
国内生产环境常见套路是:CouchDB 以 集群+反向代理 方式部署,前面挂 Nginx/OpenResty,旁边独立跑 Jaeger Collector;视图请求走 /_view 或 /_design/ 路径,真正触发 Map 阶段的是 couch_index_updater 进程。
因此,定位思路必须围绕“给索引更新打 span → 在 Jaeger UI 用 tag 过滤 → 下钻到 Map 函数耗时”三步展开,缺一步都会被认为是“没在生产排过障”。
知识点
- CouchDB 视图更新链路:
HTTP → couch_mrview_http → couch_index_updater → JavaScript Map 函数 → 写 .view 文件。 - Jaeger 的 span 命名规范:
国内落地时,团队一般会自定义 span.kind=server 的入口 span 叫db.couchdb.view.query,内部再嵌套 span.kind=internal 的couch_index_updater.map子 span。 - 关键 tag:
db.name、db.couchdb.design_document、db.couchdb.view_name、db.couchdb.map_phase=true。 - Jaeger UI 过滤语法:
支持 key=value 精确匹配与 minDuration 阈值过滤,可把“>500 ms”的 Map 阶段一把抓出来。 - 国内排障经验:
如果 Map 阶段无独立 span,99% 是因为 couch_index_updater 没插桩;此时需要改 couchdb.trace.module 配置并重启节点,否则只能在“大 span”里干瞪眼。
答案
- 在 Jaeger UI 顶部 Search 栏里,Service 选 CouchDB 对应的 serviceName(通常是
couchdb或db-couch)。 - 在 Tags 输入框键入
db.couchdb.map_phase=true and db.couchdb.view_name=your_view,回车。 - 在 Min Duration 填
500ms,点“Find Traces”。 - 结果列表里找到耗时最长的 trace,点进去后,左侧时间轴会展开一条叫
couch_index_updater.map的 内部 span;该 span 的 Duration 就是一次慢查询的 Map 阶段耗时。 - 若未发现该 span,说明 CouchDB 未启用 细粒度追踪,需在每个节点
local.ini追加:
重启节点后重试即可。[tracing] enabled = true granularity = map_reduce
拓展思考
- 如果 Map 阶段耗时正常,但 Reduce 阶段突然飙高,如何在 Jaeger 区分?
答:在代码层给 Reduce 函数再埋一个span.name=couch_index_updater.reduce的 internal span,并通过 db.couchdb.reduce_phase=true 过滤,即可与 Map 阶段并排对比。 - 国内云厂商托管版 CouchDB 往往屏蔽了
/_node/_local/_config,无法改 ini,怎么办?
答:可退而求其次,在 Nginx 层用 OpenTracing C 模块,给/_view接口增加 x-trace-map-hint 头,把设计文档与视图名写进 baggage,再在 Jaeger 里用 baggage 字段过滤,虽不能精确到 Map 函数,也能把慢查询缩小到单视图级别。