首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >配置GlassFish JDBC连接池以处理Amazon多AZ故障转移

问配置GlassFish JDBC连接池以处理Amazon多AZ故障转移
EN

Stack Overflow用户
提问于 2014-07-25 14:55:34
回答 1查看 3K关注 0票数 5

我有一个运行在GlassFish中的Java应用程序,在EC2上运行,在Amazon上有一个MySQL数据库。我正在尝试将JDBC连接池配置为,以便在发生数据库故障转移时尽量减少停机时间。

在多AZ故障转移期间,我的当前配置无法正常工作,因为备用数据库实例似乎在几分钟内就可用(根据AWS控制台),而我的GlassFish实例在恢复工作之前仍然停留了很长一段时间(大约15分钟)。

连接池配置如下:

代码语言:javascript
复制
asadmin create-jdbc-connection-pool --restype javax.sql.ConnectionPoolDataSource \
--datasourceclassname com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource \
--isconnectvalidatereq=true --validateatmostonceperiod=60 --validationmethod=auto-commit \
--property user=$DBUSER:password=$DBPASS:databaseName=$DBNAME:serverName=$DBHOST:port=$DBPORT \
MyPool

如果我使用一个单AZdb.m1小实例,并且从控制台重新启动数据库,GlassFish将使中断的连接失效,抛出一些异常,然后在数据库可用时立即重新连接。在这个设置中,我得到不到1分钟的停机时间。

如果我使用Multidb.m1.小实例,并从AWS控制台使用故障转移重新启动,则没有任何例外。服务器完全停止,所有传入请求都会超时。15分钟后,我终于得到了这个:

代码语言:javascript
复制
Communication failure detected when attempting to perform read query outside of a transaction. Attempting to retry query. Error was: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

The last packet successfully received from the server was 940,715 milliseconds ago.  The last packet sent successfully to the server was 935,598 milliseconds ago.

似乎每个HTTP线程在无效连接上被阻塞而没有异常,因此没有机会执行连接验证。

在Multi-AZ的情况下,停机时间总是在15-16分钟之间,所以它看起来像是某种超时,但我无法改变它。

我尝试过但没有成功的事情:

  • 连接泄漏超时/回收
  • 语句泄漏超时/回收
  • 语句超时
  • 使用不同的验证方法
  • 使用MysqlDataSource而不是MysqlConnectionPoolDataSource

如何设置阻塞查询的超时,以便重新使用、验证和替换池中的连接?或者如何让GlassFish检测数据库故障转移?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-10-02 12:25:16

正如我之前评论的那样,这是因为打开并连接到数据库的套接字没有意识到连接已经丢失,所以它们一直保持连接,直到触发OS套接字超时,我读到这个超时通常需要30分钟。

为了解决这个问题,您需要覆盖JDBC连接字符串或JDNI Connection配置/属性中的套接字超时,以将socketTimeout param定义为更短的时间。

请记住,任何比定义的值更长的连接都将被终止,即使它正在被使用(我还无法确认这一点,这就是我所读到的)。

我在评论中提到的另外两个参数是connectTimeout和autoReconnect.

下面是我的JDBC连接字符串:

代码语言:javascript
复制
jdbc:(...)&connectTimeout=15000&socketTimeout=60000&autoReconnect=true 

我还禁用了Java的DNS缓存

代码语言:javascript
复制
 java.security.Security.setProperty("networkaddress.cache.ttl" , "0"); 
 java.security.Security.setProperty("networkaddress.cache.negative.ttl" , "0"); 

我这么做是因为Java不尊重TTL,并且当故障转移发生时,DNS是相同的,但是IP是变化的。

由于您使用的是Application,所以禁用DNS缓存的参数必须在使用-Dnet启动glassfish时传递给JVM,而不是应用程序本身。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24958610

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档