Кластеризация Apache ServiceMix (Apache Karaf) с помощью Cellar

1112

December 18, 2017

1. Установка ServiceMix 7.0.1

Описано в статье Установка Apache ServiceMix 7.0.1 на сервере Ubuntu 16.04 LTS

2. Подключение репозитория Cellar

Для Karaf 4.0.9, который входит в состав ServiceMix 7.0.1, предназначена версия Cellar 4.0.4 (последняя на момент написания статьи).

Для ее установки необходимо подключить репозиторий


karaf@root> feature:repo-add cellar 4.0.4

3. Установка Cellar


karaf@root> feature:install cellar
karaf@root> cluster:node-list
  | Id                 | Alias | Host Name     | Port
-----------------------------------------------------
x | 192.168.114.9:5701 |       | 192.168.114.9 | 5701

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


192.168.114.9
10.1.1.43
10.1.1.44

Видно, что два узла находятся в одной подсети, а третий - в отдельной.

4. Настройка кластера в случае нескольких физических подсетей

Apache Karaf Cellar по-умолчанию использует протокол multicast (с помощью библиотеки hazelcast) для автоматического поиска узлов в текущей подсети. Действительно, сразу после установки два из моих узла "увидели" друг друга, а третий - остался незамеченным.

для 192.168.114.9:

karaf@root>cluster:node-list
  | Id                 | Alias | Host Name     | Port
-----------------------------------------------------
x | 192.168.114.9:5701 |       | 192.168.114.9 | 5701

для 10.1.1.43:

karaf@root>cluster:node-list
  | Id                 | Alias | Host Name     | Port
-----------------------------------------------------
  | 10.1.1.44:5701     |       | 10.1.1.44     | 5701
x | 10.1.1.43:5701     |       | 10.1.1.43     | 5701

для 10.1.1.44:

karaf@root>cluster:node-list
  | Id                 | Alias | Host Name     | Port
-----------------------------------------------------
x | 10.1.1.44:5701     |       | 10.1.1.44     | 5701
  | 10.1.1.43:5701     |       | 10.1.1.43     | 5701

Но мне было необходимо создать один кластер из трех узлов.

Для этого потребуется настроить hazelcast на поиск узлов по TCP/IP. В последних версиях Cellar возможна работа лишь в одном из режимов поиска узлов: либо multicast, либо tcp/ip. Поэтому изменим в файле-конфигурации настройки: etc/hazelcast.xml (путь относительно установленного ServiceMix или Karaf)

    ...
    
    <hz:network>
        
        ...
        
        <hz:join>
            <hz:multicast enabled="false">
                <hz:multicast-group>224.2.2.3</hz:multicast-group>
                <hz:multicast-port>54327</hz:multicast-port>
            </hz:multicast>
            <hz:tcp-ip enabled="true">
              <hz:interface>192.168.114.9</hz:interface>
              <hz:interface>10.1.1.43</hz:interface>
              <hz:interface>10.1.1.44</hz:interface>
            </hz:tcp-ip>

    ...

Выключим multicast <hz:multicast enabled="false"> , включим tcp/ip <hz:tcp-ip enabled="true"> и прописать явно список узлов, входящих в кластер.

После перезапуска самого Karaf спустя несколько секунд кластер смог увидеть все ноды.

для 192.168.114.9:

karaf@root>cluster:node-list
  | Id                 | Alias | Host Name     | Port
-----------------------------------------------------
  | 10.1.1.44:5701     |       | 10.1.1.44     | 5701
  | 10.1.1.43:5701     |       | 10.1.1.43     | 5701
x | 192.168.114.9:5701 |       | 192.168.114.9 | 5701

для 10.1.1.43:

karaf@root>cluster:node-list
  | Id                 | Alias | Host Name     | Port
-----------------------------------------------------
  | 10.1.1.44:5701     |       | 10.1.1.44     | 5701
x | 10.1.1.43:5701     |       | 10.1.1.43     | 5701
  | 192.168.114.9:5701 |       | 192.168.114.9 | 5701

для 10.1.1.44:

karaf@root>cluster:node-list
  | Id                 | Alias | Host Name     | Port
-----------------------------------------------------
x | 10.1.1.44:5701     |       | 10.1.1.44     | 5701
  | 10.1.1.43:5701     |       | 10.1.1.43     | 5701
  | 192.168.114.9:5701 |       | 192.168.114.9 | 5701

5. Механизм синхронизации кластера Cellar

