Go 可用 net/http 快速实现带时间戳、uptime、goroutines 数量等真实状态指标的 HTTP 健康检查端点,需避免耗时操作并设置 context 超时以适配 Kubernetes livenessProbe。

如何用 Go 快速启动一个 HTTP 健康检查端点
不需要引入任何第三方库,net/http 就够用。关键不是“写个接口”,而是让这个接口能真实反映服务状态——比如是否能连上数据库、磁盘剩余空间是否低于阈值。
- 别只返回
{"status": "ok"},至少加一个时间戳和基础指标,比如uptime或goroutines数量 - 把健康检查逻辑放在 handler 里,但不要做耗时操作(如远程调用),否则会拖慢探针响应;真要查依赖,用带超时的
context.WithTimeout - Kubernetes 的
livenessProbe默认 1 秒超时,若 handler 执行超过这个时间,会被反复重启——务必测试curl -o /dev/null -s -w "%{http_code}\n" http://localhost:8080/health
package main
import (
"encoding/json"
"net/http"
"runtime"
"time"
)
func healthHandler(w http.ResponseWriter, r *http.Request) {
data := map[string]interface{}{
"status": "ok",
"timestamp": time.Now().UTC().Format(time.RFC3339),
"uptime": time.Since(startTime).String(),
"goroutines": runtime.NumGoroutine(),
"heap_alloc": runtime.ReadMemStats().Alloc,
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(data)
}
var startTime = time.Now()
func main() {
http.HandleFunc("/health", healthHandler)
http.ListenAndServe(":8080", nil)
}
监控指标怎么暴露给 Prometheus
Prometheus 要的是纯文本格式的指标,不是 JSON。用官方客户端库 promclient 是最稳妥的选择,避免自己拼字符串出错或不兼容新版协议。
- 所有自定义指标必须注册到
prometheus.DefaultRegisterer,否则/metrics不会输出 - 计数器(
prometheus.CounterVec)适合记录错误次数,但注意:它只能增不能减,别用来记“当前连接数”这种瞬时值 - 如果服务是多实例部署,别在指标里硬编码 instance 标签;让 Prometheus 通过
relabel_configs注入,避免 Go 程序感知部署细节
为什么 http.ListenAndServe 启动后进程不退出
这不是 bug,是设计行为:ListenAndServe 是阻塞调用。但运维场景下你很可能需要优雅关闭——比如收到 SIGHUP 重载配置,或 SIGTERM 配合 k8s rolling update。
- 直接用
http.Server结构体,配合server.Shutdown(),而不是依赖ListenAndServe - 监听
os.Interrupt和syscall.SIGTERM,但别忽略syscall.SIGINT(Ctrl+C)和syscall.SIGHUP(某些 systemd 场景) -
Shutdown()有默认 30 秒超时,若你的 handler 正在处理长请求,得在 handler 内部检查r.Context().Done()主动退出
日志里看不到 panic?那是因为没捕获
Go HTTP server 默认把 panic 捕获后转成 500 响应,同时打印到标准错误——但如果你用 log.SetOutput(ioutil.Discard) 或重定向到了文件却没刷缓存,就等于“静默崩溃”。
立即学习“go语言免费学习笔记(深入)”;
真正难的不是写一个能返回 200 的 /health,而是让这个端点在 CPU 飙高、磁盘写满、DB 连接池耗尽时,依然能快速给出准确反馈——而这取决于你对每个依赖项的超时控制、对资源使用率的采样频率、以及 panic 发生时有没有保留足够线索。










