如何使用etcd选举api

时间:2017-07-28 20:59:34

标签: go etcd

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
            }
        }
    }

1 个答案:

答案 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可以找到领导报告。