Spring 使用 c3p0 数据库池和故障转移启动 JDBCTemplate
Spring Boot JDBCTemplate with c3p0 DataBase Pooling and failover
我需要在 SpringBoot 应用程序(嵌入式 tomcat)中为 ibatis 和使用 c3p0 进行连接的 jdbctemplate 建立数据库连接故障转移 pooling.Below 是我 applicaiton.I 的 applicaiton.properties有主要的和次要的 databases.If 主要失败然后次要应该用于运行时的数据库连接故障转移。请帮助我实现 this.I 试图将多个数据库 url 作为配置的一部分包含在内,但这是行不通的。
https://docs.genesys.com/Documentation/Composer/8.1.4/Help/ConnectionPooling
application.properties:(错误来了)
# connection properties for data source
##########################################################################################################
spring.datasource.c3p0.driverClass=oracle.jdbc.driver.OracleDriver
spring.datasource.c3p0.maxConnectionAge=3600
spring.datasource.c3p0.maxIdleTime=600
spring.datasource.c3p0.initialPoolSize=5
spring.datasource.c3p0.maxPoolSize=10
spring.datasource.c3p0.minPoolSize=5
spring.datasource.c3p0.acquireIncrement=1
##########################################################################################################
spring.datasource.url=jdbc:oracle:thin:@primary.com:1521:db1,jdbc:oracle:thin:@secondary.com:1521:db2
spring.datasource.username=user
spring.datasource.password=password
您需要定义 2 组属性并分别引用它们 - 请注意 url 键
中的区别
#set1
app.datasource.url=jdbc:mysql://localhost/test
app.datasource.username=dbuser
app.datasource.password=dbpass
app.datasource.pool-size=30
#set2
app.datasource.jdbc-url=jdbc:mysql://localhost/test
app.datasource.username=dbuser
app.datasource.password=dbpass
app.datasource.maximum-pool-size=30
但是如果您使用 JDBC 或 JPA 的默认自动配置,您可以将其中之一标记为 @Primary(然后任何 @Autowired 注入都会选择该配置)。
ref - Spring docs
@Bean
@Primary
@ConfigurationProperties(prefix="datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix="datasource.secondary")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
您也可以参考分步指南here。
据我所知,故障转移配置取决于 JDBC 驱动程序。对于 Oracle,您可以使用连接描述符对其进行配置。所以在你的情况下你会把它放在 tnsnames.ora
:
CONNECTION_WITH_FAILOVER =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = primary.com)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = secondary.com)(PORT = 1521))
(LOAD_BALANCE = no)
(FAILOVER = yes)
)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = db)
(FAILOVER_MODE =
(TYPE = select)
(METHOD = preconnect)
(RETRIES = 180)
(DELAY = 10)
)
)
)
然后在您的配置中:
spring.datasource.url=jdbc:oracle:thin:@CONNECTION_WITH_FAILOVER
当然,您可能没有或不想使用 tnsnames.ora
,在这种情况下,您可以使用连接描述符作为 JDBC 连接字符串的一部分:
spring.datasource.url=jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=primary.com)(PORT=1521))(ADDRESS=(PROTOCOL=TCP)(HOST=secondary.com)(PORT=1521))(LOAD_BALANCE=no)(FAILOVER=yes))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=db)(FAILOVER_MODE=(TYPE=select)(METHOD=preconnect)(RETRIES=180)(DELAY=10))))
有关连接描述符、tnsnames.ora
和为 Oracle DB 配置故障转移的更多详细信息,请参阅这些链接:
- Local Naming Parameters
- Oracle and OCI & JDBC connection strings
- TNS_ADMIN - 用于配置
tnsnames.ora
的位置
- Description of failover mode in Oracle DB (pdf) - 包含参数说明 FAILOVER_MODE
请注意,所有数据库上的服务名称必须相同,因此我将您的配置中的 db1
和 db2
替换为 db
.
如果您想要不同的服务名称,您必须以编程方式配置单独的数据源(如 Sheetal Mohan Sharma 所述)。
编辑:
- 您收到的错误表明您正在尝试连接到服务器上不存在的服务名称 - 更多 here
我今天更仔细地重新阅读了文档(特别是我上面链接的 PDF),似乎可以在连接字符串中指定辅助服务名称,所以在你的情况下输入 tnsnames.ora 将是:
CONNECTION_WITH_FAILOVER =
(说明 =
(ADDRESS_LIST =
(地址 =(协议 = TCP)(主机 = primary.com)(端口 = 1521))
(地址 =(协议 = TCP)(主机 = secondary.com)(端口 = 1521))
(LOAD_BALANCE = 否)
(故障转移 = 是)
)
(CONNECT_DATA =
(服务器 = 专用)
(SERVICE_NAME = db1)
(FAILOVER_MODE =
(类型 = select)
(方法 = 预连接)
(重试 = 180)
(延迟 = 10)
(备份 = db2)
)
)
)
作为 JDBC URL 在 application.properties:
spring.datasource.url=jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=primary.com)(PORT=1521))(ADDRESS=(PROTOCOL=TCP)(HOST=secondary.com)(PORT=1521))(LOAD_BALANCE=no)(FAILOVER=yes))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=db1)(FAILOVER_MODE=(TYPE=select)(METHOD=preconnect)(RETRIES=180)(DELAY=10)(BACKUP = db2))))
我目前没有配置这样的设置,所以我把它放在我的 tnsnames.ora:
CONNECTION_WITH_FAILOVER =
(说明 =
(ADDRESS_LIST =
(地址 =(协议 = TCP)(主机 = google.com)(端口 = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = my-actual-database)(PORT = my-db-port))
(LOAD_BALANCE = 否)
(故障转移 = 是)
)
(CONNECT_DATA =
(服务器 = 专用)
(SERVICE_NAME = 我的服务名称)
(FAILOVER_MODE =
(类型 = select)
(方法 = 预连接)
(重试 = 1)
(延迟 = 1)
)
)
)
模拟主连接失败(因为显然 google.com 上没有 Oracle DB 运行)并设法使用连接 URL 通过 DataGrip 连接到我的数据库:jdbc:oracle:thin:@CONNECTION_WITH_FAILOVER
我也直接在 JDBC URL:
中尝试使用连接描述符
jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=google.com)(PORT=1521))(ADDRESS=(PROTOCOL=TCP)(HOST=my-actual-database)(PORT=my-db-port))(LOAD_BALANCE=no)(FAILOVER=yes))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=my-service-name)(FAILOVER_MODE=(TYPE=select)(METHOD=preconnect)(RETRIES=1)(DELAY=5))))
它也能正常工作,虽然两次都需要相当长的时间才能建立连接(但这可能与我的网络配置或驱动程序的连接超时值有关)
- 确保配置
FAILOVER_MODE
参数以满足您的需要 - 特别考虑 RETIRES 和 DELAY 值 - 在我提供的示例中,我使用了 180 次重试和 10 秒重试之间的延迟,加上连接超时在每次重试时,驱动程序实际切换到故障转移连接可能需要很长时间。
我需要在 SpringBoot 应用程序(嵌入式 tomcat)中为 ibatis 和使用 c3p0 进行连接的 jdbctemplate 建立数据库连接故障转移 pooling.Below 是我 applicaiton.I 的 applicaiton.properties有主要的和次要的 databases.If 主要失败然后次要应该用于运行时的数据库连接故障转移。请帮助我实现 this.I 试图将多个数据库 url 作为配置的一部分包含在内,但这是行不通的。
application.properties:(错误来了)
# connection properties for data source
##########################################################################################################
spring.datasource.c3p0.driverClass=oracle.jdbc.driver.OracleDriver
spring.datasource.c3p0.maxConnectionAge=3600
spring.datasource.c3p0.maxIdleTime=600
spring.datasource.c3p0.initialPoolSize=5
spring.datasource.c3p0.maxPoolSize=10
spring.datasource.c3p0.minPoolSize=5
spring.datasource.c3p0.acquireIncrement=1
##########################################################################################################
spring.datasource.url=jdbc:oracle:thin:@primary.com:1521:db1,jdbc:oracle:thin:@secondary.com:1521:db2
spring.datasource.username=user
spring.datasource.password=password
您需要定义 2 组属性并分别引用它们 - 请注意 url 键
中的区别#set1
app.datasource.url=jdbc:mysql://localhost/test
app.datasource.username=dbuser
app.datasource.password=dbpass
app.datasource.pool-size=30
#set2
app.datasource.jdbc-url=jdbc:mysql://localhost/test
app.datasource.username=dbuser
app.datasource.password=dbpass
app.datasource.maximum-pool-size=30
但是如果您使用 JDBC 或 JPA 的默认自动配置,您可以将其中之一标记为 @Primary(然后任何 @Autowired 注入都会选择该配置)。
ref - Spring docs
@Bean
@Primary
@ConfigurationProperties(prefix="datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix="datasource.secondary")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
您也可以参考分步指南here。
据我所知,故障转移配置取决于 JDBC 驱动程序。对于 Oracle,您可以使用连接描述符对其进行配置。所以在你的情况下你会把它放在 tnsnames.ora
:
CONNECTION_WITH_FAILOVER =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = primary.com)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = secondary.com)(PORT = 1521))
(LOAD_BALANCE = no)
(FAILOVER = yes)
)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = db)
(FAILOVER_MODE =
(TYPE = select)
(METHOD = preconnect)
(RETRIES = 180)
(DELAY = 10)
)
)
)
然后在您的配置中:
spring.datasource.url=jdbc:oracle:thin:@CONNECTION_WITH_FAILOVER
当然,您可能没有或不想使用 tnsnames.ora
,在这种情况下,您可以使用连接描述符作为 JDBC 连接字符串的一部分:
spring.datasource.url=jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=primary.com)(PORT=1521))(ADDRESS=(PROTOCOL=TCP)(HOST=secondary.com)(PORT=1521))(LOAD_BALANCE=no)(FAILOVER=yes))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=db)(FAILOVER_MODE=(TYPE=select)(METHOD=preconnect)(RETRIES=180)(DELAY=10))))
有关连接描述符、tnsnames.ora
和为 Oracle DB 配置故障转移的更多详细信息,请参阅这些链接:
- Local Naming Parameters
- Oracle and OCI & JDBC connection strings
- TNS_ADMIN - 用于配置
tnsnames.ora
的位置
- Description of failover mode in Oracle DB (pdf) - 包含参数说明 FAILOVER_MODE
请注意,所有数据库上的服务名称必须相同,因此我将您的配置中的 db1
和 db2
替换为 db
.
如果您想要不同的服务名称,您必须以编程方式配置单独的数据源(如 Sheetal Mohan Sharma 所述)。
编辑:
- 您收到的错误表明您正在尝试连接到服务器上不存在的服务名称 - 更多 here
我今天更仔细地重新阅读了文档(特别是我上面链接的 PDF),似乎可以在连接字符串中指定辅助服务名称,所以在你的情况下输入 tnsnames.ora 将是:
CONNECTION_WITH_FAILOVER = (说明 = (ADDRESS_LIST = (地址 =(协议 = TCP)(主机 = primary.com)(端口 = 1521)) (地址 =(协议 = TCP)(主机 = secondary.com)(端口 = 1521)) (LOAD_BALANCE = 否) (故障转移 = 是) ) (CONNECT_DATA = (服务器 = 专用) (SERVICE_NAME = db1) (FAILOVER_MODE = (类型 = select) (方法 = 预连接) (重试 = 180) (延迟 = 10) (备份 = db2) ) ) )
作为 JDBC URL 在 application.properties:
spring.datasource.url=jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=primary.com)(PORT=1521))(ADDRESS=(PROTOCOL=TCP)(HOST=secondary.com)(PORT=1521))(LOAD_BALANCE=no)(FAILOVER=yes))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=db1)(FAILOVER_MODE=(TYPE=select)(METHOD=preconnect)(RETRIES=180)(DELAY=10)(BACKUP = db2))))
我目前没有配置这样的设置,所以我把它放在我的 tnsnames.ora:
CONNECTION_WITH_FAILOVER = (说明 = (ADDRESS_LIST = (地址 =(协议 = TCP)(主机 = google.com)(端口 = 1521)) (ADDRESS = (PROTOCOL = TCP)(HOST = my-actual-database)(PORT = my-db-port)) (LOAD_BALANCE = 否) (故障转移 = 是) ) (CONNECT_DATA = (服务器 = 专用) (SERVICE_NAME = 我的服务名称) (FAILOVER_MODE = (类型 = select) (方法 = 预连接) (重试 = 1) (延迟 = 1) ) ) )
模拟主连接失败(因为显然 google.com 上没有 Oracle DB 运行)并设法使用连接 URL 通过 DataGrip 连接到我的数据库:jdbc:oracle:thin:@CONNECTION_WITH_FAILOVER
我也直接在 JDBC URL:
中尝试使用连接描述符jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=google.com)(PORT=1521))(ADDRESS=(PROTOCOL=TCP)(HOST=my-actual-database)(PORT=my-db-port))(LOAD_BALANCE=no)(FAILOVER=yes))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=my-service-name)(FAILOVER_MODE=(TYPE=select)(METHOD=preconnect)(RETRIES=1)(DELAY=5))))
它也能正常工作,虽然两次都需要相当长的时间才能建立连接(但这可能与我的网络配置或驱动程序的连接超时值有关)
- 确保配置
FAILOVER_MODE
参数以满足您的需要 - 特别考虑 RETIRES 和 DELAY 值 - 在我提供的示例中,我使用了 180 次重试和 10 秒重试之间的延迟,加上连接超时在每次重试时,驱动程序实际切换到故障转移连接可能需要很长时间。