RussianLDP Рейтинг@Mail.ru
WebMoney: 
WMZ Z294115950220 
WMR R409981405661 
WME E134003968233 
Visa 
4274 3200 2453 6495 

Глава 9. Связи с несколькими хостами

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

Разработчики должны знать следующие вещи о таких связях, которые организованы через Connector/J:

  • Каждая мультисвязь это обертка основных физических связей.

  • У каждой из основных физических связей есть своя собственная сессия. Сессии не могут быть прослежены, разделены или скопированы, они заданы архитектурой MySQL.

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

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

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

9.1. Формирование отказоустойчивости сервера для связей, используя JDBC

MySQL Connector/J поддерживает отказоустойчивость сервера. Отказоустойчивость происходит, когда связанные со связью ошибки происходят для основной, активной связи. Ошибки связи, по умолчанию, размножены клиенту, который должен обращаться с ними, например, воссоздавая рабочие объекты (Statement, ResultSet и т.д.) и перезапуск процессов. Иногда драйвер мог бы в конечном счете отступить к оригинальному хосту автоматически, прежде чем клиентское приложение продолжит работу, в этом случае переключение хоста прозрачно, клиентское приложение даже не заметит его.

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

Отказоустойчивость формируется на стадии начальной настройки связи сервера связью URL (см. объяснения формата здесь):

jdbc:mysql://[primary host][:port],[secondary host 1][:port][,[secondary host 2][:port]]...[/[database]]
[?propertyName1=propertyValue1[&propertyName2=propertyValue2]...]

Список хостов в связи URL включает два типа хостов primary и secondary. Начиная новую связь, драйвер всегда пытается соединиться с основным хостом сначала и при необходимости с вторичными в списке последовательно, когда есть проблемы коммуникации. Даже если начальная связь с основным хостом прерывается, и драйвер связан с вторичным хостом, основной никогда не теряет особый статус: например, это может формироваться с режимом доступа, отличным от вторичных, это может быть помещено на более высокий приоритет, когда хост должен быть выбран во время процесса отказоустойчивости.

Поддержка кластерных систем формируется следующими свойствами связи (их функции объяснены в параграфах ниже):

  • failOverReadOnly

  • secondsBeforeRetryMaster

  • queriesBeforeRetryMaster

  • retriesAllDown

  • autoReconnect

  • autoReconnectForPools

Формирование режима доступа связи

Как с любой стандартной связью, начальная связь с основным хостом находится в режиме чтения-записи. Однако, если драйвер не устанавливает начальную связь с основным хостом, и она автоматически переключается на следующий хост в списке, режим доступа теперь зависит от значения параметра failOverReadOnly, которое true по умолчанию. То же самое происходит, если драйвер первоначально связан с основным хостом и из-за некоторой неудачи связи, он переключается на вторичный хост. Каждый раз, когда связь отступает к основному хосту, ее режим доступа будет чтением-записью, независимо от того, была ли связь с основным хостом раньше. Режим доступа связи может быть изменен в любое время во время выполнения, вызвав метод method Connection.setReadOnly(boolean), который частично перекрывает свойство failOverReadOnly. При failOverReadOnly=false и режим доступа явно установлен, это становится режимом для каждой связи после переключения хоста, неважно с каким типом хоста связываются, но, если failOverReadOnly=true, изменение режима доступа к чтению-записи возможно только, если драйвер соединяется с основным хостом, однако, даже если режим доступа не может быть изменен для текущей связи, драйвер помнит последнее намерение клиента, и отступая к основному хосту, это является способом, который будет использоваться. Для иллюстрации посмотрите следующие последовательности событий со связью с двумя хостами.

  • Последовательность A с failOverReadOnly=true:

    1. Соединяется с основным хостом в режиме чтения-записи.

    2. Выполняет Connection.setReadOnly(true), основной хост теперь в режиме только для чтения.

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

    4. Выполняет Connection.setReadOnly(false), вторичный хост остается в режиме только для чтения.

    5. Отступает к основному хосту, связь теперь в режиме чтения-записи.

  • Последовательность B с failOverReadOnly=false :

    1. Соединяется с основным хостом в режиме чтения-записи.

    2. Выполняет Connection.setReadOnly(true), основной хост теперь в режиме только для чтения.

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

    4. Выполняет Connection.setReadOnly(false), связь со вторичным хостом переключается в режим чтения-записи.

    5. Отступает к основному хосту, связь теперь в режиме чтения-записи.

