Статьи

JGroups: выборы лидера без дополнительной инфраструктуры

Всем привет,

В этом посте я покажу, как вы можете решить проблему выбора лидера, не используя дополнительную инфраструктуру, такую ​​как Apache Zookeeper или Consul .

Выбор лидера является распространенным способом решения проблемы, заключающейся в том, что в распределенной системе только один экземпляр должен выполнять определенную работу.

Это может быть, например,

  • запуск запланированных заданий
  • координация установления соединения, когда система действует как клиент по отношению к внешним системам
  • выполнение задач по очистке

Обычно это решается путем использования упомянутой или аналогичной инфраструктуры. Но есть альтернатива, если вы не хотите вводить их в системный ландшафт: JGroups .

JGroups является

Инструментарий для надежного обмена сообщениями. Его можно использовать для создания кластеров, чьи узлы могут отправлять сообщения друг другу.
[Http://jgroups.org/]

С JGroups настройку выбора лидера можно сделать довольно легко, используя концепцию View JGroups.

Представления являются актуальными, угадайте, какие представления о состоянии кластера. Поскольку каждый кластер имеет ровно одного координатора, который является первым членом списка членов в представлении, этот можно интерпретировать как лидер кластера.

Если лидер умирает / перезапускается / неисправен, следующий участник в списке становится новым лидером. Это очень удобный и детерминированный подход.

пример

Давайте посмотрим на очень простой код, который демонстрирует это:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class JGroupsLeaderElectionExample {
  
  private static final int MAX_ROUNDS = 1_000;
  private static final int SLEEP_TIME_IN_MILLIS = 1000;
  
  public static void main(String[] args) throws Exception {
    JChannel channel = new JChannel();
    channel.connect("The Test Cluster");
    for (int round = 0; round < MAX_ROUNDS; round++) {
      checkLeaderStatus(channel);
      sleep();
    }
  
    channel.close();
  }
  
  private static void sleep() {
    try {
      Thread.sleep(SLEEP_TIME_IN_MILLIS);
    } catch (InterruptedException e) {
      // Ignored
    }
  }
  
  private static void checkLeaderStatus(JChannel channel) {
    View view = channel.getView();
    Address address = view.getMembers()
                          .get(0);
    if (address.equals(channel.getAddress())) {
      System.out.println("I'm (" + channel.getAddress() + ") the leader");
    } else {
      System.out.println("I'm (" + channel.getAddress() + ") not the leader");
    }
  }
}

Приведенный выше код создает новый JChannel с настройками стека по умолчанию. Стек также может быть настроен с использованием файла XML или программного подхода.
Затем канал подключается к тестовому кластеру . JGroups обнаруживает кластер, передавая по соединению. Если текущий экземпляр является первым, он создает кластер.

В цикле код теперь просто получает фактическое представление из канала и проверяет, является ли фактический экземпляр также первым членом или нет. Как вы помните, первый член может рассматриваться как лидер.

Если вы теперь запустите несколько экземпляров и остановите первый, второй вступит во владение. Как в этом примере:

1
2
3
4
5
6
7
-------------------------------------------------------------------
GMS: address=Ygdrassil-21922, cluster=The Test Cluster, physical address=2003:4e:a904:2d67:55c:2653:7e28:8634:59721
-------------------------------------------------------------------
I'm (Ygdrassil-21922) the leader
I'm (Ygdrassil-21922) the leader
I'm (Ygdrassil-21922) the leader
I'm (Ygdrassil-21922) the leader
01
02
03
04
05
06
07
08
09
10
-------------------------------------------------------------------
GMS: address=Ygdrassil-57947, cluster=The Test Cluster, physical address=2003:4e:a904:2d67:55c:2653:7e28:8634:59724
-------------------------------------------------------------------
I'm (Ygdrassil-57947) not the leader
I'm (Ygdrassil-57947) not the leader
I'm (Ygdrassil-57947) not the leader
I'm (Ygdrassil-57947) not the leader
I'm (Ygdrassil-57947) not the leader
I'm (Ygdrassil-57947) the leader
I'm (Ygdrassil-57947) the leader

Как обычно, код можно найти на моей учетной записи GitHub .

Резюме

В этой статье мы увидели, как организовать выборы лидера без введения какой-либо дополнительной инфраструктуры. JGroups предоставляет намного больше интересных вещей, таких как распределенные счетчики, выполнение распределенных задач и так далее.