Sun*_*amy 27 debugging logging tomcat log4j connection-pooling
我正在使用Tomcat JDBC连接池以及Spring启动,JDBC模板和SQL Server.当应用程序等待数据库连接时,我需要知道连接池内部的内容.如....
有没有办法通过调试或使用log4j等日志框架来获取这些信息?
任何想法将不胜感激.
Sun*_*amy 37
经过大量的研究,我能够找到3种方法来记录和监控数据库连接池.
https://tomcat.apache.org/tomcat-8.0-doc/jdbc-pool.html
使用Spring Boot 属性进行监视.
使用JMX(Java Management Extensions)进行监控(如@nitin建议的那样)
使用Spring Aspects进行监控.
第一种方式:使用Spring Boot属性进行监控.
我发现下面的Spring引导属性对于记录和监视数据库连接池非常有用.
这些属性(以及更多属性)没有记录.有关详细信息,请参阅下面的github问题. 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
Run Code Online (Sandbox Code Playgroud)
此列表包含更多仅与数据源相关的属性.(取自上面的链接)
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
Run Code Online (Sandbox Code Playgroud)
第二种方式:使用JMX进行监控(Java Management Extensions)
Tomcat JDBC池提供了一个MBean,即ConnectionPoolMBean.
Spring Boot自动注册JMX MBean.因此,无需将此MBean注册/导出到MBean服务器.只需打开JDK附带的JConsole,打开,在Windows->命令提示符 - > jconsole,就是这样.有关详情,请参阅下面的屏幕截
每当连接被放弃,连接失败,查询花费很长时间等时,此MBean也会通知.请参阅下面的屏幕截图.
第三种方式:使用Spring方面进行监控(仅适用于开发/ QA环境).
我使用此方面来记录TomcatJdbc连接池.
我创建了一个Spring Aspect,它将拦截每个数据库调用.这肯定会影响性能.
因此,在开发/ QA环境中使用此方面,在不需要时注释掉此方法(例如:在生产部署期间).
@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();
}
Run Code Online (Sandbox Code Playgroud)
现在,您可以轻松识别在应用程序中创建连接泄漏的特定数据库调用.
感谢@Sundararaj Govindasamy 的精彩回答。基于它,我在我的 Spring Boot 应用程序中创建了一个组件来调试我的数据库池信息。
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()));
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
30846 次 |
| 最近记录: |