Различие между этими двумя сценариями находится в шаге 4: режим доступа для вторичного хоста в последовательности A не изменяется в том шаге, но драйвер помнит и использует установленный режим, отступая к основному хосту, который был бы только для чтения иначе, но в последовательности B, режим доступа для вторичного хоста немедленно изменяется.

Формирование отступления к основному хосту

Как уже упомянуто, основной хост особенный в договоренности отказоустойчивости когда дело доходит до режима доступа хоста. Кроме того, драйвер пытается отступить к основному хосту как можно скорее по умолчанию, даже если никакое коммуникационное исключение не происходит. Два свойства secondsBeforeRetryMaster и queriesBeforeRetryMaster определяют, когда драйвер будет готов повторить повторное соединение с основным хостом (Master в имени свойства указывает на основной хоста нашей связи URL, который является не обязательно основным хостом в репликации):

  • secondsBeforeRetryMaster определяет, сколько времени драйвер ждет прежде, чем попытаться отступить к основному хосту.

  • queriesBeforeRetryMaster определяет количество запросов, которые выполняются, прежде чем драйвер пытается отступить к основному хосту. Заметьте, что для драйвера каждый вызов метода Statement.execute*() увеличивает счетчик выполнения запросов, поэтому, когда сделан вызов Statement.executeBatch() или если включены allowMultiQueries или rewriteBatchStatements, у драйвера может не быть точного фактического количества запросов, выполненных на сервере. Кроме того, драйвер вызывает методы Statement.execute*() внутренне в нескольких случаях. Все это значит, что можно применить queriesBeforeRetryMaster только как грубую спецификацию того, когда примерно отступить к основному хосту.

В целом попытка к отступлению к основному хосту предпринята, когда по крайней мере одно из условий, определенных этими двумя свойствами, выполнено, и попытка всегда происходит в границах транзакции. Однако, если выключен auto-commit, проверка происходит только когда вызван метод Connection.commit() или Connection.rollback(). Автоматическое отступление к основному хосту может быть вообще выключено, установив одновременно secondsBeforeRetryMaster и queriesBeforeRetryMaster в 0. Установка одного из свойств в 0 отключает только одну часть проверки.

Формирование попыток повторного соединения

Устанавливая новую связь или когда событие отказоустойчивости имеет место, драйвер пытается соединиться последовательно со следующим кандидатом в списке хостов. Когда конец списка был достигнут, это начинает снова с начала списка, однако, через основной хост перескакивает, если: (a) НЕ все вторичные хосты были уже проверены, по крайней мере, однажды И (b) условия отступления, определенные secondsBeforeRetryMaster и queriesBeforeRetryMaster, еще не выполняются. Каждый просмотр списка хостов (который не обязательно закончен в конце списка) считается как единственная попытка подключения. Драйвер пробует столько попыток подключения, сколько определено значением retriesAllDown.

Бесшовное повторное соединение

Хотя не рекомендуется, можно заставить драйвер выполнить отказоустойчивость, не лишая законной силы активные экземпляры Statement или ResultSet, устанавливая любой параметр autoReconnect или autoReconnectForPools в true. Это позволяет клиенту продолжать использовать те же самые экземпляры объектов после события отказоустойчивости, не принимая исключительных мер. Это, однако, может привести к неожиданным результатам: например, если драйвер будет связан с основным хостом с режимом доступа для чтения-записи, и он переключается к вторичному хосту в режиме только чтения, дальнейшие попытки выполнить изменяющие данные запросы приведут к ошибкам, а клиент не будет знать об этом. Это ограничение особенно релевантно, используя потоковые данные: после события отказоустойчивости, ResultSet надеется быть в порядке, но основная связь уже, возможно, изменилась, и никакой курсор больше не доступен.

