gRPC 官方的健康检查协议怎么用?Check 和 Watch 的行为有什么不同?服务关闭时怎么表示?客户端怎么才会真的避开不健康的后端?这篇逐项验证。
新建的 health.Server,Check(""):RPC 成功,status=SERVING
Check("demo.Demo")(没登记):RPC 失败 code=NotFound message="unknown service"
SetServingStatus(demo.Demo, NOT_SERVING) 之后 Check:RPC 成功,status=NOT_SERVING
SetServingStatus(demo.Demo, SERVING) 之后 Check:RPC 成功,status=SERVING
List:err=<nil>;"":SERVING "demo.Demo":SERVINGgrpc.health.v1.Health 有 Check(一次性)、Watch(流式推送状态变化)、List。服务名为空字符串表示整个服务器的整体状态。health.Server 是官方实现,用 SetServingStatus 修改状态。
Watch("svc") 刚开始(没登记):收到 [SERVICE_UNKNOWN]
SetServingStatus(SERVING):收到 [SERVING]
再连续设置 2 次 SERVING:收到 []
设为 NOT_SERVING:收到 [NOT_SERVING]
从 SetServingStatus 到客户端收到的延迟:0.2 ms
紧接着快速交替设置 1000 次(最后一次是 SERVING):客户端收到 14 条,最后一条 SERVING没登记的服务先返回 SERVICE_UNKNOWN;状态没变化不重复发;变化太快时中间状态会被合并,保证最后收到的是最新状态。
初始:"" → SERVING;svc → SERVING Shutdown 之后:"" → NOT_SERVING;svc → NOT_SERVING Shutdown 之后再 SetServingStatus(svc, SERVING):svc → NOT_SERVING(被忽略) Resume 之后:"" → SERVING;svc → SERVING
Shutdown() 把所有服务设为 NOT_SERVING 并忽略之后的修改,Resume() 恢复。适合在停机前先让上游摘除自己。
无 healthCheckConfig:全部 SERVING,60 次调用各后端收到 [20 20 20] 无 healthCheckConfig:后端 1 设为 NOT_SERVING 后 1.5 秒内,最后一次打到后端 1 是在设置之后 1491.5 ms;之后 60 次调用各后端收到 [20 20 20] 有 healthCheckConfig:全部 SERVING,60 次调用各后端收到 [20 20 20] 有 healthCheckConfig:后端 1 设为 NOT_SERVING 后 1.5 秒内,最后一次打到后端 1 是在设置之后 0.1 ms;之后 60 次调用各后端收到 [30 0 30] 有 healthCheckConfig:3 个后端全部 NOT_SERVING 后的调用:code=Unavailable message="pickfirst: health check failure: connection active but health check failed. status=NOT_SERVING" 后端 2 恢复 SERVING 后的调用:<nil>
客户端只有在服务配置里设置了 healthCheckConfig,才会对每个连接发起 Watch,并避开 NOT_SERVING 的后端。没有这个配置,健康状态不影响负载均衡。