hibernate tomcat transactions sql-server-2012 connection-pooling

Connection Pool Empty Hibernate 4, pero no se puede encontrar el culpable



tomcat transactions (4)

Estoy monitoreando la base de datos SQL para las conexiones cada 5 minutos. Durante días oscilará alrededor de 5 conexiones (mi inactividad) y de repente estoy en 50. Obviamente, este es un problema recursivo porque no veo por qué saltaría de 5 a 50 en 5 minutos sin tráfico.

Estoy usando Hibernate 4 y Tomcat y sé de un problema en Hibernate que fue parchado en 4.3.2, pero estoy en 4.3.5

Más detalles: el evento vacío de la piscina ocurre todos los días exactamente a las 7:13:20 PM ... Suena demasiado automático. Estoy usando Quartz y se ejecuta cada 1 minuto, pero no puedo ver cómo están relacionados.

Mis propiedades:

jmxEnabled = true initialSize = 5 maxActive = 50 minIdle = 5 maxIdle = 25 maxWait = 10000 maxAge = 10 * 60000 timeBetweenEvictionRunsMillis = 5000 minEvictableIdleTimeMillis = 60000 validationQuery = "SELECT 1" validationQueryTimeout = 3 validationInterval = 15000 testOnBorrow = true testWhileIdle = true testOnReturn = false jdbcInterceptors = "ConnectionState" defaultTransactionIsolation = java.sql.Connection.TRANSACTION_READ_COMMITTED

Ambiente:

  • Tomcat 7.0.59
  • Actualización de java 1.7.0 76
  • SQL Server 2012

Más información: Reduje la frecuencia de trabajo de cuarzo a cada 5 minutos. El evento aún tuvo lugar cuando cargué una página / vista en la aplicación. Esto fue aproximadamente a las 7:14 PM. Estoy a punto de degradar para hibernar 3.

Actualización Hoy recargué la aplicación en Tomcat Manager a las 6:50 p. M., Pero el evento aún tuvo lugar. Volcado de hilo


Ah, ese tipo de insectos son divertidos. Obviamente, no hay forma de que podamos indicarle la falla exacta (excepto cuando alguien desenterra un error en las librerías que mencionó), así que veamos cómo puede depurar esto. Aproximadamente de fácil a difícil de hacer, aunque los detalles dependen de su entorno.

  1. Tiene información muy útil: el problema ocurre siempre al mismo tiempo. Esto sugiere dos opciones: cualquiera de sus trabajos que ejecuta con Quartz consume conexiones, o algo que está sucediendo en ese momento provocando que su código consuma conexiones. Obviamente, debe verificar las configuraciones de trabajo y los trabajos cron o trabajos configurados dentro de la base de datos o similares para posibles culpables. Tenga en cuenta que podrían comenzar bastante antes y llegar a ese estado crítico más adelante, por lo que el trabajo podría comenzar 2 horas antes por todo lo que sabemos.

  2. Verifique sus registros y los registros del sistema y los registros de la base de datos para detectar cualquier cosa que ocurra en ese momento o algún tiempo antes.

  3. Comprueba dos veces todo lo que recibe una conexión si siempre devuelve la conexión. Especialmente cuando se lanzan excepciones. Una manera clásica de fallar en eso es una construcción como esta (java como pseudo código):

    Connection con; try { con = getConnection(); Statement = stmnt = con.createStatement(); .... } finally (Exception ex){ if (stmnt != null) stmnt.close(); if (con != null) con.close(); // this will never happen if stmnt.close throws an exceptions }

  4. Establezca un registro que le permita ver cuándo exactamente no se devuelve la conexión. Todo lo que comience con algo en su aplicación debe pasar por algún tipo de envoltorio (AOP alrededor de Aspect, Filtro de servlet o similar). Ese contenedor debería hacer lo siguiente: crear una identificación única para la acción (UUID) y poner en el MDC de su marco de registro . Al final de la acción, esa identificación se elimina nuevamente. Todos los demás registros deberían incluir esa identificación. Envuelve tu grupo de conexión también. Mantenga un registro de cuándo algo solicitó una conexión, incluida la marca de tiempo, la identificación y posiblemente la pila de registro (creando y almacenando una excepción). Registra eso. Cada vez que se devuelve una conexión, registre la hora en que se usó. Además, cada vez que se solicita una conexión, verifique si se utiliza alguna conexión por más tiempo que un umbral.

  5. Aislar cosas: configure un segundo servidor, donde ejecuta la aplicación. ¿Tiene el mismo problema? Ejecutar algunas partes solo en uno de los dos servidores, ¿todavía tienen ambos el problema? Continúe excluyendo candidatos hasta que solo quede uno.


Si me enfrento a un problema así, haré todo lo posible para obtener un volcado de subprocesos cuando las conexiones de maxActive alcancen 50. Podría intentar aumentar este límite de maxActive para verificar si la aplicación tiene un pico más alto.

También configuraría Tomcat para usar un proveedor de grupo de conexiones como c3p0, si aún no se está utilizando. Luego crearía una clase de enlace personalizada como se describe en la siguiente sección: http://www.mchange.com/projects/c3p0/#connection_customizers

Con esta clase personalizada, mantenga un contador activo de las conexiones que se adquieren y liberan. Cuando este número está cerca o en el límite, inicie un volcado de subprocesos mediante programación. Esto se puede hacer como se describe en la siguiente página: http://crunchify.com/how-to-generate-java-thread-dump-programmatically/ Analice este volcado de hilo para verificar el origen de las conexiones.

Esta información no solo será útil para su problema actual, sino también para la resolución de problemas de rendimiento futuros.


Primero quiero agradecer a todos por contribuir con sus respuestas. Al igual que @JensSchauder había sugerido que estaba trabajando para tratar de aislar el problema. Me pregunto por qué no tuve el problema en QA, pero lo hice en producción.

A pesar de que seguí con mi equipo de operaciones de red, nadie lo acertó hasta que finalmente obtuve los registros que necesitaba.

Usamos un producto llamado Alert Logic para escanear e identificar vulnerabilidades de seguridad, pero lamentablemente no se descubrió que era el culpable hasta que pude rastrear los registros de acceso de Apache a una dirección IP. whois identificó la IP que se origina en el software Alert Logic de un host de Rackspace.

El servidor de aplicaciones era nuevo y consistía en una nueva imagen de arquitectura. Resultó que Alert Logic estaba atacando una vulnerabilidad. Esto luego condujo a un vaciado del grupo de conexión (¿achicar?)

Hasta mediados de la semana pasada, no tenía idea de que Alert Logic estuviera incluso en la ecuación. De hecho, ahora, estoy trabajando con operaciones de red para obtener una mejor observación del producto, ya que fue caducado.

Más adelante esta semana, publicaré los hallazgos de la vulnerabilidad mientras esté en QA (ya que parchear la producción era la prioridad).


Creé una herramienta de monitoreo de Pool de conexiones , llamada FlexyPool, y podría ayudarlo a encontrar al culpable. También es compatible con TomcatCP y puede correlacionar sus métricas con otros registros que esté utilizando actualmente,

El connection lease time histogram debería indicar cuánto tiempo se mantiene una conexión, lo que significa que es posible que tenga algunas consultas lentas.

El concurrent connections histogram le dice cuántas conexiones se utilizan en una y si tiene menos de 50, entonces tiene un problema de fuga de conexión.