在 etcd 服务注册方 KeepAlive 机制中,主要是用一个 channel 接收 keepalive 响应, 其原理如下:
工作原理
- 租约创建:
leaseResp, err := cli.Grant(ctx, s.EtcdTTL) 创建一个带 TTL 的租约,如果不续约会自动过期。 - 开启 KeepAlive:
ch, err := cli.KeepAlive(ctx, leaseResp.ID) KeepAlive 返回一个 channel,etcd 客户端会: 自动定期发送 keepalive 请求到 etcd 服务器, 看v3 代码它用的是grpc 默认间隔 是租约 TTL 的 1/3 每次收到服务器响应后,通过 ch 发送 LeaseKeepAliveResponse - 响应处理:
go func() { for chResp := range ch { s.L.Debug("续约:", logger.String("resp", chResp.String())) } }()
内部机制
- 客户端自动续约:etcd 客户端库在后台启动 goroutine 定期发送续约请求
- 服务器确认:etcd 服务器收到请求后重置租约 TTL,并返回响应
- Channel 通知:客户端收到响应后将 LeaseKeepAliveResponse 发送到 ch
- 异常处理:如果网络断开或服务器异常,channel 会被关闭,for range 循环退出
etcd服务消费者的心跳检测
调用方(服务消费者)与 etcd 的心跳检测使用 Watch 机制:
// 调用方监听服务变化
watchChan := client.Watch(ctx, "service/user-service", clientv3.WithPrefix())
for watchResp := range watchChan {
for _, event := range watchResp.Events {
switch event.Type {
case mvccpb.PUT:
// 服务上线
case mvccpb.DELETE:
// 服务下线(租约过期)
}
}
}