как использовать API выборов 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
            }
        }
    }

person pjvds    schedule 28.07.2017    source источник
comment
@ Адриан, он пишет клиент для etcd. Не имеет никакого отношения к запуску службы. etcd предоставляет средства для того, чтобы ваш клиент выбрал своего лидера при содействии etcd.   -  person Luke    schedule 15.08.2017


Ответы (1)


В настоящее время избирательный API не позволяет вам сделать это просто. Однако вы можете запустить код выборов в горутине и запросить результат выборов, используя вызов 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
}

Полный пример выбора лидера с прерыванием соединения и начальным отчетом о лидерстве можно найти здесь.

person Thrawn01    schedule 03.12.2018