Один JDBC OracleDataSource/HikariCP с основной/резервной БД

Я пытаюсь настроить единый пул соединений, который ссылается на нашу основную базу данных до тех пор, пока она не станет неработоспособной, после чего пул выйдет из строя, заполняясь нашей резервной копией. До сих пор я использовал недокументированную функцию источников данных JNDI нашего сервера приложений, которая позволяет мне указать две строки URL-адреса соединения JDBC следующим образом:

jdbc:oracle:thin:@primary:1521:DB|jdbc:oracle:thin:@backup:1521:DB

У меня есть следующий код, который, без сомнения, частично взят из документации Hikari/Spring несколько месяцев назад.

@Bean(name = "dataSource")
public DataSource dataSource() throws SQLException {
    String userName = "user";
    String password = "pass";
    String server = "primary";
    String database = "DB";

    OracleDataSource ods = new OracleDataSource();
    ods.setServerName(server);
    ods.setDatabaseName(database);
    ods.setNetworkProtocol("tcp");
    ods.setUser(userName);
    ods.setPassword(password);
    ods.setPortNumber(1521);
    ods.setDriverType("thin");

    HikariConfig hkConfig = new HikariConfig();
    hkConfig.setDataSource(ods);
    hkConfig.setDataSourceClassName("oracle.jdbc.pool.OracleDataSource");
    hkConfig.setPoolName("springHikariRECPool");
    hkConfig.setMaximumPoolSize(15);
    hkConfig.setMinimumIdle(3);
    hkConfig.setMaxLifetime(1800000); // 30 minutes

    return new HikariDataSource(hkConfig);
}

Мой Google-Fu подвел меня. У кого-нибудь есть идеи о том, как добиться функциональности аварийного переключения?

Редактировать - повторно. @М. Deinum «Удалите конструкцию OracleDataSource и просто установите URL-адрес в HikariConfig».

HikariConfig hkConfig = new HikariConfig();
hkConfig.setUsername(userName);
hkConfig.setPassword(password);
hkConfig.setJdbcUrl("jdbc:oracle:thin:@primary:1521:DB|jdbc:oracle:thin:@backup:1521:DB");
hkConfig.setDataSourceClassName("oracle.jdbc.pool.OracleDataSource");
hkConfig.setPoolName("springHikariRECPool");
hkConfig.setMaximumPoolSize(15);
hkConfig.setMinimumIdle(3);
hkConfig.setMaxLifetime(1800000);

К сожалению, это дает довольно длинный стек, основа которого такова:

Caused by: java.sql.SQLException: Invalid Oracle URL specified: OracleDataSource.makeURL
    at oracle.jdbc.pool.OracleDataSource.makeURL(OracleDataSource.java:1277)
    at oracle.jdbc.pool.OracleDataSource.getConnection(OracleDataSource.java:185)
    at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:356)
    at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:199)
    at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:444)
    at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:515)

Исследование этого здесь - проблема с подключением Hikaricp Oracle и здесь - Указан неверный URL-адрес Oracle: OracleDataSource.makeURL заставляет меня добавить некоторые дополнительные свойства.

hkConfig.addDataSourceProperty("portNumber", "1521");
hkConfig.addDataSourceProperty("driverType", "thin");

Который сейчас бомбит с:

Caused by: java.net.UnknownHostException: null: Name or service not known
    at java.net.Inet6AddressImpl.lookupAllHostAddr(Native Method)
    at java.net.InetAddress$2.lookupAllHostAddr(InetAddress.java:928)
    at java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1323)
    at java.net.InetAddress.getAllByName0(InetAddress.java:1276)
    at java.net.InetAddress.getAllByName(InetAddress.java:1192)
    at java.net.InetAddress.getAllByName(InetAddress.java:1126)
    at oracle.net.nt.TcpNTAdapter.connect(TcpNTAdapter.java:117)
    at oracle.net.nt.ConnOption.connect(ConnOption.java:133)
    at oracle.net.nt.ConnStrategy.execute(ConnStrategy.java:370)

URL-адрес JDBC больше не используется. . . и, подтверждено - я взял строку подключения резервного копирования из URL-адреса и достиг того же исключения со стандартным подключением к одному серверу. Таким образом, кажется, что ODS требует настройки, как изначально сделано (или имитируется с помощью свойств).

В качестве последнего вздоха для этого метода я попытался установить для свойства serverName значение «primary | standby», и, как и ожидалось, это тоже взорвалось:

Caused by: java.net.UnknownHostException: primary|backup: Name or service not known
    at java.net.Inet6AddressImpl.lookupAllHostAddr(Native Method)
    at java.net.InetAddress$2.lookupAllHostAddr(InetAddress.java:928)
    at java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1323)
    at java.net.InetAddress.getAllByName0(InetAddress.java:1276)
    at java.net.InetAddress.getAllByName(InetAddress.java:1192)
    at java.net.InetAddress.getAllByName(InetAddress.java:1126)
    at oracle.net.nt.TcpNTAdapter.connect(TcpNTAdapter.java:117)
    at oracle.net.nt.ConnOption.connect(ConnOption.java:133)
    at oracle.net.nt.ConnStrategy.execute(ConnStrategy.java:411)
    ... 56 more

До сих пор я не заметил, что использую ojdbc7.jar.


person Jon Sampson    schedule 21.04.2017    source источник
comment
Удалите конструкцию OracleDataSource и просто установите URL-адрес HikariConfig.   -  person M. Deinum    schedule 21.04.2017
comment
Вопрос @M.Deinum обновлен в ответ. Спасибо за ваш вклад.   -  person Jon Sampson    schedule 24.04.2017


Ответы (1)


Используйте стандартный способ. Поддержка DataGuard, отказоустойчивость, RAC — это встроенная функция драйверов Oracle JDBC.

Сначала используйте tnsnames.ora, как описано здесь "Как подключить JDBC к tns oracle"

2-й использовать несколько хостов в tnsnames.ora:

DB =
(DESCRIPTION=
(ADDRESS_LIST=
  (LOAD_BALANCE=off)
  (FAILOVER=ON)
  (ADDRESS=(PROTOCOL=TCP)( HOST=primary)(PORT=1521))
  (ADDRESS=(PROTOCOL=TCP)( HOST=backup)(PORT=1521)))
(CONNECT_DATA=(SERVICE_NAME=DB)))

Драйвер Oracle JDBC подключится к хосту, где база данных «ОТКРЫТА» и присутствует служба с именем «БД».

PS: вы также можете передать всю строку подключения tns драйверу jdbc напрямую в качестве параметра.

url="jdbc:oracle:thin:@(DESCRIPTION=
  (LOAD_BALANCE=on)
   (ADDRESS_LIST=
   (ADDRESS=(PROTOCOL=TCP)(HOST=primary)(PORT=1521))
  (ADDRESS=(PROTOCOL=TCP)(HOST=secondary)(PORT=1521)))
  (CONNECT_DATA=(SERVICE_NAME=DB)))"
person ibre5041    schedule 21.04.2017
comment
Мне бы понравилась «простая» версия, которая не включает установку Oracle Client и т. Д., Но это, похоже, другой путь. Это промежуточное ПО или клиент. Спасибо! - person Jon Sampson; 24.04.2017