2016-10-14 136 views
0

我已經與我的球衣REST應用中的長時間運行的問題,利用春節jdbcTemplate進行基本SELECTINSERTUPDATEDELETE查詢到我們的數據庫(我們使用DB2)連接被關閉。Spring的JdbcTemplate -

這個問題每隔幾天就會發生一次,所以我沒有一個錯誤內容的System.out(下次發生錯誤時我會包含一個截圖)。隔幾天左右,由於「連接已關閉」,我的REST服務中的部分查詢開始失敗。錯誤。每當我遇到這個錯誤時,我只需重新啓動tomcat應用程序服務器,問題就解決了幾天,直到它再次發生。

每隔幾天重新啓動一次服務器,一旦他們開始使用它,對我們的最終用戶來說將不是一個可以接受的解決方案。因此,如果任何人有任何想法,爲什麼發生這種情況,以及我怎麼能夠永久解決這個問題,請讓我知道。

這裏是我的春天數據源配置:

package com.my.package; 

import org.springframework.beans.factory.annotation.Qualifier; 
import org.springframework.boot.context.properties.ConfigurationProperties; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.context.annotation.Primary; 

import org.springframework.jdbc.core.JdbcTemplate; 
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder; 
import javax.sql.DataSource; 

@Configuration 
public class DataSourceConfig { 

    @Bean (name = "dataSource1") 
    @Primary 
    @ConfigurationProperties(prefix = "ds1.datasource") 
    public DataSource dataSource1() { 
     return DataSourceBuilder.create().build(); 
    } 

    @Bean(name = "ds1") 
    public JdbcTemplate jdbcTemplate1(@Qualifier("dataSource1") DataSource dataSource1) { 
     return new JdbcTemplate(dataSource1); 
    } 

    @Bean (name = "dataSource2") 
    @ConfigurationProperties(prefix="ds2.datasource") 
    public DataSource dataSource2() { return DataSourceBuilder.create().build(); } 

    @Bean(name = "ds2") 
    public JdbcTemplate jdbcTemplate2(@Qualifier("dataSource2") DataSource dataSource2) { 
     return new JdbcTemplate(dataSource2); 
    } 
} 

這裏是我的application.properties:

ds1.datasource.url=url1 
ds1.datasource.username=user1 
ds1.datasource.password=pass1 
ds1.datasource.driver-class-name=com.ibm.db2.jcc.DB2Driver 

ds2.datasource.url=url2 
ds2.datasource.username=user2 
ds2.datasource.password=pass2 
ds2.datasource.driver-class-name=com.ibm.db2.jcc.DB2Driver 

我的pom.xml在那裏我有春天JDBC和驅動程序的依賴性

<dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-jdbc</artifactId> 
</dependency> 
<dependency> 
    <groupId>ibm.db2</groupId> 
    <artifactId>db2jcc4.jar</artifactId> 
    <version>4.19.26</version> 
</dependency> 

最後,我使用jdbcTempla執行一個簡單的SELECT查詢的例子TE

@Autowired 
@Qualifier("ds1") 
private JdbcTemplate jdbcTemplate; 

List<Something> sampleQuery(){ 
    String sqlQuery = "SELECT * FROM TABLE"; 
    try { 
     return this.jdbcTemplate.query(
       sqlQuery, 
       (rs, rowNum) -> { 

        Something something = new Something(); 
        something.setVal1(rs.getString("FIELD1").trim()); 
        something.setVal2(rs.getString("FIELD2").trim()); 

        return something; 
       }); 
    }catch (Exception ex){ 
     ex.printStackTrace(); 
     System.out.println("error..."); 
     return new ArrayList<>(); 
    } 
} 

編輯:錯誤仍在進行之中。這次我能夠捕獲日誌。它基本上只是說「無法驗證新建立的連接」。我不知道爲什麼。