После создания кластера Cellar в конфигурации по-умолчанию все его узлы равнозначны. Это значит, что любые изменения синхронизируемых объектов после их внесения на одном узле сразу распространяются и на другие узлы кластера.

Кластер Cellar может синхронизировать следующие типы объектов Karaf :

  1. Конфигурация (настройки)
  2. Bundle-ы (бандлы - пользовательские приложения)
  3. KAR (к сожалению, мне пока не удалось найти документацию по этому типу объектов)
  4. Репозитории Feature-ов
  5. Feature-ы (фичеры - модули Karaf)

Связь (обмен) между узлами кластера Cellar можно представить в виде схемы:

Каждый узел может выступать в роли:

  1. Producer - поставщик событий
  2. Consumer - потребитель событий
  3. Event Handler - обработчик событий

Таким образом, когда в один из узлов вносятся изменения какого-либо объекта синхронизации (конфигурация, бандлы, фичеры и др.), этот узел рассылает (producer) сообщение о событии всем остальным узлам. В свою очередь, остальные узлы принимают (consumer) это сообщение и передают в соответствующий обработчик (event handler). Этим механизмом поддерживается идентичность узлов кластера Cellar.

6. Управление ролями узлов кластера Cellar

Настройки хранятся в файле конфигурации etc/org.apache.karaf.cellar.node.cfg

Для просмотра состояния ролей узла можно выполнить следующие команды:


karaf@root>cluster:producer-status
  | Node               | Status
-------------------------------
  | 10.1.1.44:5701     | ON
  | 10.1.1.43:5701     | ON
x | 192.168.114.9:5701 | ON


karaf@root>cluster:consumer-status
  | Node               | Status
-------------------------------
  | 10.1.1.44:5701     | ON
  | 10.1.1.43:5701     | ON
x | 192.168.114.9:5701 | ON

karaf@root>cluster:handler-status
  | Node               | Status | Event Handler
------------------------------------------------------------------------------------------
  | 10.1.1.44:5701     | ON     | org.apache.karaf.cellar.bundle.BundleEventHandler
  | 10.1.1.44:5701     | ON     | org.apache.karaf.cellar.config.ConfigurationEventHandler
  | 10.1.1.44:5701     | ON     | org.apache.karaf.cellar.kar.KarEventHandler
  | 10.1.1.44:5701     | ON     | org.apache.karaf.cellar.features.RepositoryEventHandler
  | 10.1.1.44:5701     | ON     | org.apache.karaf.cellar.features.FeaturesEventHandler
  | 10.1.1.43:5701     | ON     | org.apache.karaf.cellar.bundle.BundleEventHandler
  | 10.1.1.43:5701     | ON     | org.apache.karaf.cellar.config.ConfigurationEventHandler
  | 10.1.1.43:5701     | ON     | org.apache.karaf.cellar.kar.KarEventHandler
  | 10.1.1.43:5701     | ON     | org.apache.karaf.cellar.features.FeaturesEventHandler
  | 10.1.1.43:5701     | ON     | org.apache.karaf.cellar.features.RepositoryEventHandler
x | 192.168.114.9:5701 | ON     | org.apache.karaf.cellar.config.ConfigurationEventHandler
x | 192.168.114.9:5701 | ON     | org.apache.karaf.cellar.bundle.BundleEventHandler
x | 192.168.114.9:5701 | ON     | org.apache.karaf.cellar.kar.KarEventHandler
x | 192.168.114.9:5701 | ON     | org.apache.karaf.cellar.features.RepositoryEventHandler
x | 192.168.114.9:5701 | ON     | org.apache.karaf.cellar.features.FeaturesEventHandler

Видно, что роли Producer и Consumer задаются на целый узел, а обработчики события - на каждый тип объекта.

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

Выключение ролей:


karaf@root>cluster:producer-stop
  | Node               | Status
-------------------------------
x | 192.168.114.9:5701 | OFF


karaf@root>cluster:consumer-stop
  | Node               | Status
-------------------------------
x | 192.168.114.9:5701 | OFF


karaf@root>cluster:handler-stop org.apache.karaf.cellar.bundle.BundleEventHandler
  | Node               | Status | Event Handler
-----------------------------------------------------------------------------------
x | 192.168.114.9:5701 | OFF    | org.apache.karaf.cellar.bundle.BundleEventHandler

Включение ролей:


karaf@root>cluster:producer-start
  | Node               | Status
-------------------------------
x | 192.168.114.9:5701 | ON


karaf@root>cluster:consumer-start
  | Node               | Status
-------------------------------
x | 192.168.114.9:5701 | ON