9.2. Формирование отказоустойчивости сервера для связей, используя X DevAPI

Используя X-протокол, Connector/J поддерживает клиентскую функцию отказоустойчивости для установления сессии. Если многократные хосты определяются в связи URL, когда Connector/J не соединяется с перечисленным хостом, это пытается соединиться с другим. Это типовой X DevAPI URL для формирования клиентской отказоустойчивости:

mysqlx://sandy:mypassword@[host1:33060,host2:33061]/test

С клиентской формируемой отказоустойчивостью, когда есть отказ установить связь, Connector/J продолжает пытаться соединиться с хостом в списке хостов. Порядок, в котором хосты проверены для связи, следующий:

  • Для связей с установелнным свойством priority для каждого хоста в связи URL хосты перебраны согласно приоритетам для хостов, которые определяются любыми числами от 0 до 100 с большим числом, указывающим на более высокий приоритет для связи. Например:

    mysqlx://sandy:mypassword@[(address=host1:33060,priority=2),
    (address=host2:33061,priority=1)]/test
    

    В этом примере host1 всегда проверяется до host2, когда новые сессии создаются.

    Приоритеты должны быть установлены для всех или ни для каких хостов.

  • Для связей без свойства priority для каждого хоста в связи URL:

    • Для версий 8.0.19 и позже: хосты проверены один за другим в произвольном порядке.

    • Для версий 8.0.18 и ранее: хосты проверены один за другим в порядке, в котором они появляются в связи URL: хост, перечисленный ранее в списке, будет проверен перед хостом, перечисленным позже в списке.

Заметьте, что особенность отказоустойчивости сервера X DevAPI только допускает отказоустойчивость, когда Connector/J пытается установить связь, но не во время операций после того, как связь была уже установлена.

Объединение связи, используя X DevAPI. Используя объединение связи с X DevAPI, Connector/J отслеживает любой хост, с которым не соединился и в течение короткого времени ожидания после неудачи, избегает соединяться с ним во время создания или поиска Session. Однако, если все другие хосты уже проверены, исключенные хосты будут проверены без ожидания. Как только все хосты проверены и никакие связи не могут быть установлены, Connector/J бросает исключение com.mysql.cj.exceptions.CJCommunicationsException и возвращает сообщение Unable to connect to any of the target hosts.

9.3. Формирование выравнивания нагрузки с Connector/J

Connector/J долго обеспечивал эффективное средство, чтобы распределить нагрузку чтения-записи на многократные экземпляры сервера MySQL для Cluster или средств репликации master-master. Можно динамично формировать уравновешенные связи без приостановки обслуживания. Незавершенные транзакции не потеряны, никакие прикладные исключения не произведены, если какое-либо приложение пытается использовать конкретный экземпляр сервера.

Выравнивание нагрузки формируется на стадии начальной настройки связи сервера следующей связью URL, у которого есть формат, аналогичный общему URL JDBC для подключения MySQL, но со специализированной схемой:

jdbc:mysql:loadbalance://[host1][:port],[host2][:port][,[host3][:port]]...[/[database]]
[?propertyName1=propertyValue1[&propertyName2=propertyValue2]...]

