可观测性与运维
单 VM / Docker Compose 阶段的日志、指标、告警和排障手册
目标
MVP 阶段不建设复杂链路追踪和集群级平台。可观测性的目标是用低运维成本回答四个问题:
- 用户能不能下单?
- 支付回调有没有成功?
- 库存和订单状态有没有卡住?
- worker 有没有堆积或失败?
组件选择
| 能力 | MVP 方案 | 说明 |
|---|---|---|
| 应用日志 | Go JSON 日志 + docker compose logs | 每条日志带 trace_id |
| 指标 | Prometheus scrape /metrics | API、业务、worker 指标 |
| 看板 | Grafana | 接 Prometheus |
| 告警 | Prometheus Alertmanager 或云监控 webhook | P0/P1 告警到微信群/短信 |
| 追踪 | 暂不部署独立 tracing | 先用 trace_id 串联日志和业务表 |
| 健康检查 | /healthz、/readyz | Docker Compose 和发布脚本使用 |
日志规范
日志必须是 JSON,字段稳定,禁止输出敏感信息。
json
{
"level": "info",
"ts": "2026-05-22T10:00:00+08:00",
"trace_id": "01J...",
"process": "api-server",
"module": "order",
"event": "order_created",
"order_no": "DW202605220001",
"latency_ms": 42
}| 字段 | 要求 |
|---|---|
trace_id | HTTP 请求入口生成,worker 事件继承或新建 |
process | api-server / admin-api / worker |
module | auth/user/catalog/inventory/order/payment/coupon/delivery/asset/shared |
event | 稳定事件名,便于检索 |
order_no / payment_no | 有则必打 |
error | 错误摘要,不含敏感原文 |
禁止日志:手机号明文、详细地址、openid、支付回调完整密文、JWT、密钥。
指标体系
HTTP 指标
text
http_requests_total{process,method,path,status}
http_request_duration_seconds_bucket{process,method,path}
http_request_in_flight{process}
http_request_body_bytes{process,path}目标:
| 指标 | 目标 |
|---|---|
| API P95 | < 500ms |
| API 错误率 | < 1% |
| 登录/下单/支付接口错误率 | 单独看板 |
业务指标
text
orders_created_total{status}
orders_paid_total
orders_cancelled_total{reason}
orders_completed_total
payments_created_total
payments_paid_total
payment_notify_total{result}
refunds_total{status}
inventory_lock_total{result}
inventory_confirm_total{result}
inventory_release_total{result}
delivery_tasks_total{status}核心关注:订单创建、支付成功、库存锁定失败、退款失败、配送超时。
Worker 指标
text
outbox_pending_count
outbox_processing_count
outbox_failed_count
outbox_processed_total{event_type}
outbox_retry_total{event_type}
outbox_handler_duration_seconds_bucket{event_type}
worker_loop_errors_total目标:outbox_pending_count 长时间增长必须告警。
依赖指标
text
db_open_connections
db_in_use_connections
db_wait_count_total
valkey_ops_total{cmd,result}
valkey_errors_total
cos_upload_total{result}
wechat_api_total{api,result}
wechat_api_duration_seconds_bucket{api}健康检查
| 接口 | 语义 |
|---|---|
GET /healthz | 进程存活,不检查依赖 |
GET /readyz | DB、Valkey 可访问,关键配置存在 |
GET /metrics | Prometheus 指标 |
worker 没有 HTTP 端口时,可以用日志心跳和 outbox 指标判断状态;如果需要,也可以给 worker 开一个仅内网访问的管理端口。
Grafana 看板
经营/交易看板
| 面板 | 指标 |
|---|---|
| 今日订单数 | increase(orders_created_total[1d]) |
| 今日支付成功数 | increase(orders_paid_total[1d]) |
| 支付成功率 | paid / created |
| 退款数 | increase(refunds_total[1d]) |
| 配送完成数 | increase(delivery_tasks_total{status="delivered"}[1d]) |
技术看板
| 面板 | 指标 |
|---|---|
| API QPS | rate(http_requests_total[5m]) |
| API 错误率 | 5xx / total |
| API P95/P99 | histogram_quantile |
| DB 连接池 | open / in_use / wait |
| Valkey 错误 | rate(valkey_errors_total[5m]) |
Worker 看板
| 面板 | 指标 |
|---|---|
| pending 事件数 | outbox_pending_count |
| failed 事件数 | outbox_failed_count |
| 事件处理速率 | rate(outbox_processed_total[5m]) |
| 重试速率 | rate(outbox_retry_total[5m]) |
| 慢事件 | handler duration P95 |
告警规则
P0:立即处理
| 告警 | 条件 | 处理 |
|---|---|---|
| 订单创建错误率过高 | 5xx > 5% 持续 5 分钟 | 暂停发布,检查 api-server、DB、库存模块 |
| 支付回调失败 | payment_notify_total{result="failed"} 连续增长 | 检查验签、证书、微信平台、回调原文 |
| DB 连接池耗尽 | in_use 接近 max 持续 5 分钟 | 检查慢 SQL、连接泄漏、重启风险 |
| worker failed 激增 | failed > 10 或持续增长 | 停止相关事件消费,查看 last_error |
P1:工作时间优先处理
| 告警 | 条件 | 处理 |
|---|---|---|
| API P95 过高 | P95 > 1s 持续 10 分钟 | 查慢接口、DB、外部依赖 |
| outbox 堆积 | pending > 100 持续 15 分钟 | 查 worker、DB 锁、外部 API |
| 库存锁定失败升高 | failure rate > 20% | 查库存水位、并发冲突、商品配置 |
| Valkey 不可用 | errors 持续增长 | 降级 DB 查询,恢复 Valkey |
P2:复盘优化
| 告警 | 条件 |
|---|---|
| 配送超时升高 | 超时订单 > 5% |
| 退款失败 | refund_failed > 0 |
| 慢 SQL | 单次查询 > 500ms |
| COS 上传失败 | 失败率 > 5% |
排障流程
支付成功但订单未更新
- 查
payment_notifications是否收到微信通知。 - 查
payments是否进入paid。 - 查
orders当前状态。 - 查
outbox_events是否有payment.paidfailed/pending。 - 查 worker 日志中的
order_no和trace_id。 - 必要时调用 payment 查单接口,对账后手动补偿。
库存不一致
- 查
inventory当前total_qty和reserved_qty。 - 查
inventory_locks是否有未释放 active lock。 - 查
inventory_movements按时间排序复盘。 - 查
audit_logs是否有人工作业。 - 如果需要修复,走后台库存调整,并写 reason。
订单超时未取消
- 查
outbox_events是否存在order.timeout。 - 查该事件
scheduled_at、status、retry_count、error_msg。 - 查 worker 是否运行。
- 手动触发
ProcessTimeout前先查订单是否已支付。
运维日报
markdown
# 运维日报 YYYY-MM-DD
## 核心数据
- 订单创建:
- 支付成功:
- 支付成功率:
- 退款数:
- 配送完成:
## 技术指标
- API P95:
- API 5xx:
- outbox pending:
- outbox failed:
- DB 连接池峰值:
## 异常
- 支付异常:
- 库存异常:
- 配送异常:
- 用户投诉关联订单:
## 动作
- 已处理:
- 待跟进: