跳到主内容
Autional 徽标
Architecture10 分钟#可观测性#OpenTelemetry#分布式追踪

身份系统可观测性:OpenTelemetry 全链路追踪实践

2025 年一家大型 SaaS 平台的生产事故至今仍是鲜明警示:在没有分布式追踪的情况下,一个「登录慢」的用户投诉,从建单到定位根因,耗尽了 3 名 SRE 整整 6 个小时。罪魁祸首是 session-service 中 Redis 连接池的配置错误,导致每次校验令牌都新建连接——但因为没有追踪,团队只能逐个服务、逐个中间件手工排查,如同大海捞针。

这正是可观测性不是「锦上添花」,而是身份系统生命线的原因。当身份系统宕机或性能退化时,所有依赖它的业务系统都会随之不可用——而这个爆炸半径远超任何单一业务模块。

Autional 从第一天起就把可观测性当作一等公民,在 OpenTelemetry 之上构建了日志-指标-追踪三位一体的可观测体系。本文逐层拆解,并用真实案例演示如何快速定位问题。

可观测性三大支柱与身份系统的特殊需求

日志:记录「发生了什么」

传统日志的痛点不是数据太少,而是太多。一个中等规模的认证系统每天可产生数 GB 的访问日志,但真正发生故障时,运维人员往往迷失在非结构化的日志海洋中。

Autional 的结构化日志方案:

  • 78+ 个标准化日志键:所有日志都使用 base/logger 包中预定义的键常量,如 logger_base.KeyUserID、logger_base.KeyTraceID、logger_base.KeyErrorCode。这意味着你可以精确 grep 出某个用户的全部操作、某个错误码的全部出现,或某个追踪 span 内的每一步日志。
  • 请求级日志上下文:在每个 HTTP 请求上,中间件向 context.Context 注入 request_id、tenant_id、user_id、trace_id。后续所有 logger_base.FromContext(ctx) 调用都会自动携带这些标识。只要函数接收 ctx,就无需手工传递日志参数。
  • 完整错误链记录:error_base.Err 携带完整错误链(cause -> cause -> cause),在日志输出中自动展开为 "error_chain" 字段,让根因一目了然。
logger.Info("user login successful",
    slog.String(logger_base.KeyUserID, userID),
    slog.String(logger_base.KeyTenantID, tenantID),
    slog.Duration(logger_base.KeyDuration, elapsed),
)

指标:量化「发生了什么」

日志告诉你单次请求的细节;指标告诉你系统的宏观健康度。Autional 的 Prometheus 指标覆盖四个层次:

层次 示例指标 用途
HTTP 服务 http_requests_total, http_request_duration_seconds 请求量、延迟、错误率
领域事件 events_published_total, events_publish_duration_seconds 领域事件吞吐量与延迟
MQ 消费 mq_consumer_messages_total, mq_consumer_message_duration_seconds 消费速率、处理延迟、DLQ 积压
基础设施 db_connections_active, redis_commands_duration_seconds 连接池健康度、缓存命中率

这些指标通过 micro-middleware/metrics 中间件自动注册——业务代码无需手工埋点。但这不意味着你可以忽视指标。关键在于定义正确的告警规则,我们将在另一篇文章中详述。

追踪:理解「怎么发生的」

日志告诉你每一步的结果,指标告诉你系统的整体趋势。追踪把两者连接起来——它揭示一次请求跨越了多少个服务、每个服务耗时多久、瓶颈在哪里。

Autional 中一次典型的「用户登录」请求追踪:

flowchart TD
    G["gateway 1ms"] --> I["identity-service /auth/login 45ms"]
    I --> B["bcrypt 密码校验 30ms"]
    I --> J["JWT 令牌签发 2ms"]
    I --> A["audit-service /log 5ms,异步"]
    I --> S["session-service /session/create 8ms"]
    S --> R["Redis SET 2ms"]
    S --> P["PostgreSQL INSERT 4ms"]
    G --> PR["profile-service /profile/me 12ms,并行"]

图 1:一次典型登录的追踪树——bcrypt 校验 30ms 是最大头,审计投递与资料查询只是旁枝。

在旧架构下,如果投诉是「登录慢」,你得逐个 SSH 登录服务、手工查日志。有了分布式追踪,一屏就能看出 identity-service 的 bcrypt 耗时 30ms(占总耗时 65%),而 session-service 的 PostgreSQL INSERT 仅耗时 4ms——一切一目了然。

Autional 的 OpenTelemetry 落地架构

跨协议传播

身份系统的特殊之处在于需要同时支持三种通信协议:HTTP、gRPC 与 MQ。/auth/login 是 HTTP → HTTP,但 compliance-service 可能需要 gRPC 调用,审计日志则通过 MQ 异步投递。如果追踪上下文无法在协议之间顺畅流动,链路就会断裂。

Autional 的方案:

  • HTTP:采用 W3C Trace Context 标准,通过 traceparent 请求头传播。micro-middleware/tracing 中间件自动提取与注入。
  • gRPC:使用 otelgrpc 的 NewClientHandler() / NewServerHandler(),通过 gRPC metadata 传播。所有 gRPC 客户端连接强制注入 otelgrpc.NewClientHandler()。
  • MQ:micro-pkg/event.Publisher 在 buildHeaders 中自动注入 W3C traceparent。消费者通过 consumer/middleware.Tracing() 中间件提取。

