readinessprobe 必须验证关键依赖而非仅返回200,/readyz需调用db.pingcontext、redis.ping及下游健康检查;maxunavailable应设为0,terminationgraceperiodseconds≥shutdown超时;go shutdown须先srv.shutdown再关闭依赖,最后os.exit。

readinessProbe 必须检查真实就绪状态,不能只 ping 端口
很多 Golang 服务的 readinessProbe 配置成 httpGet: path: /healthz,但这个端点只返回 200,不查 DB、Redis 或下游 gRPC 是否连通。结果 Pod 进入 Running 状态后立刻被加进 Endpoints,流量进来却 502/503。
正确做法是让 /readyz 显式验证关键依赖:
- 调用
db.PingContext(ctx),超时设为 5 秒以上 - 检查 Redis 连接池是否 ready(如
redis.Client.Ping()) - 对关键下游服务发轻量健康请求(带 context timeout)
-
initialDelaySeconds至少设 10 秒,给 Go runtime、DB 连接池、配置加载留出冷启动时间
滚动更新必须配 maxUnavailable: 0 和 terminationGracePeriodSeconds ≥ Shutdown 超时
默认 maxUnavailable: 25% 在 replicas=3 时允许 1 个 Pod 同时不可用——新 Pod 尚未 Ready,旧 Pod 已被删,Service 后端瞬间为空,Nginx/Traefik 就会报 503。
安全策略是显式写死:
-
maxUnavailable: 0:确保旧 Pod 一个不删,直到所有新 Pod Ready -
terminationGracePeriodSeconds: 60:必须 ≥ Go 中http.Server.Shutdown()的 context timeout(比如你设了 30 秒,这里至少填 45) - 别信“默认 30 秒够用”——高负载下连接 draining 可能卡在 write buffer 或 TLS handshake 阶段
Golang 代码里 shutdown 顺序不能错:先 Shutdown Server,再关依赖
常见错误是收到 SIGTERM 后直接 os.Exit(0),或 server.Close() 暴力中断连接;更隐蔽的错法是 shutdown 完 HTTP server 就 exit,没等 DB 连接池 close 完。
标准流程只有这一种顺序有效:
- 用
signal.Notify(c, syscall.SIGTERM)捕获信号 - 调用
srv.Shutdown(),传入context.WithTimeout(context.Background(), 30*time.Second) -
Shutdown()返回后,再依次调用db.Close()、redis.Close()、取消长轮询ctx.Cancel() - 最后才
os.Exit(0);别在 handler 里启 goroutine 后立刻返回——Shutdown()不等它们
Service selector 切换不是原子的,得靠 readinessProbe + Endpoint 更新节奏兜底
Kubernetes 的 Service 切换 selector(比如把 version: v1 改成 version: v2)看似原子,但实际生效有延迟:
-
kube-proxy监听EndpointSlice变化,iptables/ipvs 规则刷新有几百毫秒滞后 - 已有 TCP 长连接仍打向旧 Pod,HTTP/2 多路复用下更明显
- 所以不能依赖 “改完 selector 就立刻切流”,而要靠新 Pod 的
readinessProbe通过后,Endpoint 才真正更新,反代才会把新连接导过去 - 如果发现切换后仍有少量 5xx,先看
kubectl get endpointslice -o wide,确认新 Pod IP 是否已出现在address列
Shutdown() 的 timeout 形成闭环。这点最容易被忽略——很多人测通了单 Pod 优雅关闭,却没压测过滚动更新期间的 Endpoint 更新窗口期。golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











