5

私が理解している限り、「testOnBorrow」パラメーターと「validationQuery」パラメーターは私の路地のすぐ上にありますが、期待どおりに機能していないようです。

アプリケーションを起動し、いくつかのクエリを実行すると、すべてがうまくいきます。次に、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

私のSpringBeanの構成は次のとおりです。

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;
}

何か案が?

ありがとう

4

3 に答える 3

1

接続の検証は、最初にプールから借用されたときにのみ行われます。すべてのクエリの前にチェックされたとしても、チェックとクエリの間に接続が失われる可能性のある期間があります。すべてのクエリには、クエリの失敗に対処するための何らかの形式の例外処理が必要です。一般に、不良な接続ハンドルを破棄し、新しい接続ハンドルを取得し、(可能であれば) クエリを再試行します。

JDBC標準には、このようなことが発生するたびに呼び出されることになっている「connectionErrorOccurred」のコールバックメソッドがありますが、JDBCとJavaがどのように機能するかを十分に理解していないため、その使用方法を知ることができません(または、これをカバーしていても)場合)。

いずれにせよ、接続が良いか悪いかを知ることができるのは、それを使用しようとするときだけであり、クエリを実行して再試行するためのカスタム呼び出しを使用しない限り、接続プールがその問題を自動的に克服することはできません。標準インターフェースへの JDBC「コントラクト」。

于 2012-12-13T22:03:06.657 に答える
1

同様の問題があります。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" />
于 2015-09-07T11:22:58.457 に答える
1

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

最後に、JdbcTemplate (Spring の org.springframework.jdbc.core.JdbcTemplate を使用) でアラウンド アドバイスを作成し、アドバイス内で再試行します。

春の設定は次のようになります。

<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;
    }
}
于 2013-07-24T01:22:45.787 に答える