5.3 KiB
5.3 KiB
tags, aliases, date created, date modified
| tags | aliases | date created | date modified | |
|---|---|---|---|---|
|
星期三, 十二月 10日 2025, 12:10:32 中午 | 星期三, 十二月 10日 2025, 12:12:02 中午 |
🛡️ 基础设施模块:错误处理与响应系统 (Infra: Error Handling & Response)
1. 模块概述
本模块实现了 Modular Clean Architecture 中的基础设施层 (Level 0 & Level 1),提供了一套统一的、安全的、可观测的 HTTP 响应机制。
核心能力:
- 统一契约: 所有 API 响应(成功、失败、Panic、404)严格遵循
{code, msg, data, trace_id}结构。 - 安全降级: 自动识别业务错误与系统错误。对系统级错误(如 SQL 失败)进行“掩码”处理,防止敏感信息泄露。
- 可观测性: 集成 Prometheus 埋点,通过
X-Biz-Code实现业务级监控;全链路 TraceID 自动注入。 - 开发体验: 提供
Responder接口与工厂模式,支持 Handler 层的依赖注入与 Mock 测试。
2. 文件清单 (File Manifest)
以下代码位于项目根目录 gitea-aliyun/Klein/enterprise-cms-core/ 下:
Level 0: 基础领域层 (internal/pkg/ecode)
依赖: 零依赖 (仅标准库)
| 文件名 | 类型 | 核心职责 |
|---|---|---|
code.go |
Const | 错误码注册表。定义 1xxxx (系统) 和 2xxxx (业务) 常量。 |
msg.go |
Data | 文案映射。维护全局 map[int]string,提供并发安全的 GetMsg。 |
error.go |
Struct | 错误实体。实现 error 接口,支持 WithMsg/WithDetails 扩展。 |
ecode_test.go |
Test | 验证并发安全性及不可变性。 |
Level 1: 应用工具层 (internal/pkg/app)
依赖:
gin,ecode
| 文件名 | 类型 | 核心职责 |
|---|---|---|
responder.go |
Interface | 接口定义。定义 Responder 接口与 Factory 函数类型,用于解耦。 |
response.go |
Impl | 核心实现。封装 Gin Context,实现 JSON 序列化、错误清洗、监控埋点。 |
options.go |
Pattern | 功能选项。提供 WithTraceID 等扩展配置。 |
response_test.go |
Test | 验证 JSON 契约、空指针防御及错误降级逻辑。 |
Global: 全局中间件 (internal/middleware)
依赖:
gin,pkg/app,pkg/ecode,prometheus
| 文件名 | 类型 | 核心职责 |
|---|---|---|
recovery.go |
Safety | Panic 兜底。捕获 Panic 并转换为标准 JSON 500 响应。 |
not_found.go |
Route | 404 兜底。将无路由请求转换为标准 JSON 404 响应。 |
metrics.go |
Monitor | 业务监控。采集 http_requests_total 指标,包含 biz_code 标签。 |
3. 快速上手 (Quick Start)
3.1 定义新错误
在 internal/pkg/ecode/code.go 添加常量,并在 msg.go 添加文案。
// code.go
const UserBalanceInsufficient = 20005
// msg.go
msg = map[int]string{
// ...
UserBalanceInsufficient: "User Balance Insufficient",
}
3.2 在 Handler 中使用 (推荐写法)
使用依赖注入的 app.Factory 创建响应器,而非直接调用 app.New。
import (
"github.com/gin-gonic/gin"
"gitea-aliyun/Klein/enterprise-cms-core/internal/pkg/app"
"gitea-aliyun/Klein/enterprise-cms-core/internal/pkg/ecode"
)
type UserHandler struct {
// 注入 Responder 工厂,便于测试 Mock
RespFactory app.Factory
}
func (h *UserHandler) Create(c *gin.Context) {
// 1. 创建响应器
resp := h.RespFactory(c)
// 2. 模拟业务逻辑
if err := h.Service.Create(); err != nil {
// 自动处理错误:如果是业务错误直接返回;如果是系统错误则降级并记录日志
resp.Error(err)
return
}
// 3. 成功响应
resp.Success(gin.H{"status": "created"})
}
3.3 系统接入 (Main.go)
在 HTTP Server 启动时注册全局中间件。
r := gin.New()
// 1. Recovery (必须最先注册)
r.Use(middleware.Recovery())
// 2. Metrics (监控业务码)
r.Use(middleware.BusinessMetrics())
// ... 注册业务路由 ...
// 3. 404 处理 (最后注册)
r.NoRoute(middleware.NotFound())
4. 设计决策说明 (Architecture Decisions)
A. HTTP 200 Always 策略
- 规则: 除非网络层崩溃,所有接口(包括业务错误和系统错误)均返回
HTTP 200 OK。 - 原因: 防止网关(Nginx/ALB)拦截非 200 响应并替换 Body,确保前端始终能解析 JSON 中的
code。
B. 安全掩码 (Security Masking)
- 输入:
db.Query失败返回sql: connection refused。 - 输出: 前端收到
{ "code": 10000, "msg": "Internal Server Error" }。 - 日志: 服务端 Error Log 记录原始堆栈。
- 目的: 杜绝数据库结构、IP 等敏感信息通过报错接口泄露。
C. 监控指标 (Metrics)
- 指标名:
http_requests_total - 关键标签:
biz_code(业务状态码)。 - SRE 告警: 请针对
biz_code >= 10000(系统错误) 配置告警,而非 HTTP Status Code。
5. 测试指南
本模块已包含完整的单元测试与竞态检测 (Race Detection)。
# 运行所有测试
go test -v -race ./internal/pkg/...