这意味着即使业务链路跨越 HTTP → MQ → gRPC → HTTP,追踪依然完整。这对身份系统尤为关键,因为一次「用户注册」操作会触发审计落库(MQ)、钱包创建(HTTP)与默认角色分配(gRPC)。

集成方式

Autional 选择直接使用 OpenTelemetry SDK,而非厂商特定的 agent。好处是:

  1. 厂商中立:追踪数据可导出到任何兼容 OTLP 的后端——Jaeger、Tempo、Datadog、阿里云 ARMS——只需改一个环境变量:OTEL_EXPORTER_OTLP_ENDPOINT。
  2. 采样可配:开发环境 100% 采样;生产环境按需采样(如仅错误请求与慢请求),避免追踪数据爆炸。
  3. 零代码侵入:所有追踪逻辑由基础设施层中间件处理。业务代码只需正常传递 ctx——零手工埋点成本。

真实案例:用追踪排查登录慢

某天运维收到告警:「identity-service P99 延迟从 80ms 飙升至 500ms。」以下是利用分布式追踪定位根因的完整过程:

第一步:看大盘

打开 Grafana 的 http_request_duration_seconds 面板。确认延迟从 14:32 开始飙升,P99 从 80ms 升至 500ms。错误率正常——说明服务没有崩溃,只是性能退化。

第二步:找到代表性追踪

在追踪后端(如 Jaeger)查询 operation = POST /api/v1/auth/login 且 duration > 400ms 的追踪。随机抽取 5 条,发现共同规律:

flowchart TD
    I["identity-service auth/login 420ms"] --> B["bcrypt compare 28ms——正常"]
    I --> J["JWT generate 2ms——正常"]
    I --> S["session save 385ms——异常"]
    S --> P["PostgreSQL INSERT 383ms"]
    S --> R["Redis SET 2ms"]

图 2:案例中的异常追踪——bcrypt 与 JWT 都正常,385ms 全堆在 session save 上,问题直指 PostgreSQL 写入。

问题出在 session-service 的 PostgreSQL 写入。

第三步:关联日志

从追踪中拿到 trace_id,在 Loki 中按它检索日志(Autional 所有日志都携带 trace_id 字段):

14:32:15 [session-service] ERROR session save failed
  error="could not serialize access token" cause="pq: value too long for type character varying(1024)"
  trace_id=abc123
  user_id=01ARZ3NDEKTSV4RRFFQ69G5FAV

根因清晰了:某租户配置了异常庞大的 JWT claims(自定义字段过多),导致序列化后的令牌超出数据库列长度限制。修复方式:加大列长度,并在序列化前增加截断保护。

整个过程:从收到告警到定位根因——4 分钟。 没有可观测性系统,这个过程可能要花 4 小时。

追踪之外:可观测性的下一站

Autional 的可观测体系仍在演进。接下来的里程碑包括:

审计日志与可观测性的融合

身份系统天然需要审计能力——谁在何时执行了什么操作。Autional 打通了审计日志(audit-service 写入 MongoDB)与结构化日志:每条审计记录都携带 trace_id。你能从一条追踪直接跳到对应的审计记录,确认某个操作是由用户本人发起(而非内部调用)。这是合规审计的杀手级能力(GDPR 第 30 条——处理活动记录)。

错误预算看板

基于 SLO 与错误预算理念,我们正在构建一个集中的「身份系统健康度」看板,把核心指标翻译成业务语言:

  • 登录成功率(最近 1 小时)——实际值与 SLO(99.9%)对比
  • 剩余错误预算(本月)——还剩多少容错空间
  • 令牌签发 P99 延迟——是否影响用户体验?

当错误预算耗尽时,告警级别自动升级,并创建工单,强制团队暂停功能开发、优先保障稳定性——这是 Google SRE 的精髓,也是我们在可观测性之上构建的决策层。

给读者的建议

如果你正在为身份系统构建可观测性,这里有三条按优先级排序的建议:

  1. 从结构化日志开始:把 fmt.Sprintf("user %s login", uid) 换成 slog.Info("user login", "user_id", uid)。这是投入产出比最高的改进——近乎零成本,立竿见影。
  2. 再加分布式追踪:如果你的架构跨越 3 个以上服务,分布式追踪必不可少。先在网关层和核心认证服务注入追踪头,再在消费端提取。Autional 的 micro-pkg 中间件开箱即用。
  3. 最后落地指标:先定义你的 SLO(什么算「可用」),再建看板和告警。没有 SLO 的指标只是图表;有 SLO 的指标才是决策工具。

可观测性不是一套工具——而是一种文化:「我怎样才能更快知道系统出了什么问题?」对身份系统而言,这种文化直接决定你的安全响应速度,并最终决定用户的信任。


27 个 Autional 微服务全部内置 OpenTelemetry 支持,开箱即用。了解如何将 Autional 认证集成到你的应用中,请参阅快速开始指南。

相关阅读

准备好给应用加上身份层了吗?

Autional 提供认证、组织、访问控制、审计与开发者 API —— 面向 AI 生成应用的身份层。