org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: Failed to validate a newly established connection. 
    at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:80) 
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:615) 
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:680) 
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:712) 
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:722) 
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:772) 
    at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(ResourceMethodInvocationHandlerFactory.java:81) 
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:144) 
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:161) 
    at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$TypeOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:205) 
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:99) 
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:389) 
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:347) 
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:102) 
    at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:326) 
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271) 
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267) 
    at org.glassfish.jersey.internal.Errors.process(Errors.java:315) 
    at org.glassfish.jersey.internal.Errors.process(Errors.java:297) 
    at org.glassfish.jersey.internal.Errors.process(Errors.java:267) 
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317) 
    at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305) 
    at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154) 
    at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:473) 
    at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:427) 
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:388) 
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:341) 
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:228) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) 
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) 
    at org.springframework.boot.actuate.autoconfigure.EndpointWebMvcAutoConfiguration$ApplicationContextHeaderFilter.doFilterInternal(EndpointWebMvcAutoConfiguration.java:261) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) 
    at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:115) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) 
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) 
    at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:87) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) 
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) 
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:121) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) 
    at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:103) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) 
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141) 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:522) 
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1095) 
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:672) 
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1502) 
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1458) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) 
    at java.lang.Thread.run(Thread.java:745) 
Caused by: java.sql.SQLException: Failed to validate a newly established connection. 
    at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:811) 
    at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:626) 
    at org.apache.tomcat.jdbc.pool.ConnectionPool.getConnection(ConnectionPool.java:185) 
    at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:127) 
    at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) 
    at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) 
    ... 81 more 

編輯#2:最後標誌着@ exoddus的答案正確的。在閱讀他的回答並查看他提供的Spring JDBC文檔(這使我瞭解了底層tomcat JDBC連接池文檔)之後,我開始使用許多不同的屬性,直到它正常工作。

這是當前的配置我在生產環境中使用:

ds1.datasource.url=jdbc:db2://database.domain.com:12345/DBMS 
ds1.datasource.username=admin 
ds1.datasource.password=admin 
ds1.datasource.driver-class-name=com.ibm.db2.jcc.DB2Driver 
ds1.datasource.max-active=200 
ds1.datasource.max-idle=200 
ds1.datasource.max-wait=20000 
ds1.datasource.min-idle=50 
ds1.datasource.test-while-idle=true 
ds1.datasource.test-on-borrow=true 
ds1.datasource.validation-query=SELECT 1 FROM SYSIBM.SYSDUMMY1 
ds1.datasource.time-between-eviction-runs-millis=30000 
ds1.datasource.remove-abandoned=true 
ds1.datasource.remove-abandoned-timeout=30 
ds1.datasource.abandon-when-percentage-full=50 
ds1.datasource.initial-size=50 
ds1.datasource.jdbcInterceptors=ResetAbandonedTimer 

重複的DS2。自從我大約6個月前實施這個配置以來,這種配置工作得很好。

+0

你使用連接池嗎? – Ralph

+0

我相信我呢?我覺得'spring-boot-starter-jdbc'使用tomcat-jdbc pooling作爲默認 – bscott

+0

,感謝6個月後的跟蹤,接受迴應並分享您的想法! – exoddus

回答

2

根據您的情況,我會嘗試配置DataSource beans的一些參數。也許在某些日子之後,你會失去聯繫,因爲其中一些從未被釋放或完成(我只是猜測)。

嘗試添加屬性您application.properties:

ds1.datasource.max-active=50 
ds1.datasource.max-idle=8 
ds1.datasource.max-wait=10000 
ds1.datasource.min-idle=4 
ds1.datasource.test-on-borrow=true 

同爲ds2

的正確值取決於你environtment /硬件。請看here,以獲得關於數據源和池的更好和簡明的解釋。

Here你可以在春天找到關於DataSource的另一個有趣的問題,它可以幫助你。

+0

另請參閱有關連接池的Spring Boot部分:http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-sql.html#boot-features-connect-生產數據庫 – Ralph

+0

謝謝,我現在將執行這些,看看這是否解決了這個問題。因爲「連接已關閉」通常需要1-3天。錯誤發生,我會等到下週五說錯誤發生 – bscott

+0

我更新了您提供的屬性的值並添加了更多內容:'ds1.datasource.validation-query =「SELECT 1 FROM SYSIBM.SYSDUMMY1」 '和'ds1.datasource.initial-size = 10'。同樣,自「連接已關閉」以來,這是很難驗證/測試的。問題每隔幾天出現一次。我將在本週的其餘時間繼續使用該應用程序。如果「連接已關閉」。問題不會在本週結束後出現,我會假設此解決方案起作用並將其標記爲正確答案。 – bscott

相關問題