Mi aplicación web Java que ejecuta Tomcat (7.0.28) deja de responder periódicamente. Espero algunas sugerencias de posibles culpables (¿sincronización?), Así como quizás algunas herramientas recomendadas para recopilar más información sobre lo que ocurre durante un bloqueo. Algunos hechos que he acumulado:La aplicación web Java en tomcat se congela periódicamente
Cuando la aplicación web se congela, Tomcat sigue alimentando los hilos de solicitud en la aplicación, pero la aplicación no libera ellos. El grupo de subprocesos se llena hasta el máximo (actualmente 250), y las solicitudes subsiguientes fallan inmediatamente. Durante el funcionamiento normal, nunca hay más de 2 o 3 hilos activos.
No hay errores o excepciones de ningún tipo registradas en ninguno de los registros de Tomcat o de la aplicación web cuando ocurre el problema.
Al hacer una "Parada" y luego un "Inicio" en nuestra aplicación a través de la aplicación web de administración de tomcat resuelve inmediatamente este problema (hasta el día de hoy).
Últimamente la frecuencia ha sido dos o tres veces al día, aunque hoy ha sido mucho peor, probablemente 20 veces, y en ocasiones no vuelve a la vida inmediatamente.
El problema se produce sólo durante el horario comercial
El problema no se produce en nuestro sistema de estadificación
Cuando se produce el problema, el uso del procesador y la memoria en el servidor permanece plana (y bastante bajo) . Tomcat informa mucha memoria libre.
Tomcat sigue respondiendo cuando se produce el problema. La aplicación web de administración funciona perfectamente, y tomcat continúa enviando solicitudes a nuestra aplicación hasta que se llenen todos los hilos del grupo.
Nuestro servidor de base de datos sigue siendo receptivo cuando ocurre el problema. Utilizamos el marco Spring para el acceso e inyección de datos.
El problema generalmente ocurre cuando el uso es alto, pero nunca hay un aumento inusualmente alto en el uso.
Historial de problemas: algo similar ocurrió hace un año y medio. Después de muchos cambios en la configuración y el código del servidor, el problema desapareció hasta hace aproximadamente un mes. En las últimas semanas se ha producido con mucha más frecuencia, un promedio de 2 o 3 veces al día, a veces varias veces seguidas.
Identifiqué algún código de servidor hoy que puede no haber sido seguro para las hebras, y puse una solución para eso, pero el problema todavía está sucediendo (aunque con menos frecuencia). ¿Es este el tipo de problema que puede causar un código inseguro?
ACTUALIZACIÓN: Con varios mensajes que indican la conexión de base de datos de la piscina agotamiento, lo hice un poco de búsqueda en esa dirección y encontramos esta otra Stackoverflow question que explica casi todos los problemas que estoy experimentando.
Aparentemente, los valores predeterminados para las conexiones maxActive y maxIdle en la implementación BasicDataSource de Apache son cada 8. Además, maxWait se establece en -1, por lo que cuando se agota el grupo y entra una nueva solicitud de conexión, esperará para siempre sin registrar ningún tipo de excepción.Todavía voy a esperar a que este problema vuelva a suceder y realizar un volcado de jstack en la JVM para poder analizar esa información, pero parece que este es el problema. Lo único que no explica es por qué la aplicación a veces no se recupera de este problema. Supongo que las solicitudes simplemente se acumulan a veces y una vez que se atrasa nunca pueden ponerse al día.
ACTUALIZACIÓN II: me encontré con un jstack durante un accidente y se encontró cerca de 250 hilos (máximo) de los siguientes:
"http-nio-443-exec-294" daemon prio=10 tid=0x00002aaabd4ed800 nid=0x5a5d in Object.wait() [0x00000000579e2000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:485)
at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:1118)
- locked <0x0000000743116b30> (a org.apache.commons.pool.impl.GenericObjectPool$Latch)
at org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:106)
at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044)
at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111)
at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:573)
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.query(JdbcTemplate.java:718)
Para mi ojo no entrenado, esto parece bastante concluyente. Parece que el grupo de conexiones de la base de datos ha tocado su límite. Configuré un maxWait de tres segundos sin modificar maxActive y maxIdle solo para asegurarnos de comenzar a ver las excepciones registradas cuando el grupo se llena. Luego estableceré esos valores en algo apropiado y supervisaré.
ACTUALIZACIÓN III: Después de configurar maxWait, empecé a ver estos en mis registros, como se esperaba:
org.apache.commons.dbcp.SQLNestedException: Cannot get a connection, pool error Timeout waiting for idle object
at org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:114)
at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044)
at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111)
at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77)
he fijado maxActive a -1 (infinito) y maxIdle a 10. lo haré monitorear por un tiempo, pero mi suposición es que este es el final del problema.
'kill -3' es tu amigo. Ejecuta esto y mira el volcado de hilo. Es posible que desee consultar el Thread Dump Analyzer para obtener información agrupada (http://java.net/projects/tda/). –
mindas
Wild-guess sin ninguna otra información (¡necesita volcados de hilos!): Agotamiento del conjunto de conexiones DB. –
Esto es exactamente lo que me estaba pasando, la aplicación de aplicaciones creció demasiado, las conexiones máximas eran demasiado bajas y el tiempo de espera no se había definido, los hilos seguían acumulándose ahora y el servidor se congelaba. Aumento de contras máximos y establecer un tiempo específico en la espera máxima y ahora solo estoy monitoreando, pero el servidor funciona bien. Gracias por este mini tutorial. – Lauro182