2015-04-14 3 views
15

Я запускаю приложение Spring Boot для создания REST apis. Часто я получаю сообщение о том, что соединение с базой данных закрыто, и после этого я не могу звонить в приложение. Я использую DB Postgres. Это полная трассировка стека:Postgres connection was closed error in Spring Boot

org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is javax.persistence.PersistenceException: org.hibernate.TransactionException: JDBC begin transaction failed: 
    at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:431) 
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373) 
    at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:457) 
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:276) 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) 
    at com.sun.proxy.$Proxy91.findByUriMoniker(Unknown Source) 
    at com.mypkg.businessobjects.OrderInfoBO.getOrderInfo(OrderInfoBO.java:76) 
    at com.mypkg.controller.OrderInfoController.getOrderInfo(OrderInfoController.java:78) 
    at sun.reflect.GeneratedMethodAccessor104.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:483) 
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221) 
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137) 
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110) 
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:777) 
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:706) 
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) 
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943) 
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877) 
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966) 
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:687) 
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) 
    at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85) 
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:130) 
    at com.mypkg.config.CORSFilter.doFilter(CORSFilter.java:39) 
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:60) 
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:132) 
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:60) 
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:132) 
    at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:85) 
    at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:61) 
    at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) 
    at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131) 
    at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:56) 
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) 
    at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:45) 
    at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:63) 
    at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:58) 
    at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:70) 
    at io.undertow.security.handlers.SecurityInitialHandler.handleRequest(SecurityInitialHandler.java:76) 
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) 
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) 
    at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:261) 
    at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:247) 
    at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:76) 
    at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:166) 
    at io.undertow.server.Connectors.executeRootHandler(Connectors.java:197) 
    at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:759) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
    at java.lang.Thread.run(Thread.java:745) 
Caused by: javax.persistence.PersistenceException: org.hibernate.TransactionException: JDBC begin transaction failed: 
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1763) 
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1677) 
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:1771) 
    at org.hibernate.jpa.internal.TransactionImpl.begin(TransactionImpl.java:64) 
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.beginTransaction(HibernateJpaDialect.java:159) 
    at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:380) 
    ... 56 more 
Caused by: org.hibernate.TransactionException: JDBC begin transaction failed: 
    at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doBegin(JdbcTransaction.java:76) 
    at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.begin(AbstractTransactionImpl.java:162) 
    at org.hibernate.internal.SessionImpl.beginTransaction(SessionImpl.java:1435) 
    at org.hibernate.jpa.internal.TransactionImpl.begin(TransactionImpl.java:61) 
    ... 58 more 
Caused by: org.postgresql.util.PSQLException: This connection has been closed. 
    at org.postgresql.jdbc2.AbstractJdbc2Connection.checkClosed(AbstractJdbc2Connection.java:833) 
    at org.postgresql.jdbc2.AbstractJdbc2Connection.getAutoCommit(AbstractJdbc2Connection.java:794) 
    at sun.reflect.GeneratedMethodAccessor35.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:483) 
    at org.apache.tomcat.jdbc.pool.ProxyConnection.invoke(ProxyConnection.java:126) 
    at org.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:108) 
    at org.apache.tomcat.jdbc.pool.DisposableConnectionFacade.invoke(DisposableConnectionFacade.java:81) 
    at com.sun.proxy.$Proxy56.getAutoCommit(Unknown Source) 
    at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doBegin(JdbcTransaction.java:68) 
    ... 61 more 

При перезагрузке приложения оно исчезает. Я думаю, что эта проблема возникает, когда я перезапускаю свою базу данных postgres. Почему это происходит?

ответ

9

Очень действительный вопрос, и эта проблема обычно встречается многими. Исключение обычно происходит, когда сетевое соединение теряется между пулом и базой данных (большую часть времени из-за перезапуска). Если посмотреть на трассировку стека, которую вы указали, совершенно ясно, что вы используете jdbc pool, чтобы получить соединение. JDBC pool имеет опции для тонкой настройки различных настроек пула подключений и сведений о том, что происходит внутри пула.