Есть два свойства конфигурации, связанные с этой функциональностью:

  • loadBalanceConnectionGroup Это обеспечивает способность сгруппировать связи из других источников. Это позволяет вам управлять этими источниками JDBC в загрузчике единого класса в любой комбинации, которую вы выбираете. Если они используют ту же самую конфигурацию, и вы хотите управлять ими как логической единственной группой, надо дать им то же самое имя. Это ключевое свойство для управления: если вы не определяете имя (последовательность) для loadBalanceConnectionGroup, вы не можете управлять связями. Все уравновешенные связи, разделяющие то же самое значение loadBalanceConnectionGroup, независимо от того, как приложение создает их, будут управляться вместе.

  • ha.enableJMX Способность управлять связями выставляется, когда вы определяете loadBalanceConnectionGroup, но если вы хотите управлять этим внешне, позвольте JMX, установив это свойство в true. Это позволяет внедрение JMX, которое реализует управление и контролирующие операции группы связи. Далее запустите свое приложение с флагом JVM -Dcom.sun.management.jmxremote. Можно тогда управлять соединениями, используя такой клиент JMX, как jconsole.

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

  • Текущий счетчик активных хостов.

  • Текущий счетчик активных физических соединений.

  • Текущий счетчик активных логических соединений.

  • Общее число созданных логических соединений.

  • Общее число транзакций.

Следующие операции управления могут также быть выполнены:

  • Добавьте хост.

  • Удалите хост.

Интерфейс JMX com.mysql.cj.jdbc.jmx.LoadBalanceConnectionGroupManagerMBean имеет следующие методы:

  • int getActiveHostCount(String group);

  • int getTotalHostCount(String group);

  • long getTotalLogicalConnectionCount(String group);

  • long getActiveLogicalConnectionCount(String group);

  • long getActivePhysicalConnectionCount(String group);

  • long getTotalPhysicalConnectionCount(String group);

  • long getTotalTransactionCount(String group);

  • void removeHost(String group, String host) throws SQLException;

  • void stopNewConnectionsToHost(String group, String host) throws SQLException;

  • void addHost(String group, String host, boolean forExisting);

  • String getActiveHostsList(String group);

  • String getRegisteredConnectionGroups();

Метод getRegisteredConnectionGroups() возвращает имена всех групп связи, определенных в этом загрузчике класса.

Можно проверить эту установку со следующим кодом:

public class Test {
  private static String URL = "jdbc:mysql:loadbalance://" +
                 "localhost:3306,localhost:3310/test?" +
                 "loadBalanceConnectionGroup=first&ha.enableJMX=true";

  public static void main(String[] args) throws Exception {
    new Thread(new Repeater()).start();
    new Thread(new Repeater()).start();
    new Thread(new Repeater()).start();
  }
  static Connection getNewConnection() throws SQLException,
         ClassNotFoundException {
    Class.forName("com.mysql.cj.jdbc.Driver");
    return DriverManager.getConnection(URL, "root", "");
  }

