Настройка кластеризации и репликации сеанса в Tomcat#

Чтобы включить кластеризацию в Tomcat, достаточно добавить элемент <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/> в <Engine> или <Host>.

Использование данной конфигурации включает репликацию сессий между всеми node кластера с использованием DeltaManager. Каждая сессия реплицируется на все остальные node. Такой подход хорошо работает для небольших кластеров (до 4 node), но не рекомендуется для больших кластеров. При использовании DeltaManager Tomcat будет реплицировать сессии на все node, даже на те, где приложение не развернуто.

Чтобы избежать проблем, рекомендуется использовать BackupManager. В отличие от DeltaManager, BackupManager реплицирует данные сессии только на один резервный node, и только на те node, где приложение развернуто.

Важные параметры по умолчанию:

  • Multicast-адрес;

  • Multicast-порт (порт и адрес определяют членство в кластере);

  • IP-адрес для рассылки: java.net.InetAddress.getLocalHost().getHostAddress();

  • TCP-порт для прослушивания сообщений репликации: первый доступный серверный сокет в диапазоне 4000-4100;

  • Listener: настроен как ClusterSessionListener;

  • Два Interceptor: настроены TcpFailureDetector и MessageDispatchInterceptor.

Пример конфигурации:

<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
                 channelSendOptions="8">

          <Manager className="org.apache.catalina.ha.session.DeltaManager"
                   expireSessionsOnShutdown="false"
                   notifyListenersOnReplication="true"/>

          <Channel className="org.apache.catalina.tribes.group.GroupChannel">
            <Membership className="org.apache.catalina.tribes.membership.McastService"
                        address="<IP_address>"
                        port="45564"
                        frequency="500"
                        dropTime="3000"/>
            <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
                      address="auto"
                      port="4000"
                      autoBind="100"
                      selectorTimeout="5000"
                      maxThreads="6"/>

            <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
              <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
            </Sender>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatchInterceptor"/>
          </Channel>

          <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
                 filter=""/>
          <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>

          <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
                    tempDir="/tmp/war-temp/"
                    deployDir="/tmp/war-deploy/"
                    watchDir="/tmp/war-listen/"
                    watchEnabled="false"/>

          <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
        </Cluster>

Безопасность#

Реализация кластера в Tomcat предполагает использование безопасной и доверенной сети для всего сетевого трафика, связанного с кластером. Небезопасно запускать кластер в ненадежной или незащищенной сети.

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

  • Частная локальная сеть (LAN);

  • Виртуальная частная сеть (VPN);

  • IPSEC.

Компонент EncryptInterceptor обеспечивает конфиденциальность и целостность данных, но он не защищает от всех рисков, связанных с запуском кластера Tomcat в ненадежной сети, особенно от атак типа DoS.

Настройка репликации#

Чтобы настроить репликацию сессий в Tomcat, выполните следующие шаги:

  1. Все атрибуты сессии должны реализовывать интерфейс java.io.Serializable.

  2. Элемент <Cluster> в файле server.xml должен быть раскомментирован.

  3. Если определены пользовательские valve для кластера, убедитесь, что также определен ReplicationValve внутри элемента <Cluster> в server.xml.

  4. Если экземпляры Tomcat работают на одной машине, убедитесь, что атрибут Receiver.port уникален для каждого экземпляра. В большинстве случаев Tomcat автоматически определяет доступные порты в диапазоне 4000-4100.

  5. Убедитесь, что в web.xml есть элемент <distributable/>.

  6. Если используете mod_jk, убедитесь, что атрибут jvmRoute задан в элементе <Engine>: <Engine name="Catalina" jvmRoute="node01">.

  7. Убедитесь, что все node работают в одинаковом времени и синхронизируются с сервисом NTP.

  8. Убедитесь, что балансировщик нагрузки настроен на режим sticky session mode.

Включение репликации#

Для включения репликации сессий в Tomcat можно использовать три различных подхода:

  1. Использование сохранения сессий (PersistenceManager) и хранение сессий в общей файловой системе (FileStore).

  2. Использование сохранения сессий (PersistenceManager) и хранение сессий в общей базе данных (JDBCStore).

  3. Использование репликации в памяти с помощью SimpleTcpCluster, который поставляется с Tomcat (библиотеки catalina-tribes.jar и catalina-ha.jar).

