tutorial example conexiones debugging tomcat logging log4j connection-pooling

debugging - example - ¿Cómo depurar/registrar las conexiones del grupo de conexiones JDBC de Tomcat?



tomcat jdbc tutorial (2)

Estoy usando el grupo de conexiones JDBC de Tomcat junto con el arranque Spring, la plantilla JDBC y el servidor SQL. Necesito saber qué ocurre dentro del grupo de conexiones mientras la aplicación está esperando la conexión de la base de datos. Como....

  • No de conexiones activas.
  • No de conexiones inactivas
  • No de conexiones bloqueadas, información adicional de por qué esta conexión está bloqueada
  • No de conexiones disponibles.
  • y ...

¿Hay alguna forma de obtener esta información mediante la depuración o el uso de marcos de registro como log4j?

Cualquier idea será apreciada.


Después de mucha investigación, puedo encontrar 3 formas de registrar y monitorear el conjunto de conexiones de la base de datos.

https://tomcat.apache.org/tomcat-8.0-doc/jdbc-pool.html

  1. Monitoreo usando las propiedades de Spring Boot .

  2. Monitoreo usando JMX (Java Management Extensions) (como se sugiere @nitin)

  3. Monitorización utilizando Spring Aspects .

1st Way: Monitoreo usando las propiedades Spring Boot.

Encontré a continuación las propiedades de arranque de Spring que serán muy útiles para registrar y monitorear el conjunto de conexiones de la base de datos.

Estas propiedades (y algunas más también) no fueron documentadas . Por favor, consulte más abajo el tema de github para más detalles. https://github.com/spring-projects/spring-boot/issues/1829

#Maximum no.of active connections spring.datasource.max-active=10 #Log the stack trace of abandoned connection spring.datasource.log-abandoned=true #Remove abandoned connection,So, new connection will be created and made available to threads which are waiting for DB connection spring.datasource.remove-abandoned=true #If any connection is not used for 10 seconds, consider that connection as "abandoned" spring.datasource.remove-abandoned-timeout=10 #Number of ms to wait before throwing an exception if no connection is available. spring.datasource.max-wait=1000

Esta lista contiene más propiedades relacionadas con la fuente de datos solamente (tomadas del enlace anterior)

spring.datasource.abandon-when-percentage-full spring.datasource.access-to-underlying-connection-allowed spring.datasource.alternate-username-allowed spring.datasource.auto-commit spring.datasource.catalog spring.datasource.commit-on-return spring.datasource.connection-customizer spring.datasource.connection-customizer-class-name spring.datasource.connection-init-sql spring.datasource.connection-init-sqls spring.datasource.connection-properties spring.datasource.connection-test-query spring.datasource.connection-timeout spring.datasource.data-source spring.datasource.data-source-class-name spring.datasource.data-source-j-n-d-i spring.datasource.data-source-properties spring.datasource.db-properties spring.datasource.default-auto-commit spring.datasource.default-catalog spring.datasource.default-read-only spring.datasource.default-transaction-isolation spring.datasource.driver-class-loader spring.datasource.fair-queue spring.datasource.idle-timeout spring.datasource.ignore-exception-on-pre-load spring.datasource.init-s-q-l spring.datasource.initialization-fail-fast spring.datasource.isolate-internal-queries spring.datasource.jdbc-interceptors spring.datasource.jdbc-url spring.datasource.jdbc4-connection-test spring.datasource.leak-detection-threshold spring.datasource.log-abandoned spring.datasource.log-validation-errors spring.datasource.log-writer spring.datasource.login-timeout spring.datasource.max-age spring.datasource.max-lifetime spring.datasource.max-open-prepared-statements spring.datasource.maximum-pool-size spring.datasource.metrics-tracker-class-name spring.datasource.minimum-idle spring.datasource.num-tests-per-eviction-run spring.datasource.pool-name spring.datasource.pool-prepared-statements spring.datasource.pool-properties spring.datasource.propagate-interrupt-state spring.datasource.read-only spring.datasource.record-metrics spring.datasource.register-mbeans spring.datasource.remove-abandoned spring.datasource.remove-abandoned-timeout spring.datasource.rollback-on-return spring.datasource.suspect-timeout spring.datasource.test-on-connect spring.datasource.thread-factory spring.datasource.transaction-isolation spring.datasource.use-disposable-connection-facade spring.datasource.use-equals spring.datasource.use-lock spring.datasource.validation-interval spring.datasource.validation-query-timeout spring.datasource.validator spring.datasource.validator-class-name spring.datasource.xa spring.datasource.xa.data-source-class-name spring.datasource.xa.properties

