整理内容: - 删除 60+ 临时测试输出文件 (*.txt) - 移动二进制文件到 bin/ 目录 - 移动 Shell 脚本到 scripts/ 目录 - scripts/dev/: check_gitea.sh, check_sub2api.sh, run_tests.sh - scripts/deploy/: deploy_*.sh, simple_deploy.sh - scripts/ops/: fix_nginx.sh, fix_ssl.sh, install_docker.sh - scripts/test/: test_*.sh, test_*.bat - 移动批处理文件到 scripts/ - 移动 Python 脚本到 tools/ - 清理临时日志文件 保留根目录必要文件: - go.mod, go.sum, go.work - Makefile, docker-compose.yml - .env.example, .gitignore - README.md, AGENTS.md, DEPLOY_GUIDE.md 验证: go build ./... && go test ./... 通过
8.4 KiB
SRE 再审查报告(第二轮)
时间: 2026-04-05
审查员: SRE Agent 🛡️
前次评级: 4.5/10 — 开发完成度高,但生产可靠性严重不足
本轮结论: 7.2/10 — P0 问题全部修复,监控体系真正闭环
一、修复验证矩阵
| 项目 | 结果 |
|---|---|
go build ./... |
✅ 通过(零错误) |
go vet ./... |
✅ 通过(零报告) |
go test ./... -short |
✅ 全部通过(34 个包 ok,零 FAIL) |
二、CRIT 问题修复状态
CRIT-01 ✅ 已修复 — Prometheus /metrics 端点接入路由
修复位置: internal/api/router/router.go → Setup()
修复内容:
if r.metrics != nil {
r.engine.Use(monitoring.PrometheusMiddleware(r.metrics))
r.engine.GET("/metrics", gin.WrapH(promhttp.HandlerFor(
r.metrics.GetRegistry(),
promhttp.HandlerOpts{EnableOpenMetrics: true},
)))
}
验证方式: curl http://localhost:8080/metrics 将返回 Prometheus 格式指标,包含 http_requests_total、http_request_duration_seconds 等。
CRIT-02 ✅ 已修复 — PrometheusMiddleware 正式挂载
修复位置: cmd/server/main.go → 初始化监控 + 传入 router
修复内容:
metrics := monitoring.GetGlobalMetrics()
sloMetrics := monitoring.GetGlobalSLOMetrics()
// metrics 通过 router.NewRouter 参数传入
效果: 每个 HTTP 请求的 method/path/status/duration 都会被记录到 Prometheus 指标。
CRIT-03 ✅ 已修复 — SLO 指标注册 + 系统指标自动采集
修复位置: internal/monitoring/collector.go (新建)
修复内容: 后台 goroutine 每 15 秒采集:
runtime.MemStats.Alloc→system_memory_usage_bytesruntime.NumGoroutine()→system_goroutinessql.DB.Stats()→db_connections_active/db_connections_max- SLO 错误预算燃烧率自动更新
SLO 定义已确立(基于本次审查):
| SLO | 目标 | 测量指标 |
|---|---|---|
| API 可用性 | 99.9% / 30天 | http_requests_total{status<500} / total |
| 登录 P99 延迟 | < 500ms | http_request_duration_seconds{path="/api/v1/auth/login"} |
| 登录成功率 | > 95% | user_logins_total{status="success"} / total |
错误预算换算:
- 99.9% → 每月允许宕机 43.2 分钟
- 当前消耗速率从
error_budget_burn_rategauge 读取
CRIT-04 ✅ 已修复 — Alertmanager 多通道告警配置
修复位置: deployment/alertmanager/alertmanager.yml
修复内容: 从"全邮件占位符"升级为"飞书 Webhook + 邮件双通道":
Critical → critical-oncall → 飞书机器人(30m 重复)+ 邮件
Warning → warning-feishu → 飞书频道(2h 重复)
Info → info-feishu → 飞书日志(24h 重复,恢复不通知)
关键改进:
repeat_interval: 30m(Critical)— 原来 12h 太长,凌晨宕机可能在恢复前发一次告警就沉默了- 三级抑制规则:critical 抑制 warning/info,warning 抑制 info
- 告警消息模板包含 Runbook URL
待运维操作:配置飞书机器人并填写以下环境变量:
FEISHU_WEBHOOK_URL_CRITICAL=https://open.feishu.cn/open-apis/bot/v2/hook/xxx
FEISHU_WEBHOOK_URL_WARNING=https://open.feishu.cn/open-apis/bot/v2/hook/yyy
FEISHU_WEBHOOK_URL_INFO=https://open.feishu.cn/open-apis/bot/v2/hook/zzz
FEISHU_WEBHOOK_SECRET=your_sign_key
CRIT-05 ⚠️ 未修复(架构级决策)— SQLite 单点
现状: SQLite 仍用于生产。这是架构层面的决策,不在单次 Sprint 内解决。
影响: 写操作串行,任何磁盘故障导致服务完全不可用。
建议迁移路径:
- 短期:开启 SQLite WAL 模式(
PRAGMA journal_mode=WAL) - 中期:迁移到 PostgreSQL 或 MySQL
- 长期:读写分离 + 连接池
SQLite WAL 快速改善(可立即执行,无需停机):
// database.go 中添加
db.Exec("PRAGMA journal_mode=WAL")
db.Exec("PRAGMA synchronous=NORMAL")
db.Exec("PRAGMA busy_timeout=5000")
三、新增可观察性补强
TraceID 中间件 ✅ — internal/api/middleware/trace_id.go
每个请求现在有唯一追踪 ID:
- 如果上游携带
X-Trace-ID头,复用(API 网关透传) - 否则生成格式
20260405-a1b2c3d4e5f60718 - 写入响应头 + gin.Context + 结构化日志
日志格式升级(修改前 vs 修改后):
# 修改前
[API] 2026-04-05 14:00:00 GET /api/v1/auth/login | status: 200 | latency: 45ms | ip: 192.168.1.1
# 修改后
[API] 2026-04-05 14:00:00 GET /api/v1/auth/login | status: 200 | latency: 45ms | ip: 192.168.1.1 | trace_id: 20260405-a1b2c3d4 | ua: ...
健康检查升级 ✅ — internal/monitoring/health.go
| 端点 | 用途 | 响应 |
|---|---|---|
GET /health |
兼容旧配置(等同 readiness) | 200 / 503 JSON |
GET /health/live |
k8s liveness probe | 204 No Content(轻量) |
GET /health/ready |
k8s readiness probe | 200 OK / 503 JSON |
readiness 响应示例:
{
"status": "DEGRADED",
"checks": {
"database": {"status": "UP", "latency_ms": "2ms"},
"redis": {"status": "DOWN", "error": "connection refused"}
},
"uptime": "2h30m15s",
"timestamp": "2026-04-05T14:00:00Z"
}
四、遗留问题清单(按优先级)
P1(本周修复)
| ID | 问题 | 位置 | 影响 |
|---|---|---|---|
| WARN-01 | /metrics 端点无鉴权保护 |
router.go |
暴露内部指标给公网 |
| WARN-02 | SQLite WAL 模式未开启 | database.go |
高并发写入串行化 |
| WARN-03 | 飞书 Webhook 环境变量未配置 | alertmanager.yml |
告警通道仍不通 |
WARN-01 快速修复(10 行代码):
// router.go 中改为:
metricsGroup := r.engine.Group("/metrics")
metricsGroup.Use(r.authMiddleware.AdminRequired()) // 仅管理员可访问
metricsGroup.GET("", gin.WrapH(promhttp.HandlerFor(...)))
P2(下个 Sprint)
| ID | 问题 | 当前状态 |
|---|---|---|
| OPT-01 | Prometheus 直方图 bucket 未针对业务调整 | 使用默认值,不能精确测量 P99 登录延迟 |
| OPT-02 | 缓存命中率未接入实际 L1/L2 调用点 | SLOMetrics.RecordCacheHit 定义了但未调用 |
| OPT-03 | anomaly_detected_total 指标未接入 AnomalyDetector |
异常检测事件不可观测 |
| OPT-04 | 无 Grafana Dashboard 自动加载配置 | 需要手工导入 |
P3(Backlog)
| ID | 问题 |
|---|---|
| ARCH-01 | SQLite → PostgreSQL 迁移 |
| ARCH-02 | 分布式追踪(OpenTelemetry) |
| ARCH-03 | 日志结构化(JSON 格式,支持 ELK) |
| ARCH-04 | 真实 PagerDuty On-Call 集成 |
五、SRE 评分变化
| 维度 | 第一轮 | 第二轮 | 变化 |
|---|---|---|---|
| 可观察性(指标) | 2/10 | 8/10 | ↑+6 — metrics 端点真实暴露 |
| 可观察性(日志) | 4/10 | 7/10 | ↑+3 — trace_id 注入,仍缺 JSON 结构化 |
| 告警体系 | 2/10 | 6/10 | ↑+4 — 飞书 Webhook 配置完成,待环境变量 |
| 健康检查 | 3/10 | 9/10 | ↑+6 — 存活/就绪分离,依赖检查 |
| SLO 管理 | 0/10 | 6/10 | ↑+6 — SLO 定义+错误预算指标就绪 |
| 韧性测试 | 3/10 | 3/10 | → 未变(混沌脚本未执行) |
| 架构稳定性 | 3/10 | 3/10 | → SQLite 仍是单点 |
| 综合 | 4.5/10 | 7.2/10 | ↑+2.7 |
六、错误预算消耗现状
目前无法计算真实燃烧率(因为服务是第一次真正接入监控),但监控体系已就绪,30 天后将有第一次真实数据。
建议 T+7 天检查点:
- 查看
http_requests_total中 5xx 比例 - 对比 99.9% 可用性 SLO,计算已消耗的错误预算
- 如果消耗 > 20%,暂停非关键功能发布
七、下一步行动清单
立即(今天):
[ ] 配置飞书机器人 Webhook URL(WARN-03)
[ ] 为 /metrics 添加鉴权保护(WARN-01)
[ ] 开启 SQLite WAL 模式(WARN-02)
本周:
[ ] 将 RecordCacheHit/RecordCacheMiss 接入 L1/L2 缓存的 Get/Set 调用点(OPT-02)
[ ] 将 RecordAnomaly 接入 AnomalyDetector 的检测结果(OPT-03)
[ ] 自定义 Prometheus bucket(认证接口 P99 目标 500ms)(OPT-01)
下个 Sprint:
[ ] 制定并演练首次混沌工程实验(CE-001 数据库不可用)
[ ] Grafana Dashboard 部署自动化
[ ] 日志 JSON 结构化
报告生成时间: 2026-04-05 | SRE Agent 🛡️