Как настроить шину событий Vert.x для работы в кластере контейнеров Docker?

В моей текущей настройке я использую опцию многоадресной рассылки по умолчанию диспетчера кластеров Hazelcast. Когда я связываю экземпляры моих контейнерных модулей Vertx (через сетевые ссылки Docker), я вижу, что они успешно создают кластер Hazelcast. Однако, когда я пытаюсь публиковать события в шине событий из одного модуля, другой модуль на это не реагирует. Я не уверен, как настройки сети в кластере Hazelcast связаны с настройками сети для шины событий.

На данный момент у меня есть следующая программная конфигурация для каждого из моих модулей Vert.x, каждый из которых развернут внутри контейнера докеров.

ClusterManager clusterManager = new HazelcastClusterManager();
VertxOptions vertxOptions = new VertxOptions()
            .setClustered(true)
            .setClusterManager(clusterManager);
vertxOptions.setEventBusOptions(new EventBusOptions()
            .setClustered(true)
            .setClusterPublicHost("application"));

В руководстве Vert.x Core указано, что мне, возможно, придется настроить clusterPublicHost и clusterPublicPort для шины событий, но я не уверен, как они связаны с общей топологией сети.


person Psycho Punch    schedule 02.10.2016    source источник


Ответы (3)


Один ответ здесь: https://groups.google.com/d/msg/vertx/_2MzDDowMBM/nFoI_k6GAgAJ

Я вижу, что этот вопрос возникает часто, и что многие люди упускают из виду в документации (включая меня), так это того, что шина событий не использует диспетчер кластера для отправки сообщений шины событий. Т.е. в вашем примере с Hazelcast в качестве менеджера кластера у вас есть кластер Hazelcast и он обменивается данными должным образом (так что ваш Cluster Manager в порядке); однако шина событий не может взаимодействовать с другими экземплярами докеров по одной или нескольким из следующих причин:

  1. Он пытается использовать неверный IP-адрес для другого узла (то есть IP-адрес частного интерфейса в экземпляре Docker, а не публично отображаемый)
  2. Он пытается связаться с портом, который Docker не настроен на пересылку (шина событий выбирает динамический порт, если вы его не укажете)

Что вам нужно сделать:

  1. Сообщите Vertx IP-адрес, который другие узлы должны использовать для связи с каждым экземпляром (с помощью параметров -cluster-host [командная строка], setClusterPublicHost [VertXOptions] или «vertx.cluster.public.host» [Свойство системы])
  2. Явно укажите Vertx порт, который следует использовать для связи по шине событий, и убедитесь, что Docker пересылает трафик для этих портов (используя "vertx.cluster.public.port" [Системное свойство], setClusterPublicPort [VertXOptions] или -cluster-port [командная строка] параметры). Раньше я использовал 15701, потому что его легко запомнить (просто «1» в портах Hazelcast).

Шина событий использует диспетчер кластеров только для управления информацией об IP / портах других экземпляров Vertx и регистрации потребителей / производителей. Связь осуществляется независимо от диспетчера кластера, поэтому вы можете правильно настроить диспетчер кластера и обмениваться данными, но при этом не иметь связи по шине событий.

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

Что-то, что также может произойти, заключается в том, что vert.x использует интерфейс обратной связи, когда не указывает IP, который vert.x (не hazelcast) должен использовать для связи по шине событий. Проблема здесь в том, что вы не знаете, какой интерфейс используется для связи (loopback, интерфейс с IP, у вас даже может быть несколько интерфейсов с IP).

Чтобы решить эту проблему, я однажды написал метод https://github.com/swisspush/vertx-cluster-watchdog/blob/master/src/main/java/org/swisspush/vertx/cluster/ClusterWatchdogRunner.java#L101

person haschibaschi    schedule 03.10.2016

Менеджер кластера работает нормально, конфигурация менеджера кластера должна быть одинаковой на каждом узле (машине / контейнере докера) в вашем кластере или вообще не выполнять никаких конфигураций (используйте конфигурацию по умолчанию вашего диспетчер кластера).

Вы должны сделать конфигурацию шины событий согласованной на каждом узле, вы должны установить узел кластера на каждом узле как IP-адрес самого этого узла и любой произвольный номер порта (если вы не пытаетесь запустить более чем экземпляр Vert.x на одном узле, вам необходимо выбрать другой номер порта для каждого экземпляра Vert.x).

Например, если IP-адрес узла 192.168.1.12, тогда вы должны сделать следующее:

VertxOptions options = new VertxOptions()
                .setClustered(true)
                .setClusterHost("192.168.1.12") // node ip
                .setClusterPort(17001) // any arbitrary port but make sure no other Vert.x instances using same port on the same node
                .setClusterManager(clusterManager);

на другом узле с IP-адресом 192.168.1.56 вы должны сделать следующее:

VertxOptions options = new VertxOptions()
                .setClustered(true)
                .setClusterHost("192.168.1.56") // other node ip
                .setClusterPort(17001) // it is ok because this is a different node
                .setClusterManager(clusterManager);
person Mohamed Elsayed    schedule 03.03.2018

нашел это решение, которое отлично сработало для меня, ниже мой фрагмент кода (важная часть - options.setClusterHost()

public class Runner {

    public static void run(Class clazz) {
        VertxOptions options = new VertxOptions();
        try {
            // for docker binding
            String local = InetAddress.getLocalHost().getHostAddress();
            options.setClusterHost(local);
        } catch (UnknownHostException e) { }

        options.setClustered(true);

        Vertx.clusteredVertx(options, res -> {
            if (res.succeeded()) {
                res.result().deployVerticle(clazz.getName());
            } else {
                res.cause().printStackTrace();
            }
        });
    }
}

public class Publisher extends AbstractVerticle {

    public static void main(String[] args) {
        Runner.run(Publisher.class);
    }

    ...
}

больше ничего определять не надо ...

person shahaf    schedule 11.08.2018