2nd Way: Monitoreo usando JMX (Java Management Extensions)

El grupo JDBC de Tomcat proporciona un MBean, a saber, ConnectionPoolMBean.

https://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/tomcat/jdbc/pool/jmx/ConnectionPoolMBean.html

Spring Boot registra JMX MBeans automáticamente. Por lo tanto, no es necesario registrar / exportar este MBean al servidor de MBean. Simplemente abra el JConsole que viene con JDK, para abrir, en Windows -> Símbolo del sistema -> jconsole, eso es todo. Consulte la siguiente captura de pantalla para obtener más información.

Este MBean también notifica cada vez que se abandona una conexión, falla la conexión, cuando una consulta lleva mucho tiempo, etc. Consulte la captura de pantalla a continuación.

3ª vía: Monitoreo usando Spring Aspects (solo para entornos de desarrollo / control de calidad).

Uso este aspecto para registrar el grupo de conexiones de TomcatJdbc.

Creé un Aspecto Spring que interceptará cada llamada a la base de datos. Esto seguramente afectará el rendimiento .

Entonces, use este aspecto en el entorno de desarrollo / control de calidad, comente este método cuando no sea necesario (por ejemplo: durante la implementación de producción).

@Before("execution(* com.test.app.db.dao.*.*(..))") public void logBeforeConnection(JoinPoint jp) throws Throwable { String methodName = ""; methodName += jp.getTarget().getClass().getName(); methodName += ":"; methodName += jp.getSignature().getName(); logger.info("before method call : " + methodName + " : number of connections in use by the application (active) : "+ tomcatJdbcPoolDataSource.getNumActive()); logger.info("before method call : " + methodName + " : the number of established but idle connections : "+ tomcatJdbcPoolDataSource.getNumIdle()); logger.info("before method call : " + methodName + " : number of threads waiting for a connection : "+ tomcatJdbcPoolDataSource.getWaitCount()); } @After("execution(* com.test.app.db.dao.*.*(..)) ") public void logAfterConnection(JoinPoint jp) throws Throwable { String methodName = ""; methodName += jp.getTarget().getClass().getName(); methodName += ":"; methodName += jp.getSignature().getName(); logger.info("after method call : " + methodName + " : number of connections in use by the application (active) : "+ tomcatJdbcPoolDataSource.getNumActive()); logger.info("after method call : " + methodName + " : the number of established but idle connections : "+ tomcatJdbcPoolDataSource.getNumIdle()); logger.info("after method call : " + methodName + " : number of threads waiting for a connection : "+ tomcatJdbcPoolDataSource.getWaitCount()); //tomcatJdbcPoolDataSource.checkAbandoned(); }

Ahora, puede identificar fácilmente la llamada a la base de datos en particular que crea una pérdida de conexión en su aplicación.


Gracias a @Sundaraj Govindasamy por una gran respuesta. Sobre esta base, creé un componente en mi aplicación Spring Boot para depurar la información de mi grupo de bases de datos.

import org.apache.tomcat.jdbc.pool.DataSource; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Aspect @Component public class DataSourceAspectLogger { protected final Logger logger = LoggerFactory.getLogger(this.getClass()); @Autowired private DataSource ds; @Before("execution(* br.com.foo.core.repository.*.*(..))") public void logBeforeConnection(JoinPoint jp) throws Throwable { logDataSourceInfos("Before", jp); } @After("execution(* br.com.foo.core.repository.*.*(..)) ") public void logAfterConnection(JoinPoint jp) throws Throwable { logDataSourceInfos("After", jp); } public void logDataSourceInfos(final String time, final JoinPoint jp) { final String method = String.format("%s:%s", jp.getTarget().getClass().getName(), jp.getSignature().getName()); logger.info(String.format("%s %s: number of connections in use by the application (active): %d.", time, method, ds.getNumActive())); logger.info(String.format("%s %s: the number of established but idle connections: %d.", time, method, ds.getNumIdle())); logger.info(String.format("%s %s: number of threads waiting for a connection: %d.", time, method, ds.getWaitCount())); } }