Как настроить переход на отказ при восстановлении PostgreSQL Hot Standby в приложении JavaEE?

У меня есть два сервера Linux (A и B) с установленной базой данных PostgreSQL 9.5. Я настроил режим горячего режима ожидания, как описано в документации. В этой настройке A настраивается как ведущий, B в режиме горячего ожидания. Это работает хорошо и ведет себя так, как ожидалось.

Теперь я хочу подключить независимое приложение Java EE (работающее на другой машине) через Hibernate/JDBC через источник данных TomEE для этой базы данных.

В документации PostgreSQL указано, что в URL-адресе подключения jdbc указывается несколько хостов:

jdbc:postgresql://host1:port1,host2:port2/database

Итак, мои вопросы:

  • Если A выключено и B переключается вручную в обычный режим работы, мое приложение все еще может продолжить работу с базой данных с помощью URL-адреса соединения jdbc, как указано выше?
  • Нужно ли мне настраивать другие параметры/библиотеки?

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

РЕДАКТИРОВАТЬ-1:

Я решил протестировать pgBouncer (как предложено в комментариях) для обходного пути. Это хорошо работает для моего прецедента. Я написал сторожевой таймер script, который автоматизирует шаги руководства:

  • Непрерывно проверяйте, если A все еще жив и прослушивает входящие соединения.
  • В случае перехода на другой ресурс переключите B в обычный режим работы и позвольте ему стать новым мастером и перезапустите службу.
  • Измените настройки pgBouncer, чтобы указать B вместо A и перезапустить службу.

Тем не менее, меня все равно интересовало бы, если у кого-нибудь есть опыт без стороннего программного обеспечения?

Ответы

Ответ 1

В таких ситуациях лучше всего проверить и измерить.

У меня нет "практического" опыта работы с горячим режимом ожидания PostrgeSQL, но я сделал провал базы данных для Java-приложения.

Сначала проверьте требования на странице документации PostgreSQL о параметре ?targetServerType=master (см. внизу страницы).
Запишите небольшой класс Java "PgHsm" с основным методом, который использует драйвер PostgreSQL JDBC через DriverManager.getConnection и запускает простой запрос на обновление.
Он должен использовать сервер A для выполнения запроса на обновление. Остановите PostgreSQL на сервере A, запустите PgHsm: он не должен подключиться, поскольку сервер B не является мастером.
Сделать сервер B мастером, запустить PgHsm: он должен работать нормально.

Источник данных поддерживается пулом подключений к базе данных в TomEE. В этой странице перечислены те, которые доступны в TomEE. Но не все пулы подключения к базе данных равны, и теперь я предпочитаю HikariCP, потому что, по моему опыту, он более прогнозирует сценарий "вниз по базе данных". См. Также тест с результатами на странице HikariCP обработки базы данных вниз.

К сожалению, HikariCP использует JDBC get/setNetworkTimeout, чтобы вести себя предсказуемо и драйвер PostgreSQL JDBC не реализует это. Поэтому, чтобы потоки приложений (JavaEE) никогда не зависали при действии базы данных, вам необходимо установить параметры драйвера connectTimeout и socketTimeout JDBC. Установка socketTimeout нестабильна, так как она автоматически устанавливает ограничение времени для ВСЕХ запросов к базе данных.

Второй тест для выполнения включает обновление класса Java "PgHsm" для использования реализации пула соединений с базой данных по вашему выбору и запустить (по крайней мере) два потока, которые постоянно запускают простые запросы обновления в цикле (в цикле соединение с базой данных получается из пула и возвращается в пул после фиксации/откат). Пока вы сбрасываете сервер A и переключаете сервер B в "главный" режим, контролируете исключения, зарегистрированные в "PgHsm" , и как долго поток ожидает/зависает при выполнении действия базы данных.
Результаты тестов можно использовать для обновления параметров драйвера JDBC и настроек пула. Сосредоточьтесь на результатах, где:

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

Второй тест основан на том, что сервер A недоступен, так что запросы на проверку соединения (выполняемые пулом подключений к базе данных) терпят неудачу. В случае, когда оба сервера остаются доступными, но главный и подчиненный коммутаторы, запрос на проверку соединения не поможет и пул соединений с базой данных предоставит неправильные (теперь доступные только для чтения) подключения к базе данных приложения. В этом случае требуется ручное вмешательство. Здесь описывается "неудачный шаблон" для HikariCP здесь (доступно только с опцией allowPoolSuspension, описанной на странице configuration):

  • suspendPool()
  • softEvictConnections()
  • Подождите, пока activeConnections не перейдет в 0.
  • resumePool()

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