2012-12-03 11 views
5

「testOnBorrow」と「validationQuery」のパラメータはわたしの路地にありますが、期待通りに動作していないようです。tomcatプールとSpringのポストグルで自動再接続

私はアプリケーションを起動し、いくつかのクエリを実行するとすべてが正常に行われます。 Tomcatを再起動せず - - それから私はpostgresのサーバを再起動して再接続を処理できるデータソースをテストするために、私が得るすべてはこれです:

This connection has been closed.; nested exception is org.postgresql.util.PSQLException: This connection has been closed. 
    at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:104) 
     at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72) 
     at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80) 
     at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80) 
     at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:603) 
     at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:637) 
     at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:666) 
     at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:674) 
    at org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.java:729) 

... 

Caused by: org.postgresql.util.PSQLException: This connection has been closed. 
    at org.postgresql.jdbc2.AbstractJdbc2Connection.checkClosed(AbstractJdbc2Connection.java:822) 
    at org.postgresql.jdbc3.AbstractJdbc3Connection.prepareStatement(AbstractJdbc3Connection.java:273) 
    at org.postgresql.jdbc2.AbstractJdbc2Connection.prepareStatement(AbstractJdbc2Connection.java:301) 
    at sun.reflect.GeneratedMethodAccessor38.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:601) 
    at org.apache.tomcat.jdbc.pool.ProxyConnection.invoke(ProxyConnection.java:126) 
    at org.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:99) 
    at org.apache.tomcat.jdbc.pool.interceptor.AbstractCreateStatementInterceptor.invoke(AbstractCreateStatementInterceptor.java:67) 
    at org.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:99) 
    at org.apache.tomcat.jdbc.pool.interceptor.ConnectionState.invoke(ConnectionState.java:153) 
    at org.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:99) 
    at org.apache.tomcat.jdbc.pool.TrapException.invoke(TrapException.java:41) 
    at org.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:99) 
    at org.apache.tomcat.jdbc.pool.DisposableConnectionFacade.invoke(DisposableConnectionFacade.java:63) 
    at $Proxy35.prepareStatement(Unknown Source) 
    at org.springframework.jdbc.core.JdbcTemplate$SimplePreparedStatementCreator.createPreparedStatement(JdbcTemplate.java:1436) 

私が使用しています:

  • 春3.1
  • 接続のPostgreSQLの9.2.1
  • プール:org.apache.tomcat.jdbc.pool 7.0.25

私のSpring Bean confにigurationは次のようになります。

public DataSource dataSource() { 
    org.apache.tomcat.jdbc.pool.DataSource dataSource = new org.apache.tomcat.jdbc.pool.DataSource(); 
    // from properties file 
    dataSource.setDriverClassName(environment 
      .getProperty("datasource.driver")); 
    dataSource.setUrl(environment.getProperty("datasource.url")); 
    dataSource.setUsername(environment.getProperty("datasource.username")); 
    dataSource.setPassword(environment.getProperty("datasource.password")); 
    // other configurations 
    dataSource.setInitialSize(10); 
    dataSource.setMinIdle(10); 
    dataSource.setMaxIdle(100); 
    dataSource.setMaxActive(100); 
    dataSource.setDefaultAutoCommit(true); 
    dataSource.setMaxWait(6000); 
    dataSource.setJmxEnabled(true); 
    dataSource 
      .setJdbcInterceptors("....ConnectionState;.....StatementFinalizer"); 
    dataSource.setRemoveAbandoned(true); 
    dataSource.setRemoveAbandonedTimeout(10); 
    dataSource.setLogAbandoned(true); 
    dataSource.setTestOnBorrow(true); 
    dataSource.setTestOnReturn(false); 
    dataSource.setTestWhileIdle(false); 
    dataSource.setUseEquals(false); 
    dataSource.setFairQueue(false); 
    dataSource.setTimeBetweenEvictionRunsMillis(30000); 
    dataSource.setMinEvictableIdleTimeMillis(30000); 
    dataSource.setValidationInterval(1800000); 
    dataSource.setValidationQuery("SELECT 1"); 

    return dataSource; 
} 

それが最初にプールから借用されたときに、接続の

答えて

1

検証のみが行われ

