Files
story/docs/observability-and-api-governance.md

6.0 KiB
Raw Permalink Blame History

可观测性与接口治理设计

1. 目标与适用范围

本设计作为 API、Callbacks 与 Worker 三个进程的公共能力基线,统一请求关联、分布式追踪、指标采集、流量保护、列表分页和资源并发更新规则。领域接口不得另行定义不兼容的分页游标或版本标记。

OpenAPI是浏览器、设备和回调接口的事实来源。拉取请求以目标分支契约为基线执行破坏性变更检查;设备接口还由代码测试固定/device/v2主版本、禁止以User-Agent推测能力,并要求兼容说明与OpenAPI版本同步。设备同主版本的新增行为必须通过可选能力位协商,破坏性变化使用新主版本,具体规则见设备API兼容性约定。

2. 请求关联与分布式追踪

  • 每个 HTTP 请求接收或生成 X-Request-Id,并在响应、统一错误体和结构化日志中返回。
  • otelhttp 在最外层创建服务端 Span,接收并传播 W3C traceparent 与 baggage。
  • 访问日志记录 request_id、trace_id、span_id、服务、方法、匹配后的路由模板和耗时;不记录 Authorization、Cookie、录音正文或供应商密钥。
  • 本地环境通过 OTLP/gRPC 发送至 OpenTelemetry Collector。Collector 当前使用调试导出器,后续环境可替换为 Tempo、Jaeger或云厂商后端,不改变业务代码。

3. Prometheus 指标

指标 标签 用途
voice_platform_http_requests_total service、method、route、status 请求量与错误率
voice_platform_http_request_duration_seconds service、method、route HTTP延迟分布
voice_platform_http_inflight_requests service 在途请求数
voice_platform_dependency_up service、dependency PostgreSQL、Redis最近一次检查状态
voice_platform_dependency_check_duration_seconds service、dependency 依赖检查耗时
voice_platform_outbox_events status pending、processing、dead积压

/metrics与/health/*不进入业务限流。Prometheus 每10秒抓取三个进程;本地入口为 http://localhost:59190。生产环境应限制指标端点只允许监控网络访问。

API还会按EXTERNAL_PROBE_INTERVAL周期验证OIDC JWKS端点可读取、JSON结构有效且至少存在一把公钥。启用方舟的API/Worker会对ARK_BASE_URL执行证书校验TLS握手,启用火山RTC的Worker会对VOLC_RTC_BASE_URL执行同类握手,启用托管内容安全的Worker会对CONTENT_SAFETY_ENDPOINT执行同类握手。TLS探针只做DNS、TCP和TLS协商,不发送供应商业务请求或待分类正文,因此不消耗模型Token、RTC分钟、策略调用或任务配额。

探针结果复用voice_platform_dependency_up{service,dependency},其中外部标签为oidc_jwks、ark_tls、volc_rtc_tls和content_safety_tls。失败不会改变服务readiness;模型和内容安全调用本身已有降级或安全重试路径,供应商网络故障不应触发Pod重启风暴。PlatformExternalDependencyUnavailable只在指标连续5分钟为0后触发CRITICAL告警。运营验收快照可把四类依赖全部选为必需项,任何记录缺失、不可用或超过三倍探针周期未更新都会阻断技术门禁。

4. Redis令牌桶限流

  • Key格式:voice-platform:ratelimit:{scope}:{identifier_hash}。
  • 标识符使用SHA-256截断摘要,Redis中不保存原始IP、用户编号、设备编号或客户组织编号。
  • Lua脚本以Redis服务器时间原子完成补充、扣减和过期时间设置,避免多实例竞态及应用服务器时钟偏差。
  • HTTP入口当前先启用 network 范围;应用服务可复用同一组件增加 user、device、tenant 范围并组合更严格策略。
  • 超限返回HTTP 429、错误码 RATE_LIMITED、Retry-After 和 X-RateLimit-Remaining。
  • Redis短时故障采用可观测的 fail-open,避免公共缓存故障放大成全站中断;登录、设备注册、密钥操作等高风险接口落地时应叠加本地保护或按接口改为 fail-closed。

本地默认速率为每来源50次/秒、突发100次,可通过 RATE_LIMIT_RPS 和 RATE_LIMIT_BURST 调整。生产值必须依据容量测试冻结。

5. 游标分页规范

  • 查询参数 limit 缺省为20,只允许1至100。
  • cursor 是HMAC-SHA256签名的不透明Base64URL值,载荷只含版本、稳定排序键和公开资源ID。
  • 服务端按“排序键 + ID”组成确定性顺序,查询下一页时使用严格大于或小于条件,禁止把数据库偏移量作为游标。
  • 响应中的 next_cursor 仅在确有下一页时返回;客户端不得解析、修改或长期持久化游标。
  • 签名失败、版本不支持或字段缺失统一作为无效游标处理,不把解析细节暴露给调用方。

6. ETag与乐观并发规范

  • 可变资源读取成功时返回强ETag,格式为 "v{version}",例如 "v3"。
  • PATCH、PUT和状态变更请求必须携带 If-Match;缺失时映射HTTP 428,格式无效映射HTTP 400,版本不一致映射HTTP 412。
  • 不接受弱ETag W/ 或通配符 *。
  • 数据表须包含从1开始的 version 列;更新SQL必须带 WHERE id=? AND version=?,成功后原子执行 version=version+1。
  • ETag只解决并发覆盖,不替代幂等键。会产生外部副作用的写请求仍须使用幂等执行器和outbox。

7. 验证门禁

  1. 日常开发运行变更包测试、OpenAPI类型生成和前端构建;go test ./...、go vet ./...保留给CI或发布候选。
  2. 游标篡改、非法limit、弱ETag、缺失If-Match和版本冲突必须有自动化测试。
  3. Redis集成测试必须证明突发上限和令牌恢复。
  4. 三个后端 /health/ready 返回200,Prometheus三个target均为 up=1。
  5. Collector日志出现三个服务上报的Span,访问日志出现对应 trace_id 与 span_id。
  6. Worker指标能区分待处理、处理中和死信事件。
  7. OpenAPI破坏性变更检查和设备协议兼容门禁必须通过。