APM 设置
安装应用性能监控以获得分布式 trace、服务地图和逐请求 profiling。
为什么
指标告诉你服务慢;APM 告诉你为什么。分布式 trace 跟踪单个请求跨每个服务、数据库、队列,所以 p95 延迟突增时你能看到 80% 时间花在库存服务里一条 Postgres 查询 — 而非"结账流某处"。服务地图给你随代码发布更新的实时依赖图,这是事件中理解爆炸半径的唯一可靠方式。没有 APM,微服务团队对跨服务延迟盲目,每次事件变成多团队互 相指责而非 5 分钟 trace 读取。
何时使用
当生产中有 2+ 服务互相调用时。单 monolith 可从指标 + 日志开始;第二个服务一出现就需要 trace 看跨边界。
如何做
1. 选匹配技术栈的 APM - 开源:OpenTelemetry SDK → Jaeger/Tempo 收集器(自托管)或 Grafana Cloud - 商业:Datadog、New Relic、Dynatrace、Honeycomb — 按语言支持 + 预算选 2. 在边界埋点 - HTTP 框架、DB 驱动、消息队列自动埋点(多数 APM 一个 agent 搞定) - 为业务逻辑加自定义 span:"validate_cart"、"apply_discount" — 非仅"handle_request" - 跨每跳传播 trace 上下文(W3C traceparent 头),含异步队列 3. 配置采样 - 头部:入口采样 1-10%(确定性、便宜、漏稀有错误) - 尾部:保留 100% 错误 + 慢 trace,其余采样(贵但抓异常) - 从 5% 头部 + 100% 错误开始;负担得起时转尾部采样 4. 建服务地图并用它 - 确认它匹配你的心智模型;缺边 = 缺埋点 - 事件中先看地图看爆炸半径再钻 trace 5. 加 trace-log 关联 - 把 trace_id 注入日志行,使 trace 链到该请求的确切日志 - 这是把"慢"(trace)变"为什么"(log)的一键桥梁
示例
// Node + OpenTelemetry 自动埋点
// tracing.js(用 --require ./tracing.js 加载)
const opentelemetry = require('@opentelemetry/sdk-node');
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');
new opentelemetry.NodeSDK({
traceExporter: new opentelemetry.ConsoleSpanExporter(), // → 生产用 OTLP 收集器
instrumentations: [getNodeAutoInstrumentations()],
}).start();
// 业务逻辑自定义 span
const tracer = opentelemetry.trace.getTracer('checkout');
app.post('/api/checkout', async (req, res) => {
const span = tracer.startSpan('checkout.validate_cart');
try { await validateCart(req.body); }
finally { span.end(); }
// ... DB 查询自动埋点为子 span
});
// 在 Jaeger:search service=checkout,按 duration 降序
// → 看慢 trace,展开 span,找到耗时 800ms 的 Postgres 查询常见问题
- ⚠忘记跨异步边界(队列、批处理)传播 trace 上下文 — 每跳一个新 trace 而非一条端到端,丢失跨服务视图。
- ⚠为省钱采样过激(0.1%)— 漏掉事件中正需要的稀有慢 trace;保留 100% 错误。
- ⚠只自动埋点 HTTP/DB 无业务逻辑 span — trace 显示"Postgres 800ms"但不显示哪条业务规则导致查询;加自定义 span。
- ⚠APM agent 开销推高延迟 — 每请求重 agent 加 5-10ms;安装后 p95 升高则基准测试并调采样。
最佳实践
- ✓跨每跳传播 W3C traceparent 头含异步队列和批处理 — 断裂 trace 链比无 trace 更糟因为它误导。
- ✓用尾部采样保留 100% 错误和慢 trace 同时采样正常流量 — 这抓异常而不破 预算。
- ✓为业务逻辑加自定义 span,非仅框架调用 — "apply_discount" 可行动;"postgres.query" 在 200 条查询时不可行动。
- ✓经 trace_id 注入关联 trace 与日志 — 从慢 span 一键跳到确切日志行使 APM 物有所值。