健康检查与内置路由

健康检查与内置路由

go-web 内置了两条健康检查路由,便于在 Kubernetes、Docker、负载均衡等场景中接入存活探针 / 就绪探针。

健康检查路由由 app/controller/health_controller.go 提供,需要在 config/autoload/router.go 中显式注册才会生效。框架不强制挂载,默认模板已经包含。

路由列表

路径 用途 检查项
GET /health 完整健康检查 数据库 + Redis
GET /health/simple 简单存活探针 仅返回 UP / 时间戳

GET /health —— 完整健康检查

依次检查:

  1. 数据库 —— helper.GetDatabase()gormDB.DB().Ping()
  2. Redis —— helper.GetRedis()client.Ping(ctx)

任何一项失败都会让整体状态变为 DOWN,并返回 HTTP 503。

成功响应:

{
  "code": 0,
  "message": "操作成功",
  "data": {
    "status": "UP",
    "timestamp": 1703123456,
    "services": {
      "database": { "status": "UP" },
      "redis":    { "status": "UP" }
    }
  }
}

失败响应(HTTP 503):

{
  "code": 503,
  "message": "服务不健康"
}

源码位置:app/controller/health_controller.go:18 GetHealth

GET /health/simple —— 简单存活探针

不检查依赖,仅返回当前进程是否还能响应请求,适合 Kubernetes liveness probe(存活探针) 使用,避免因为 Redis 短暂抖动而被 kill。

{
  "code": 0,
  "message": "操作成功",
  "data": {
    "status": "UP",
    "timestamp": 1703123456
  }
}

源码位置:app/controller/health_controller.go:44 GetHealthSimple

在 Kubernetes 中使用

推荐组合:

livenessProbe:
  httpGet:
    path: /health/simple
    port: 8080
  initialDelaySeconds: 5
  periodSeconds: 10

readinessProbe:
  httpGet:
    path: /health
    port: 8080
  initialDelaySeconds: 5
  periodSeconds: 10
  failureThreshold: 3
  • liveness/health/simple —— 防止误杀
  • readiness/health —— 数据库或 Redis 不通时把 Pod 摘下流量

Docker HEALTHCHECK

默认 Dockerfile 已经配置了健康检查:

HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
    CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health/simple || exit 1

自定义检查项

你可以为 HealthController 增加新的检查方法,例如检查 RabbitMQ、ElasticSearch、外部 HTTP 服务等。在 health_controller.go 中追加:

func (receiver HealthController) checkRabbit() dto.ServiceStatus {
    client := helper.GetRabbit() // 假设你封装了 helper
    if err := client.Ping(); err != nil {
        return dto.ServiceStatus{
            Status:  "DOWN",
            Message: "rabbit ping 失败: " + err.Error(),
        }
    }
    return dto.ServiceStatus{Status: "UP"}
}

然后在 GetHealth 中:

healthStatus.Services["rabbit"] = receiver.checkRabbit()
if healthStatus.Services["rabbit"].(dto.ServiceStatus).Status == "DOWN" {
    healthStatus.Status = "DOWN"
}

注册路由

确保在 config/autoload/router.go 中注册了健康检查路由,否则 /health 请求会返回 404:

router.GET("/health", controller.HealthController{}.GetHealth)
router.GET("/health/simple", controller.HealthController{}.GetHealthSimple)

也可以通过分组挂载:

health := router.Group("/health")
{
    health.GET("", controller.HealthController{}.GetHealth)
    health.GET("/simple", controller.HealthController{}.GetHealthSimple)
}