2012-12-03 39 views
5

Theo như tôi hiểu, các tham số "testOnBorrow" và "validationQuery" nằm ngay trên hẻm của tôi nhưng chúng dường như không hoạt động như mong đợi.Tự động kết nối lại ở hậu kỳ với hồ bơi tomcat và Spring

Tôi khởi động ứng dụng, chạy một số truy vấn và mọi thứ đều ổn. Sau đó, tôi khởi động lại máy chủ postgres - mà không cần khởi động lại tomcat - để kiểm tra DataSource có thể xử lý việc tái kết nối và tất cả tôi nhận được là:

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) 

Tôi đang sử dụng:

  • Xuân 3.1
  • PostgreSQL 9.2.1
  • Pool kết nối: org.apache.tomcat.jdbc.pool 7.0.25

My Spring bean conf iguration là như sau:

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

Bất kỳ ý tưởng nào?

Cảm ơn

Trả lời

1

Xác thực kết nối chỉ được thực hiện khi ban đầu được mượn từ hồ bơi. Ngay cả khi nó được kiểm tra trước mỗi truy vấn, vẫn có một khoảng thời gian giữa séc và truy vấn nơi kết nối có thể bị mất. Tất cả các truy vấn phải có một số hình thức xử lý ngoại lệ để đối phó với lỗi truy vấn - nói chung, xử lý xử lý kết nối kém, nhận một cái mới và thử lại truy vấn (nếu có thể).

Trong tiêu chuẩn JDBC có phương thức gọi lại là "connectionErrorOccurred", được gọi là bất cứ khi nào một cái gì đó như thế này xảy ra, nhưng tôi chưa quen với cách JDBC và Java hoạt động để biết cách sử dụng nó (hoặc thậm chí là nếu nó bao gồm trường hợp này).

Trong mọi trường hợp, thời gian CHỈ bạn có thể biết để sử dụng nếu kết nối tốt hay xấu là khi bạn cố gắng sử dụng và không có kết nối nào có thể tự động khắc phục vấn đề đó mà không sử dụng cuộc gọi tùy chỉnh để thực thi và truy vấn lại , sẽ phá vỡ "hợp đồng" JDBC thành một giao diện chuẩn.

1

Gần đây tôi có cùng một vấn đề khi muốn tự động kết nối lại nhóm kết nối JDBC Tomcat khi có mạng bị ngắt. Giống như bạn, tôi cũng tìm thấy testOnBorrow và validationInterval không thực hiện công việc cho tôi.

Cuối cùng tôi đã kết thúc việc tạo Lời khuyên xung quanh trên JdbcTemplate (chúng tôi sử dụng org.springframework.jdbc.core.JdbcTemplate của Spring) và thực hiện thử lại bên trong Lời khuyên.

cấu hình Spring trông như thế này:

lớp
<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> 

Các my.jdbc.adapter.JdbcRetryOnFailureAdvice trông như thế này:

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

Tôi có vấn đề tương tự. Tôi sử dụng Postgres 9.4. Spring 4 và Tomcat 8. Tôi giải quyết vấn đề với cấu hình 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> 

Tôi đã thử nghiệm. Nó hoạt động tốt!Tôi tắt Postgres, vì vậy tôi có Log như vậy:

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

Nhưng khi tôi bắt đầu postgres, mọi thứ đều tốt! Hai dòng này thực hiện mọi thứ để kết nối lại với cơ sở dữ liệu:

<property name="testOnBorrow" value="true" /> 
<property name="validationQuery" value="SELECT 1" /> 
Các vấn đề liên quan