2009-12-11 23 views
8

En mi aplicación, Spring administra el grupo de conexiones para acceder a la base de datos. Hibernate usa estas conexiones para sus consultas. A primera vista, no tengo problemas con el grupo: funciona correctamente con clientes simultáneos y un grupo con una sola conexión. Puedo ejecutar muchas consultas, así que creo que yo (o Spring) no dejo conexiones abiertas.La conexión se bloquea después del tiempo de inactividad

Mi problema aparece después de un tiempo de inactividad (a veces 30 minutos, a veces más de 2 horas). Entonces, cuando Hibernate realiza una búsqueda, dura demasiado. Estableciendo el nivel log4j en TRACE, obtengo estos registros:

... 
18:27:01 DEBUG nsactionSynchronizationManager - Retrieved value [[email protected]] for key [[email protected]] bound to thread [http-8080-Processor24] 
18:27:01 DEBUG HibernateTransactionManager  - Found thread-bound Session [[email protected]] for Hibernate transaction 
18:27:01 DEBUG HibernateTransactionManager  - Using transaction object [org.springframework.orm.hi[email protected]1b2ffee] 
18:27:01 DEBUG HibernateTransactionManager  - Creating new transaction with name [com.acjoventut.service.GenericManager.findByExample]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT 
18:27:01 DEBUG HibernateTransactionManager  - Preparing JDBC Connection of Hibernate Session [[email protected]] 
18:27:01 TRACE SessionImpl      - setting flush mode to: AUTO 
18:27:01 DEBUG JDBCTransaction     - begin 
18:27:01 DEBUG ConnectionManager    - opening JDBC connection 

Aquí se congela durante aproximadamente 2 - 10 minutos. Pero luego continúa:

18:30:11 DEBUG JDBCTransaction     - current autocommit status: true 
18:30:11 DEBUG JDBCTransaction     - disabling autocommit 
18:30:11 TRACE JDBCContext      - after transaction begin 
18:30:11 DEBUG HibernateTransactionManager  - Exposing Hibernate transaction as JDBC transaction [jdbc:oracle:thin:@212.31.39.50:30998:orcl, UserName=DEVELOP, Oracle JDBC driver] 
18:30:11 DEBUG nsactionSynchronizationManager - Bound value [[email protected]] for key [[email protected]] to thread [http-8080-Processor24] 
18:30:11 DEBUG nsactionSynchronizationManager - Initializing transaction synchronization 
... 

Después de eso, funciona sin problemas, hasta otro período de inactividad. En mi humilde opinión, parece que el grupo de conexiones devuelve una conexión no válida/cerrada, y cuando Hibernate se da cuenta de eso, solicita otra conexión al grupo.

No sé cómo puedo solucionar este problema o las cosas que puedo hacer para delimitarlo. Cualquier ayuda para lograr esto será apreciada.

Gracias.