Tomcat может выполнять репликацию состояния сессии «все-ко-всем» с использованием DeltaManager или репликацию только на один резервный node с использованием BackupManager. Данная репликация эффективна только для небольших кластеров. Для больших кластеров рекомендуется использовать BackupManager, где сессия хранится только на одном резервном node.

В настоящее время можно использовать атрибут domain в mod_jk для создания разделов кластера, что позволяет создать более масштабируемое решение с DeltaManager (для этого нужно настроить domain). Чтобы уменьшить сетевой трафик в среде, можно разделить кластер на меньшие группы, используя разные multicast-адреса для каждой группы.

Информация о кластере#

Членство в кластере устанавливается с помощью multicast-сообщений (heartbeats). Таким образом, если нужно разделить кластер, измените IP-адрес или порт multicast в элементе <Membership>. Сообщение содержит IP-адрес node и TCP-порт, который Tomcat использует для трафика репликации. Все данные передаются по TCP.

ReplicationValve используется для определения завершения запроса и инициации репликации, если это необходимо. Данные реплицируются только в случае изменения сессии (например, при вызове setAttribute или removeAttribute).

Одним из важных аспектов производительности является выбор между синхронной и асинхронной репликацией. В синхронном режиме запрос не завершается до тех пор, пока реплицированная сессия не будет отправлена и восстановлена на всех других node кластера. Синхронный или асинхронный режим настраивается с помощью флага channelSendOptions, который представляет собой числовое значение. По умолчанию для комбинации SimpleTcpCluster/DeltaManager используется значение 8, что соответствует асинхронному режиму.

Привязка сессии после сбоя к резервному node#

Если mod_jk используется без sticky sessions или в случае сбоя, идентификатор сессии (session id) необходимо изменить, так как он ранее содержал идентификатор (jvmRoute) предыдущего Tomcat. Для решения этой проблемы используется JvmRouteBinderValve.

JvmRouteBinderValve перезаписывает идентификатор сессии, чтобы гарантировать, что следующий запрос не будет перенаправлен на случайный node. valve перезаписывает значение JSESSIONID в cookie-файлы.

С помощью атрибута sessionIdAttribute можно изменить имя атрибута запроса, который содержит старый идентификатор сессии. По умолчанию это org.apache.catalina.ha.session.JvmRouteOriginalSessionID.

Можно включить данный режим переключения через JMX перед отключением node на всех резервных узлах. Установите enable=true на всех JvmRouteBinderValve, отключите worker в mod_jk, затем отключите node и перезапустите его. После этого включите worker в mod_jk и отключите JvmRouteBinderValve. Этот подход означает, что мигрируют только запрошенные сессии.

Мониторинг кластера с помощью JMX#

Мониторинг является важной задачей при использовании кластера. Некоторые объекты кластера представляют собой JMX MBeans.

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

set CATALINA_OPTS=\
-Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.port=%my.jmx.port% \
-Dcom.sun.management.jmxremote.ssl=false \
-Dcom.sun.management.jmxremote.authenticate=false
Список MBeans для кластера#

Имя

Описание

MBean ObjectName (Engine)

MBean ObjectName (Host)

Cluster

Полный элемент кластера

type=Cluster

type=Cluster,host=${HOST}

DeltaManager

Управление сессиями и обработка репликации сессий

type=Manager,context=${APP.CONTEXT.PATH},host=${HOST}

type=Manager,context=${APP.CONTEXT.PATH},host=${HOST}

FarmWarDeployer

Управление процессом развертывания приложения на всех node кластера

Не поддерживается

type=Cluster,host=${HOST},component=deployer

Member

Предоставление node в кластере

type=Cluster,component=member,name=${NODE_NAME}

type=Cluster,host=${HOST},component=member,name=${NODE_NAME}

ReplicationValve

Управление репликацией на резервные node

type=Valve,name=ReplicationValve

type=Valve,name=ReplicationValve,host=${HOST}

JvmRouteBinderValve

valve для изменения идентификатора сессии на текущий jvmRoute Tomcat

type=Valve,name=JvmRouteBinderValve,context=${APP.CONTEXT.PATH}

type=Valve,name=JvmRouteBinderValve,host=${HOST},context=${APP.CONTEXT.PATH}