etcd客户端初始化必须加grpc.WithBlock()和DialTimeout≥5s,否则New()可能返回nil或卡死;选主需用concurrency.NewSession创建带TTL的session并持续KeepAlive,Observe需select监听响应。

etcd客户端初始化必须加 grpc.WithBlock() 和 DialTimeout
不加这两个配置,clientv3.New() 可能返回 nil 或卡死在 goroutine 里,后续所有 Put、Watch、Campaign 都会 panic 或静默失败,日志里还看不到明显错误。
-
DialTimeout至少设为5 * time.Second;低于 3 秒容易被 DNS 解析延迟或瞬时网络抖动误判为不可达 - 必须显式传
grpc.WithBlock(),否则 client 构造是异步的,你拿到的 client 对象可能还没连上 etcd 就开始调用Election.Campaign() - 本地开发关 TLS 时,要加
grpc.WithInsecure();生产环境开 TLS 则必须配全tls.Config,漏掉ServerName会报x509: certificate is valid for ... not ...
选主不能只靠 Campaign() 成功就认为稳了
election.Campaign() 返回 nil 只代表你写入 leader key 成功了一次,不代表 lease 持续有效。etcd 的 lease 默认过期后 key 被删,但你的程序如果没做续租和监听,就会变成“假 leader”——还在跑任务,其实早被踢出。
- 必须用
concurrency.NewSession(cli, concurrency.WithTTL(10))创建带租约的 session,TTL 建议 10~15 秒,太短易抖动,太长故障发现慢 - 续租 goroutine 要独立运行:
session.Lease().KeepAlive()返回的 channel 必须持续读取,不能只调一次 -
election.Observe()返回的 channel 会在 lease 过期、key 被删、被抢占时推送*concurrency.ElectionResponse,但它也会关闭——必须用select { case resp := 双重判断 - 收到
nil或 channel 关闭,立刻停止业务逻辑(比如关掉 Gin 的 HTTP server、停消费消息队列)
Gin 启停要配合 leader 身份动态切换
Gin 的 engine.Run() 是阻塞调用,不能等选主完成再启动,也不能在失权时靠杀进程硬切——得用优雅启停 + context 控制生命周期。
- 把 Gin server 包进一个可启停结构体,用
http.Server显式管理,避免直接调engine.Run() - leader 状态变更时,通过 channel 通知 server:上位则
server.ListenAndServe(),退位则server.Shutdown(ctx)并等待结束 - 别在
Observe()的 goroutine 里做耗时操作(比如 reload config、init DB),否则会卡住后续 leader 变更通知 - 多个节点共用同一个
concurrency.Election实例?不行。CAS 冲突率飙升,选举像抽风——每个节点必须 new 自己的Election
Watch 配置变更时路径前缀和重试逻辑不能省
故障转移期间,配置中心也要跟着切;但 Watch 不稳定,常见静默丢事件,不是 etcd 问题,而是客户端没兜住。
立即学习“go语言免费学习笔记(深入)”;
- Watch 必须用
clientv3.WithPrefix("/services/your-service/"),且结尾统一加斜杠;/services/your-service和/services/your-service/是两个不同前缀 - 绝不能
for range watchCh,必须for { select { case wresp := - 每次 Watch 启动要用新 context,带 timeout(比如 30s),旧 context 复用会导致
ErrCanceled后无法重建流 - 遇到
ErrCompacted,要从wresp.Header.CompactRevision重新 Watch;遇到context.DeadlineExceeded,说明连接断了,应重建 client
真正的难点不在代码写了多少行,而在 lease 续租 goroutine 是否真的在跑、Observe() channel 是否被正确判空、Gin server 是否真被 Shutdown 且无残留 goroutine —— 这些地方一漏,集群就出现双 leader 或脑裂。


















