Tomcat jdbc在amazon multi-az故障转移期间停止

时间:2017-09-15 17:27:59

标签: java amazon-web-services tomcat jdbc amazon-rds

解决

最终,下面提到的类似机票中提到的解决方案为我们工作。当我们最初尝试它时,我们的配置解析器会破坏URL并从中删除& connectTimeout = 15000& socketTimeout = 60000,这使该测试无效。

我无法让tomcat jdbc连接池使用Amazon RDS故障转移到新的数据库服务器'多重功能。发生故障转移时,应用程序服务器会挂起,试图从池中借用连接。它与此问题类似,但是这个用户问题的解决方案对我没有帮助,所以我怀疑它并不完全相同:Configure GlassFish JDBC connection pool to handle Amazon RDS Multi-AZ failover 序列有点像这样:

  • 成功请求,按预期输出日志
  • 启动故障转移(通过RDS中的故障转移重启)
  • 请求超时,来自请求的日志消息按预期显示,直到从池中借用连接。
  • 后续请求不会生成任何日志消息,它们也会超时。
  • 经过一段时间后,守护程序最终会开始打印更多日志消息,就像它成功连接到数据库并执行操作一样。这可能需要16分钟才能完成,客户已经很久没有了。
  • 如果我等待大约50分钟并再次尝试,系统最终会再次接受连接。

备注

  • 如果我告诉tomcat关闭,日志中有异常关于它无法清理资源,以及我的servlet仍在处理请求。最值得注意的(在我看来)是以下堆栈跟踪,表明至少有一件事情在等待来自mysql的套接字上进行通信。

    java.net.SocketInputStream.socketRead0(Native Method)
    java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
    java.net.SocketInputStream.read(SocketInputStream.java:171)
    java.net.SocketInputStream.read(SocketInputStream.java:141)
    com.mysql.jdbc.util.ReadAheadInputStream.fill(ReadAheadInputStream.java:114)
    com.mysql.jdbc.util.ReadAheadInputStream.readFromUnderlyingStreamIfNecessary(ReadAheadInputStream.java:161)
    com.mysql.jdbc.util.ReadAheadInputStream.read(ReadAheadInputStream.java:189)
    com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:3116)
    com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3573)
    com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3562)
    com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4113)
    com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2570)
    com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2731)
    com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2812)
    com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2761)
    com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:894)
    com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:732)
    org.apache.tomcat.jdbc.pool.PooledConnection.validate(PooledConnection.java:441)
    org.apache.tomcat.jdbc.pool.PooledConnection.validate(PooledConnection.java:384)
    org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:716)
    org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:579)
    org.apache.tomcat.jdbc.pool.ConnectionPool.getConnection(ConnectionPool.java:174)
    org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:111)
    <...>
    
  • 如果我重新启动tomcat,它会在返回后立即恢复正常。显然,从长远来看,这可能不是维持正常运行时间的可行解决方案。

环境详情

  • 数据库:MySQL(使用mysql-connector-java 5.1.26)(服务器5.5.53)
  • Tomcat 8.0.45

在尝试解决此问题时,我对配置进行了多次更改。在撰写本文时,以下相关设置已经到位:

  • jre / lib / security / java.security - 我认为Oracle Java 1.8的默认值是30s,没有安全管理器。我将这些设置为零只是为了积极,这不是问题所在。
    • networkaddress.cache.ttl:0
    • networkaddress.cache.negative.ttl:0
  • 连接池设置
    • testOnBorrow:true
    • testOnConnect:true
    • testOnReturn:true
  • jdbc url参数
    • connectTimeout:60000
    • 了socketTimeout:60000
    • autoReconnect的:真

更新 仍未找到解决方案。
在日志记录中添加以确认这不是DNS缓存问题。在超时之前立即记录的IP地址与&#39; new&#39;的IP地址匹配。掌握RDS主机。

作为参考,以下块表示我用于初始化数据源的属性。我在代码而不是JNDI中配置池,从应用程序的配置文件中取出一些元素。我已粘贴下面的代码以及表明我一直在运行的测试的配置值的注释。

PoolProperties p = new PoolProperties();
p.setUrl(config.get("JDBC_URL"));  // jdbc:mysql://host:3306/dbname
p.setDriverClassName("com.mysql.jdbc.Driver");
p.setUsername(config.get("JDBC_USER"));
p.setPassword(config.get("JDBC_PASSWORD"));
p.setJmxEnabled(true);
p.setTestWhileIdle(false);
p.setTestOnBorrow(true);
p.setValidationQuery("SELECT 1");
p.setValidationInterval(30000);
p.setTimeBetweenEvictionRunsMillis(30000);
p.setMaxActive(Integer.parseInt(config.get("MAX_ACTIVE"))); //45
p.setInitialSize(10);
p.setMaxWait(5);
p.setRemoveAbandonedTimeout(Integer.parseInt(config.get("REMOVE_ABANDONED_TIMEOUT"))); //600
p.setMinEvictableIdleTimeMillis(Integer.parseInt(config.get("DB_EVICTION_TIMEOUT"))); //60000
p.setMinIdle(Integer.parseInt(config.get("DB_MIN_IDLE"))); //50
p.setLogAbandoned(Boolean.parseBoolean(config.get("LOG_ABANDONED"))); //true
p.setRemoveAbandoned(true);
p.setJdbcInterceptors(
   "org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"+
   "org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer;"+
   "org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer");
   // make sure new connections have auto commit true
p.setDefaultAutoCommit(true);

0 个答案:

没有答案