etcd v3的新主要版本引入了新的并发原语。其中之一是election
。
api缺乏启动广告系列并返回(其他)获胜者的支持,这意味着我们需要查询领导者。这使得它很复杂,因为现在我们有两个并发路径,一个运行一个活动,另一个监控领导改变。如果我们希望所有节点都为领导者运行,并且回退到跟随者,那么同步这两个节点的最佳做法是什么。
go func() {
if err := election.Campaign(this.ctx, this.Address); err != nil {
this.log.Error("election campaign failed", zap.Error(err))
}
}()
for {
select {
case response, ok := <-observations:
if !ok {
this.log.Warn("election observation channel closed")
return
}
value := string(response.Kvs[0].Value)
change := LeaderChanged{strings.EqualFold(value, this.Address), value}
select {
case changes <- change:
// should we figure out if we are a leader at this point?
case <-session.Done():
// it might be that we lost leadership
}
}
}
答案 0 :(得分:0)
当前,选举API不允许您简单地执行此操作。但是你可以
在goroutine中运行选举代码,并通过查询查询选举结果
使用election.Leader()
调用。
go func() {
if err := election.Campaign(this.ctx, this.Address); err != nil {
this.log.Error("election campaign failed", zap.Error(err))
}
fmt.Printf("we are leader")
for {
select {
case response, ok := <-observations:
if !ok {
this.log.Warn("election observation channel closed")
return
}
value := string(response.Kvs[0].Value)
change := LeaderChanged{strings.EqualFold(value, this.Address), value}
select {
case changes <- change:
// should we figure out if we are a leader at this point?
case <-session.Done():
// it might be that we lost leadership
}
}
}
}()
// Wait until we have a leader before continuing
for {
resp, err := election.Leader(this.ctx)
if err != nil {
if err != concurrency.ErrElectionNoLeader {
this.log.Warn("Leader returned error", err)
return
}
time.Sleep(time.Millisecond * 300)
continue
}
// Report if we are not leader
if string(resp.Kvs[0].Value) != this.Address {
fmt.Println("we are NOT leader")
}
break
}
具有连接中断和初始的领导者选举的完整示例 here可以找到领导报告。