karaf@root>cluster:handler-start org.apache.karaf.cellar.bundle.BundleEventHandler
  | Node               | Status | Event Handler
-----------------------------------------------------------------------------------
x | 192.168.114.9:5701 | ON     | org.apache.karaf.cellar.bundle.BundleEventHandler

В добавок к этому есть возможность из консоли одного узла управлять ролями другого узла. Для этого в конце каждой команды следует указать узел, например:


karaf@root>cluster:node-list
  | Id                 | Alias | Host Name     | Port
-----------------------------------------------------
  | 10.1.1.44:5701     |       | 10.1.1.44     | 5701
  | 10.1.1.43:5701     |       | 10.1.1.43     | 5701
x | 192.168.114.9:5701 |       | 192.168.114.9 | 5701


karaf@root>cluster:producer-stop 10.1.1.44:5701
  | Node           | Status
---------------------------
  | 10.1.1.44:5701 | OFF


karaf@root>cluster:producer-status
  | Node               | Status
-------------------------------
  | 10.1.1.44:5701     | OFF
  | 10.1.1.43:5701     | ON
x | 192.168.114.9:5701 | ON


karaf@root>cluster:producer-start 10.1.1.44:5701
  | Node           | Status
---------------------------
  | 10.1.1.44:5701 | ON

7. Выделение групп узлов кластера Cellar

Узлы кластера Cellar можно поделить по группам. В таком случае сообщения о событиях будут приниматься теми узлами, которые входят в состав группы. По-умолчанию все узлы добавляются в группу default. Это единственная группа, которая всегда есть, и ее нельзя удалить, т.к. она используется как шаблон для создания других групп.


karaf@root>cluster:group-list
  | Group   | Members
------------------------------------------------------------------
x | default | 10.1.1.43:5701 10.1.1.44:5701 192.168.114.9:5701(x)

Видно, что все три мои узла находятся в составе группы по-умолчанию default.

Создадим группу test и перенесем в нее один узел. Стоит отметить, что перенести в группу можно только тот узел, в чьей консоли выполняются команды (в отличие от управления ролями).


karaf@root>cluster:group-create test

karaf@root>cluster:group-list
  | Group   | Members
------------------------------------------------------------------
  | test    |
x | default | 10.1.1.43:5701 10.1.1.44:5701 192.168.114.9:5701(x)

karaf@root>cluster:group-join test
  | Group   | Members
------------------------------------------------------------------
x | test    | 192.168.114.9:5701(x)
x | default | 10.1.1.43:5701 10.1.1.44:5701 192.168.114.9:5701(x)

karaf@root>cluster:group-quit default
  | Group   | Members
--------------------------------------------
x | test    | 192.168.114.9:5701(x)
  | default | 10.1.1.43:5701 10.1.1.44:5701

В такой настройке состояние узла 192.168.114.9:5701 не будет синхронизировано с остальными двумя узлами, т.к. они теперь находятся в разных группах.

Возврат к исходному состоянию:


karaf@root>cluster:group-join default
  | Group   | Members
------------------------------------------------------------------
x | test    | 192.168.114.9:5701(x)
x | default | 10.1.1.43:5701 10.1.1.44:5701 192.168.114.9:5701(x)

karaf@root>cluster:group-quit test
  | Group   | Members
------------------------------------------------------------------
  | test    |
x | default | 10.1.1.43:5701 10.1.1.44:5701 192.168.114.9:5701(x)

karaf@root>cluster:group-delete test

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

7.1 Перекрытие групп узлов

Если создать конфигурацию групп узлов, показанную на рисунке, и произвести изменения, например, бандла в узле NodeA, то произойдут следующие миграции изменений:

  1. Поскольку NodeA и NodeB объединены в одну группу CG1, то бандл установится на узел NodeB
  2. Поскольку NodeB и NodeD объединены в одну группу CG3, то бандл установится на узел NodeD
  3. Поскольку NodeD и NodeC объединены в одну группу CG2, то бандл установится на узел NodeC

Таким образом, бандл будет установлен на все узлы кластера, несмотря на то, что явным образом все узлы не находятся в единой группе.

8. Примеры топологии узлов кластера

Типичными примерами топологии узлов кластера Cellar являются топологии в виде Креста и в виде Звезды.

8.1 Топология Крест

В этой топологии Cellar устанавливается на все узлы в одинаковой конфигурации ролей (Producers, Consumers, Event handlers) - все роли включены. Изменения могут вноситься в любой узел, распространяются на все узлы.

8.2 Топология Звезда

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