EDITAR: Bueno, finalmente se debió a una regla de firewall. La base de datos detecta que la conexión se ha perdido, pero el conjunto (dbcp o c3p0) no. Por lo tanto, intenta consultar la base de datos sin éxito. Lo que todavía me resulta extraño es que el tiempo de espera es muy variable. Tal vez la regla es especialmente extraña o el firewall no funciona correctamente. De todos modos, no tengo acceso a esa máquina y solo puedo esperar una explicación. :(

+0

¿Cómo identificó si se trataba de un problema de firewall? Me enfrenta a un problema similar donde dbcp se cuelga indefinidamente en mi transacción de Spring Batch y nunca regresa – YogendraJ

Respuesta

7

He tenido problemas como este antes cuando la base de datos está en una caja separada y hay un firewall entre ellos para agotar las conexiones inactivas.

En alguna circunst El firewall corta la conexión de tal forma que el extremo JDBC no detecta, y al intentar usarlo se produce un bloqueo indefinido.

En mi caso, se trataba de un grupo de conexiones personalizadas que enviaba una consulta de prueba por la conexión antes de devolverla desde el grupo. Configuré esta consulta de prueba para tener un tiempo de espera (usando Statement.setQueryTimeout) para que no se bloquee indefinidamente.

+0

No estoy seguro de por qué usaría un grupo personalizado para enviar solo una consulta de prueba. Un pequeño grupo de conexión decente y/o un origen de datos administrado por contenedor ya es capaz de esto. Lo mismo ocurre, por ejemplo, con DBCP y Tomcat JNDI. Consulte la documentación de configuración usando debajo de cada palabra clave 'validationQuery'. – BalusC

+0

Esto fue en un proyecto (hace mucho tiempo) que utilizaba un conjunto de conexiones a medida y estaba en la sección de código que efectivamente hacía algo similar a validationQuery en DBCP. – Joe

+0

Tienes razón. Parece que el problema es que alguna regla de firewall está fuera de mi control. Creo que las mejores soluciones serían cambiar el comportamiento del firewall. Gracias. – sinuhepop

1

Compruebe la configuración de la aplicación de la piscina. Por lo general, es Apache DBCPa timeout que tiene para cada conexión después de que la cerrará.

En su código, usted no debe tener conexiones alrededor. Conseguir uno, Úselo, ciérrelo inmediatamente. El grupo se asegurará de que esto no cueste demasiado.

+0

Spring administra mis conexiones, por lo que no soy yo quien debe llamar explícitamente a Connection.close(). ¿Soy yo? Como dices, estoy usando org.apache.commons.dbcp.BasicDataSource, con destroy-method = "cerrar". Investigaré sobre eso. – sinuhepop

+1

Hay otras dos fuentes de problemas: puede haber un firewall entre usted y el servidor de la base de datos (pero un tiempo de espera de 2 horas en las conexiones TCP inactivas es un poco corto). O su base de datos está configurada para cerrar conexiones inactivas después de un tiempo. Vea las otras opciones de configuración de DBCP para verificar conexiones inactivas y para hacer ping al DB en intervalos regulares para mantener la tubería abierta. –

+0

En cuanto a cierre: No, no debe cerrarlo, pero debe finalizar la transacción (lo que hará que Spring vea que la conexión puede devolverse al grupo). –

1

Una forma de resolver el problema del tiempo de inactividad es tener grupos de conexiones duales, uno está activo y el otro está en modo de espera (no se han creado conexiones todavía). Tener un temporizador con un tiempo de activación mucho menor que FIREWALL_IDLE_TIMEOUT y cambiar entre grupos de conexiones. Intenté esto y SU FUNCIONAMIENTO.

1

hay que añadir algunos parámetros de la fuente de datos:

más importante añadir testOnBorrow y validationQuery

1

Hemos resuelto un problema con síntomas similares que también resultaron ser causado por un firewall.

Hemos sido capaces de solucionar el problema cambiando la propiedad del grupo de conexiones testWhileIdle que evita que la conexión permanezca inactiva y que el firewall cierre la conexión. Ver Apache commons dbcp BasicDataSource. Aquí es una ejercen desde el archivo de configuración, persistentce-context.xml que solucionó el problema:

<property name="testWhileIdle"> 
    <value>true</value> 
</property> 
<property name="minEvictableIdleTimeMillis"> 
    <value>600000</value> 
</property> 
<property name="timeBetweenEvictionRunsMillis"> 
    <value>600000</value> 
</property> 

más probable es que sólo tenemos que añadir el testWhileIdle (false por defecto), pero añadimos las otras dos propiedades por si acaso .

En nuestro caso, aquí están algunos de los registros que estábamos viendo. Tenga en cuenta que en estos registros de depuración, tomará 16 minutos abrir la conexión antes de que se pueda usar la conexión y esto es lo que provocó que todo se cuelgue. No hubo errores que dificultaron el rastreo.

09-06-13 @ 16:36:34 [DEBUG] HibernateTransactionManager - Preparing JDBC Connection of Hibernate Session [[email protected]] 
09-06-13 @ 16:36:34 [DEBUG] ConnectionManager - opening JDBC connection 
09-06-13 @ 16:52:00 [DEBUG] DataSourceUtils - Setting JDBC Connection 
09-06-13 @ 16:52:00 [DEBUG] JDBCTransaction - begin 
09-06-13 @ 16:52:00 [DEBUG] JDBCTransaction - current autocommit status: true 
Cuestiones relacionadas