感謝。すべてのクエリの前にチェックされていても、チェックとクエリの間に接続が失われる可能性のある期間が残っています。すべてのクエリには、一般に、不正な接続ハンドルを破棄し、新しいものを取得し、可能であればクエリを再試行するなど、何らかの形での例外処理が必要です。

JDBC標準では、このようなことが起きるたびに呼び出されるコールバックメソッド「connectionErrorOccurred」がありますが、JDBCとJavaがどのように使用するかを知っています(またはこのケースをカバーしている場合)。

いずれの場合でも、接続が良好か悪いかを知ることができるのは、その接続を使用しようとするときだけで、クエリの実行と再試行のカスタム呼び出しを使用しないと自動的にその問題を解決することはできませんこれは、JDBCの「契約」を標準インタフェースに壊すことになります。

1

私は最近、ネットワークドロップが発生したときにTomcat JDBC接続プールを自動的に再接続したいという同じ問題を抱えています。あなたと同じく、私はtestOnBorrowとvalidationIntervalが私の仕事をしていないことも発見しました。

JdbcTemplateのAround Advice(Springのorg.springframework.jdbc.core.JdbcTemplateを使用しています)を作成し、Adviceの中で再試行しました。

Spring構成は次のようになります。

<bean id="jdbcRetryOnFailureAdvice" class="my.jdbc.adapter.JdbcRetryOnFailureAdvice"> 
    <property name="maxRetriesOnConnDrop" value="5"/> 
    <property name="retryWaitInMillis" value="5000"/> 
    <property name="sqlStatesToRetry" value="08003 08001 57P01"/> 
</bean> 

<aop:config proxy-target-class="true"> 
    <aop:aspect id="jdbcRetryOnUpdate" ref="jdbcRetryOnFailureAdvice"> 
     <aop:pointcut id="retryUpdatePointCut" 
         expression="execution(* 
         org.springframework.jdbc.core.JdbcTemplate.update(..))"/> 
     <aop:around pointcut-ref="retryUpdatePointCut" 
         method="retryOnFailure"/> 
    </aop:aspect> 
</aop:config> 

my.jdbc.adapter.JdbcRetryOnFailureAdviceクラスは次のようになります。

public class JdbcRetryOnFailureAdvice { 

    private int maxRetriesOnConnDrop = 0; 

    private long retryWaitInMillis = 1000; 

    public Object retryOnFailure(ProceedingJoinPoint jp) throws Throwable { 
     Object result = null; 
     int retryCount = 0; 
     do { 
      try { 
       Object[] args = jp.getArgs(); 
       if (args != null && args.length > 0) 
        result = jp.proceed(jp.getArgs()); 
       else 
        result = jp.proceed(); 
       break; 
      } catch (DataAccessResourceFailureException ex) { 
       if (retryCount < maxRetriesOnConnDrop) { 
        LOG.warn("Retrying...(retryCount=" + retryCount + ")"); 
        sleep(retryWaitInMillis); 
       } else { 
        throw ex; 
       } 
      } 
      retryCount++; 
     } while (retryCount <= maxRetriesOnConnDrop); 
     return result; 
    } 
} 
0

私は同様の問題を抱えています。私はPostgres 9.4を使用します。 Spring 4とTomcat 8. Springの設定で問題を解決します。

<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource" destroy-method="close"> 
    <property name="initialSize" value="10" /> 
    <property name="maxActive" value="25" /> 
    <property name="maxIdle" value="20" /> 
    <property name="minIdle" value="10" /> 
    <property name="driverClassName" value="org.postgresql.Driver" /> 
    <property name="url" value="${database.url}" /> 
    <property name="username" value="${database.username}" /> 
    <property name="password" value="${database.password}" /> 
    <property name="testOnBorrow" value="true" /> 
    <property name="validationQuery" value="SELECT 1" /> 
</bean> 

私はテストしました。うまくいく!私はPostgresの電源を切りますので、私は、このようなログを持っている:

Caused by: java.net.ConnectException: Connection refused: connect 
    at java.net.DualStackPlainSocketImpl.connect0(Native Method) 

しかし、私はpostgresのを起動すると、すべてが順調です!この2行は、データベースに再接続するためにすべてを行います。

<property name="testOnBorrow" value="true" /> 
<property name="validationQuery" value="SELECT 1" /> 
関連する問題