健康检查端点应返回http 200表示健康、503表示暂时不可用;/readyz需返回200才允许流量,/healthz返回503会触发重启;避免耗时操作与业务逻辑耦合,独立handler并缓存结果。

健康检查端点该返回什么状态码
微服务健康检查不是“能访问就行”,而是要让调用方(如 Kubernetes、Consul 或网关)准确区分“启动中”“就绪但未完全可用”“已崩溃”。HTTP 200 是唯一被广泛识别的“健康”信号,HTTP 503 表示“暂时不可用”(例如依赖 DB 连接失败但可能恢复),HTTP 404 或超时则代表服务未暴露端点或进程已退出。
常见错误是返回 200 却塞进 {"status":"degraded"} —— 多数探针只看状态码,JSON 内容被忽略。Kubernetes 的 livenessProbe 和 readinessProbe 默认不解析响应体。
- 就绪检查(
/readyz)必须返回200才允许流量进入,否则返回503 - 存活检查(
/healthz)返回503会触发容器重启,返回200表示进程仍在运行 - 避免在健康端点里做耗时操作(如查 Redis、发 HTTP 请求),否则探针超时导致误判
Go 中用 http.ServeMux 实现轻量探测端点
不用引入完整框架(如 Gin、Echo),原生 net/http 就够用。关键在于把健康逻辑和业务路由解耦,避免因主路由 panic 导致健康端点失效。
推荐为健康检查单独注册一个 http.ServeMux,或至少用独立 handler 函数,确保它不依赖任何中间件(如 auth、logging)。
- 定义两个 handler:
healthzHandler只检查 goroutine 是否卡死、内存是否爆表;readyzHandler额外检查数据库连接池db.Ping()和下游 gRPC 连接conn.GetState() == connectivity.Ready - 不要在 handler 里用
log.Fatal,会导致整个服务退出;改用log.Printf记录异常,但依然返回503 - 加个简单缓存:对
/readyz做 1 秒级本地缓存(用sync.Map存上次检查时间与结果),避免每秒几十次探针压垮 DB
func readyzHandler(w http.ResponseWriter, r *http.Request) {
if cached, ok := readyCache.Load(r.URL.Path); ok && time.Since(cached.(time.Time))
<h3>如何让 gRPC 服务也支持 HTTP 健康探测</h3>
<p>gRPC 服务默认不暴露 HTTP 端口,但 K8s 的 liveness/readiness 探针只认 HTTP。不能强行让 gRPC server 同时处理 HTTP,而应启动一个独立的 <code>http.Server</code>,复用同一进程的健康逻辑。</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill6256" title="Kubernetes Network Policy Generator"><img
src="https://img.php.cn/upload/skill/000/000/081/179085258135896.jpg" alt="Kubernetes Network Policy Generator" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill6256" title="Kubernetes Network Policy Generator" class="overflowclass">Kubernetes Network Policy Generator</a>
<p class="overflowclass">使用加权评分卡在12项标准上评估和比较隐私解决方案供应商。适用于选择隐私管理软件、比较数据保护方案等场景。</p>
</div>
<a rel="nofollow" href="/xiazai/skill6256" title="Kubernetes Network Policy Generator" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
<p>重点在于共享状态:DB 连接、gRPC 客户端连接池、自定义指标等,不能每个 HTTP handler 都重新初始化。</p>
- 把健康检查逻辑抽成结构体方法,比如
checker.IsReady() error,在 HTTP handler 和 gRPC server 启动后都调用它 - 如果用了
grpc-go/health的health.Checker,注意它默认只返回SERVING/NOT_SERVING,不对应 HTTP 状态码;需额外写一层适配器 - 避免在 gRPC 服务里监听
:8080和:9000两个端口——端口冲突难排查;统一用 flag 控制是否启用 HTTP 探针端口
Probe 超时与重试配置怎么配才不翻车
Kubernetes 的 initialDelaySeconds、timeoutSeconds 和 periodSeconds 不是随便填的数字,它们直接决定服务是否被误杀。
Go 程序冷启动慢(尤其带大量 init 逻辑或 TLS 握手),如果 initialDelaySeconds 设太小,探针在 main 函数还没跑完就开查,必然失败并反复重启。
- 实测建议:
initialDelaySeconds: 10(覆盖 Go module 初始化 + DB 连接池 warmup),timeoutSeconds: 2(健康端点必须 2 秒内返回),periodSeconds: 5(每 5 秒探一次) - Go HTTP server 的
ReadTimeout必须 >timeoutSeconds,否则探针还没发完请求,server 就先 close connection,返回http.ErrServerClosed - 本地开发用
curl -v http://localhost:8080/readyz验证,别只看 status code,用-w "%{http_code}\n"提取状态码,排除浏览器缓存干扰
最常被忽略的是 probe 的 failureThreshold:设成 1 意味着单次超时就重启,而网络抖动很常见;生产环境建议设为 3–5,配合足够长的 initialDelay 才稳。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