  static void executeSimpleTransaction(Connection c, int conn, int trans) {
    try {
      c.setAutoCommit(false);
      Statement s = c.createStatement();
      s.executeQuery("SELECT SLEEP(1) /* Connection: " + conn +
                     ", transaction: " + trans + " */");
      c.commit();
    } catch (SQLException e) {
      e.printStackTrace();
    }
  }
  public static class Repeater implements Runnable {
    public void run() {
      for(int i=0; i < 100; i++) {
        try {
          Connection c = getNewConnection();
          for(int j=0; j < 10; j++) {
            executeSimpleTransaction(c, i, j);
            Thread.sleep(Math.round(100 * Math.random()));
          }
          c.close();
          Thread.sleep(100);
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    }
  }
}

После компилирования приложение может быть запущено с флагом -Dcom.sun.management.jmxremote, чтобы позволить удаленное управление. jconsole может тогда быть запущена. Главный класс Test будет перечислен jconsole. Выберите это и нажмите Connect. Можно тогда перейти к com.mysql.cj.jdbc.jmx.LoadBalanceConnectionGroupManager . В этом пункте можно нажать на различные операции и исследовать возвращенный результат.

Если бы у вас теперь был дополнительный экземпляр MySQL на порте 3309, вы могли бы гарантировать, что Connector/J начинает использовать его при помощи addHost(), который выставляется в jconsole. Обратите внимание на то, что эти операции могут быть выполнены динамично, не имея необходимости останавливать приложение.

Для получения дополнительной информации о комбинации выравнивания нагрузки и отказоустойчивости, посмотрите раздел 9.5.

9.4. Формирование репликации Master/Slave с Connector/J

Эта секция описывает много особенностей поддержки Connector/J репликации.

Повторение формируется на стадии начальной настройки связи сервера связью URL, у которой есть формат, аналогичный общему URL JDBC для подключения MySQL, но со специализированной схемой:

jdbc:mysql:replication://[master host][:port],[slave host 1][:port][,[slave host 2][:port]]...[/[database]]
[?propertyName1=propertyValue1[&propertyName2=propertyValue2]...]

Пользователи могут определить свойство allowMasterDownConnections=true, чтобы позволить объекты Connection, которые будут созданы даже при том, что никакие основные хосты недостижимы. Такие объекты Connection сообщают, что они только для чтения, и isMasterConnection() вернет false для них. Connection проверяет на доступные мастер-хосты при вызове Connection.setReadOnly(false), бросив SQLException, если он не может установить связь с мастер-хостом или переключаясь на основную связь, если хост доступен.

Пользователи могут определить свойство allowSlavesDownConnections=true, чтобы позволить объекты Connection, которые будут созданы даже при том, что никакие подчиненные хосты недостижимы. Connection во время выполнения проверяются на доступные подчиненные хосты при вызове Connection.setReadOnly(true) (см. объяснение метода ниже), бросая SQLException, если это не может установить связь с подчиненным хостом, если свойство readFromMasterWhenNoSlaves = true (см. ниже для описания свойства).

Масштабирование нагрузки чтения, распределяя трафик на хосты Slave

Connector/J поддерживает связи репликации. Это может автоматически послать запросы read/write на мастер-хост, используя отказоустойчивость или циклический алгоритм балансировки на основе статуса Connection.getReadOnly().

Приложение сигнализирует, что хочет, чтобы транзакция была только для чтения, вызывая Connection.setReadOnly(true). Связь будет использовать одну из slave-связей, которые распределяют нагрузку на подчиненные хосты, используя циклическую схему. Данная связь прилипает к хосту, пока команда границы транзакции (передача или отмена) не дается, или пока хост не удален из службы. После запроса Connection.setReadOnly(true), если вы хотите позволить связь мастер-хосту, когда никакие подчиненные не доступны, установите свойство readFromMasterWhenNoSlaves = true. Заметьте, что основной хост будет использоваться в статусе только для чтения в этих случаях, как будто это подчиненный хост. Также заметьте, что установка readFromMasterWhenNoSlaves=true может привести к дополнительной нагрузке для основного хоста.

Если у вас есть транзакция записи или процесс, который чувствителен ко времени (помните, репликация в MySQL асинхронная), установите связь в режим не только для чтения, вызвав Connection.setReadOnly(false), и драйвер гарантирует, что дальнейшие вызовы посылают в основной сервер MySQL. Драйвер заботится о размножении текущего состояния autocommit, уровня изоляции и каталога между всеми связями, которые это использует, чтобы достигнуть функциональности выравнивания нагрузки.

Чтобы позволить эту функциональность, используйте специализированную схему репликации (jdbc:mysql:replication:// ) соединяясь с сервером.

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

import java.sql.Connection;
import java.sql.ResultSet;
import java.util.Properties;
import java.sql.DriverManager;

public class ReplicationDemo {
  public static void main(String[] args) throws Exception {
    Properties props = new Properties();
    // We want this for failover on the slaves
    props.put("autoReconnect", "true");
    // We want to load balance between the slaves
    props.put("roundRobinLoadBalance", "true");
    props.put("user", "foo");
    props.put("password", "password");

    // Looks like a normal MySQL JDBC url, with a
    // comma-separated list of hosts, the first
    // being the 'master', the rest being any number
    // of slaves that the driver will load balance against
    Connection conn =
      DriverManager.getConnection("jdbc:mysql:replication://master,
                                  slave1,slave2,slave3/test", props);

    // Perform read/write work on the master
    // by setting the read-only flag to "false"
    conn.setReadOnly(false);
    conn.setAutoCommit(false);
    conn.createStatement().executeUpdate("UPDATE some_table ....");
    conn.commit();

    // Now, do a query from a slave, the driver automatically picks one
    // from the list
    conn.setReadOnly(true);
    ResultSet rs = conn.createStatement().executeQuery("SELECT a,b
                                                       FROM alt_table");
    .......
  }
}

Рассмотрите использование Load Balancing JDBC Pool (lbpool), который обеспечивает обертку вокруг типичного драйвера JDBC и позволяет вам использовать пул соединения с БД, который включает проверки на системные отказы и неравномерное распределение нагрузки. Для получения дополнительной информации посмотрите Load Balancing JDBC Driver for MySQL (mysql-lbpool).

Поддержка топографий репликации с несколькими мастерами

Connector/J репликации с несколькими мастерами.

Связь URL для репликации рассмотрена ранее в формате jdbc:mysql:replication://master,slave1,slave2, slave3/test). Она предполагает, что первым (и только первым) хостом является мастер. Поддержка развертывания с произвольным числом мастеров и подчиненных требует синтаксис URL "address-equals" для многократной связи хоста, обсужденной в разделе 6.2, со свойством type=[master|slave]:

jdbc:mysql:replication://address=(type=master)(host=master1host),
                         address=(type=master)(host=master2host),
                         address=(type=slave)(host=slave1host)/database

Connector/J использует уравновешенную связь внутренне для управления основными связями, это означает, что ReplicationConnection, когда формируется, чтобы использовать многократные мастер-хосты, выставляет те же самые опции уравновесить нагрузку через основные хосты, как описано в разделе 9.3.

Живая реконфигурация топографии репликации

Connector/J также поддерживает живое управление хостом репликации. Это позволяет пользователям продвинуть хосты для приложений Java, не требуя перезапуска приложений.

Хостами репликации наиболее эффективно управляют в контексте группы соединения репликации. Класс ReplicationConnectionGroup представляет логическую группировку связей, которые могут быть организованы вместе. Могут быть одна или более таких групп соединения репликации в данном загрузчике класса Java (может быть приложение с двумя различными ресурсами JDBC, которые должны управляться независимо). Этот ключевой класс выставляет методы управления хоста для соединений репликации и объекты ReplicationConnection регистрируются с соответствующим ReplicationConnectionGroup, если значение для нового свойства replicationConnectionGroup определяется. Объект ReplicationConnectionGroup отслеживает эти связи, пока они не закрываются, и это используется, чтобы управлять хостами, связанными с этими связями.

Некоторые важные методы, связанные с управлением хостами, включают:

  • getMasterHosts(): Возвращает коллекцию последовательностей, представляющих мастер-хосты.

  • getSlaveHosts(): Возвращает коллекцию последовательностей, представляющих подчиненные хосты.

  • addSlaveHost(String host): Добавляет новый хост в пул возможных подчиненных хостов для выбора в начале новой рабочей нагрузки только для чтения.

  • promoteSlaveToMaster(String host): Удаляет хост из пула потенциальных хостов для будущих процессов только для чтения (существующему процессу только для чтения позволяют продолжиться до завершения) и добавляет хост в пул потенциальных основных хостов.

  • removeSlaveHost(String host, boolean closeGently): Удаляет хост (совпадение имени хоста должно быть точным) из списка формируемых подчиненных, если closeGently = false, существующие связи, у которых есть этот хост, как в настоящее время активный, будут закрыты сразу (приложение должно ожидать исключения).

  • removeMasterHost(String host, boolean closeGently): Аналог removeSlaveHost(), но удаляет хост из списка мастер-хостов.

Некоторые полезные метрики управления включают:

  • getConnectionCountWithHostAsSlave(String host): Возвращает количество объектов ReplicationConnection, у которых есть данный хост, формируемый как возможный подчиненный.

  • getConnectionCountWithHostAsMaster(String host): Возвращает количество объектов ReplicationConnection, у которых есть данный хост, формируемый как возможный мастер-хост.

  • getNumberOfSlavesAdded(): Возвращает число раз, которое хост был динамически добавлен к пулу.

  • getNumberOfSlavesRemoved(): Возвращает число раз, которое хост был динамически удален из пула.

  • getNumberOfSlavePromotions(): Возвращает число раз, которое хост был продвинут до мастера.

  • getTotalConnectionCount(): Возвращает количество объектов ReplicationConnection, которые были зарегистрированы в этой группе.

  • getActiveConnectionCount(): Возвращает количество объектов ReplicationConnection в настоящее время управляемых этой группой.

ReplicationConnectionGroupManager

com.mysql.cj.jdbc.ha.ReplicationConnectionGroupManager обеспечивает доступ к группам соединения репликации, вместе с некоторыми служебными методами.

  • getConnectionGroup(String groupName): Вернет объект ReplicationConnectionGroup, соответствующий обеспеченному groupName.

Другие методы ReplicationConnectionGroupManager отражают ReplicationConnectionGroup за исключением того, что первый аргумент это название группы (String). Эти методы будут управлять на всем соответствии ReplicationConnectionGroups, что полезно для удаления сервера из обслуживания и цдаления его из всех имеющихся ReplicationConnectionGroups.

Эти методы могли бы быть полезны для управления хостами репликации в JVM, если применение вызывает изменения топографии. Для управления конфигурациями хоста снаружи JVM может использоваться JMX.

Применение JMX для управления хостами репликации

Когда Connector/J начат с ha.enableJMX=true и значение установлено для свойства replicationConnectionGroup, JMX MBean будет зарегистрирован, позволяя манипуляцию хостов репликации клиентом JMX. Интерфейс MBean определяется в com.mysql.cj.jdbc.jmx.ReplicationGroupManagerMBean и позволяет статические методы ReplicationConnectionGroupManager :

public abstract void addSlaveHost(String groupFilter, String host) throws SQLException;
public abstract void removeSlaveHost(String groupFilter, String host) throws SQLException;
public abstract void promoteSlaveToMaster(String groupFilter, String host) throws SQLException;
public abstract void removeMasterHost(String groupFilter, String host) throws SQLException;
public abstract String getMasterHostsList(String group);
public abstract String getSlaveHostsList(String group);
public abstract String getRegisteredConnectionGroups();
public abstract int getActiveMasterHostCount(String group);
public abstract int getActiveSlaveHostCount(String group);
public abstract int getSlavePromotionCount(String group);
public abstract long getTotalLogicalConnectionCount(String group);
public abstract long getActiveLogicalConnectionCount(String group);

9.5. Продвинутая конфигурация выравнивания нагрузки и отказоустойчивости

Connector/J обеспечивает полезное внедрение выравнивания нагрузки для MySQL Cluster или систем с несколькими мастер-хостами, как объяснено в разделе 9.3. Это же самое внедрение используется для балансирования нагрузки между подчиненными хостами только для чтения при репликации.

Пытаясь уравновесить рабочую нагрузку между многократными серверами, драйвер должен определить, когда безопасно менять серверы, так как такое действие, например, посреди транзакции может вызвать проблемы. Важно не потерять статус информацию. Поэтому Connector/J только попытается выбрать новый сервер, когда одно из следующего произойдет:

  1. На границах транзакции (транзакции явно переданы или отменены).

  2. При коммуникационном исключении (статус SQL, начинающийся с "08").

  3. Когда условия совпадения SQLException определяются пользователем, используя точки расширения, определенные свойствами loadBalanceSQLStateFailover, loadBalanceSQLExceptionSubclassFailover или loadBalanceExceptionChecker.

Третье условие обрабатывает три свойства, которые позволяют вам управлять триггером отказоустойчивости SQLException:

  • loadBalanceExceptionChecker: свойство loadBalanceExceptionChecker действительно ключ. Это берет полностью квалифицированное имя класса, который осуществляет новый интерфейс com.mysql.cj.jdbc.ha.LoadBalanceExceptionChecker. Этот интерфейс очень прост, и необходимо осуществить только следующий метод:

    public boolean shouldExceptionTriggerFailover(SQLException ex)
    

    SQLException передается, возвращается значение типа boolean. Значение true вызывает отказоустойчивость, false нет.

    Можно использовать это, чтобы осуществить собственную логику. Пример, где это могло бы быть полезно, имея дело со случайными ошибками, используя MySQL Cluster, где определенные буферы могут стать перегруженными. Следующий фрагмент кода иллюстрирует это:

    public class NdbLoadBalanceExceptionChecker extends
           StandardLoadBalanceExceptionChecker {
      public boolean shouldExceptionTriggerFailover(SQLException ex) {
        return super.shouldExceptionTriggerFailover(ex) ||
               checkNdbException(ex);
      }
      private boolean checkNdbException(SQLException ex) {
        // Have to parse the message since most NDB errors
        // are mapped to the same DEMC.
        return (ex.getMessage().startsWith("Lock wait timeout exceeded") ||
               (ex.getMessage().startsWith("Got temporary error") &&
               ex.getMessage().endsWith("from NDB")));
      }
    }
    

    Код выше расширяет com.mysql.cj.jdbc.ha.StandardLoadBalanceExceptionChecker , который является реализацией по умолчанию. Есть несколько удобных коротких путей, встроенных в это для тех, кто хочет иметь некоторый уровень контроля, используя свойства, не сочиняя код Java. Эта реализация по умолчанию использует два остающихся свойства: loadBalanceSQLStateFailover и loadBalanceSQLExceptionSubclassFailover .

  • loadBalanceSQLStateFailover: позволяет вам определять разграниченный запятой список кодовых префиксов SQLState, с которыми сравнивается SQLException. Если префикс соответствует, переключение вызывается. Так, например, следующее вызвало бы переключение, если данный SQLException начинается с "00" или с "12345":

    loadBalanceSQLStateFailover=00,12345
    
  • loadBalanceSQLExceptionSubclassFailover: может использоваться вместе с loadBalanceSQLStateFailover или самостоятельно. Если вы хотите, чтобы определенные подклассы SQLException вызывали переключение, просто предоставьте разграниченный запятой список полностью квалифицированного класса или интерфейсных имен, чтобы сравнить с ними. Например, если вы хотите, чтобы все SQLTransientConnectionExceptions вызывали переключение, вы определили бы:

    loadBalanceSQLExceptionSubclassFailover=java.sql.SQLTransientConnectionException
    

В то время как три условия отказоустойчивости перечислили большинство ситуаций, если autocommit включен, Connector/J никогда не балансирует повторно и продолжает использовать ту же самую физическую связь. Это может быть проблематично, особенно когда выравнивание нагрузки используется, чтобы распределить нагрузку только для чтения на много хостов. Однако Connector/J может формироваться, чтобы повторно балансировать после того, как определенное число запросов будет выполнено, когда включен autocommit. Эта функциональность зависит от следующих свойств:

  • loadBalanceAutoCommitStatementThreshold определяет количество соответствия запросов, которые вызовут драйвер, чтобы потенциально обменять физические связи сервера. Значение по умолчанию 0 сохраняет поведение, когда связи с включенным autocommit никогда не уравновешиваются.

  • loadBalanceAutoCommitStatementRegex регулярное выражение, которому должны соответствовать запросы. Значение по умолчанию: пустое. Соответствует всем запросам. Так, например, использование следующих свойств заставит Connector/J повторно балансировать после каждого третьего запроса, который содержит последовательность test:

    loadBalanceAutoCommitStatementThreshold=3
    loadBalanceAutoCommitStatementRegex=.*test.*
    

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

Поиск

 

Найди своих коллег!

Вы можете направить письмо администратору этой странички, Алексею Паутову. mailto:alexey.v.pautov@mail.ru