Вы можете обратиться к к detailed apache documentation on pool configuration указать отказаться от тайм-аут

Проверить removeAbandoned, removeAbandonedTimeout, logAbandoned параметры

Кроме того, вы можете использовать дополнительные свойства для дальнейшего ужесточения проверки достоверности

Используйте testXXX и validationQuery для достоверности подключения.

+2

Помогла ли это решение? У меня подобная проблема, но это мне не помогло. –

+0

@ Mark.ewd: если все еще релевантно, вы можете попробовать http://stackoverflow.com/a/33660586/56285 – Jonik

+0

В Spring Boot, если вы автоматически настраиваете источник данных, пул автоматически настраивается, если соответствующий драйвер используется класс (например, org.postgresql.Driver). Вы можете настроить объединение, предоставив следующие свойства в application.properties: spring.datasource.test-on-loan = true, spring.datasource.remove-abandoned = true, spring.datasource.validation-query = SELECT 1; –

1

У меня была точно такая же проблема, with this setup, также используя DataSource from Tomcat (org.apache.tomcat.jdbc.pool) для подключения к Heroku Postgres:

org.springframework.transaction.CannotCreateTransactionException: 
    Could not open JPA EntityManager for transaction 
org.hibernate.TransactionException: JDBC begin transaction failed: ] 
    with root cause 
org.postgresql.util.PSQLException: This connection has been closed. 

Что решил это для меня было добавив в код DataSource инициализации (заимствование из a Grails question):

dataSource.setTestOnBorrow(true); 
dataSource.setTestWhileIdle(true); 
dataSource.setTestOnReturn(true); 
dataSource.setValidationQuery("SELECT 1"); 

Я не уверен, что если все эти три необходимо, чтобы получить устойчивое соединение, возможно, не но имеющее все включено Proba bly не сильно больно.

В JavaDocs разъясняется, что происходит: см., Например, setTestOnBorrow(). Немного удивительно, возможно, что по умолчанию такие тесты не проводятся.

18

Это наполовину ответили на другие сообщения, и я хотел быть очень откровенным. Также я хотел быть более весенним-загрузочным. Не стесняйтесь изменять временные интервалы по мере необходимости.

Вариант 1: Вывести нарушенные соединения из бассейна.

Используйте эти свойства:

spring.datasource.test-on-borrow=true 
spring.datasource.validation-query=SELECT 1; 
spring.datasource.validation-interval=30000 

Вариант 2: Держите связь в бассейне живой.

Используйте эти свойства:

spring.datasource.test-while-idle=true 
spring.datasource.validation-query=SELECT 1; 
spring.datasource.time-between-eviction-runs-millis=60000 

Вариант 3: упреждающее выбросить неактивные соединения.

Используйте эти свойства (Примечание: Я не был в состоянии найти надежную документацию на этом для Spring загрузки также тайм-аут в секундах не миллисекунды.):

spring.datasource.remove-abandoned=true 
spring.datasource.remove-abandoned-timeout=60 

Днем загрузку!

+3

Spring Boot 1.4 делает несколько более ясным, что эти параметры специфичны для реализации объединения, так как они должны иметь префикс правильно (например, 'spring.datasource.tomcat',' spring.datasource.dbcp', 'spring.datasource. dbcp2', или 'spring.datasource.hikari') вместо просто' spring.datasource'. Ослабленная привязка Spring затем просто передаст их в базовую реализацию пула подключений. Проверьте документы для конкретного пула, для которого вы используете, для чего нужны правильные параметры конфигурации ... выше выглядят нормально для tomcat и dbcp, но hikari немного отличается. – sworisbreathing

0

У меня была такая же проблема, но в моем случае вышеупомянутые ответы не помогли. Я понял, что при выполнении длинного запроса появляется та же ошибка. В моем случае я назвал findAll (Iterable ids) и передал огромный список из более чем 100 000 идентификаторов. Разделение списка (например, использование ListUtils из Apache Commons или Google Guava) и вызов findAll() с меньшим количеством идентификаторов сделали трюк.

Смежные вопросы