连接池-何时获取连接?何时归还连接?

373 阅读3分钟

说明

本文主要是讲事务何时获取连接?何时归还连接?

框架:spring,hibernate,dbcp。

事务拦截器准备工作

准备执行service类的事务业务方法,执行之前,先被事务拦截器拦截。

调用栈

borrowObject:1059, GenericObjectPool (org.apache.commons.pool.impl) //从连接池获取连接
getConnection:106, PoolingDataSource (org.apache.commons.dbcp)
getConnection:1044, BasicDataSource (org.apache.commons.dbcp)

getConnection:26, DbcpSecretBasicDataSource (xxx.qrcode.common.monitor.dbcp)
getConnection:83, LocalDataSourceConnectionProvider (org.springframework.orm.hibernate3) //获取连接
openConnection:446, ConnectionManager (org.hibernate.jdbc)
getConnection:167, ConnectionManager (org.hibernate.jdbc)
connection:160, JDBCContext (org.hibernate.jdbc)
begin:81, JDBCTransaction (org.hibernate.transaction)
beginTransaction:1473, SessionImpl (org.hibernate.impl)

doBegin:556, HibernateTransactionManager (org.springframework.orm.hibernate3) //开始事务
getTransaction:372, AbstractPlatformTransactionManager (org.springframework.transaction.support) //获取事务
createTransactionIfNecessary:417, TransactionAspectSupport (org.springframework.transaction.interceptor)
invokeWithinTransaction:255, TransactionAspectSupport (org.springframework.transaction.interceptor)
invoke:94, TransactionInterceptor (org.springframework.transaction.interceptor) //事务拦截器
proceed:172, ReflectiveMethodInvocation (org.springframework.aop.framework)
invoke:91, ExposeInvocationInterceptor (org.springframework.aop.interceptor)
proceed:172, ReflectiveMethodInvocation (org.springframework.aop.framework)
intercept:631, CglibAopProxy$DynamicAdvisedInterceptor (org.springframework.aop.framework)
merModifyNoAudit:-1, UrmtminfService$$EnhancerByCGLIB$$57be0f77 (xxx.qrcode.register.dbservice.impl)
merModifyNoAudit:517, QrcodeRegisterServer (xxx.qrcode.register.remoteserver.impl)
invokeMethod:-1, Wrapper20 (com.alibaba.dubbo.common.bytecode)
doInvoke:47, JavassistProxyFactory$1 (com.alibaba.dubbo.rpc.proxy.javassist)
invoke:76, AbstractProxyInvoker (com.alibaba.dubbo.rpc.proxy)
invoke:52, DelegateProviderMetaDataInvoker (com.alibaba.dubbo.config.invoker)
invoke:56, InvokerWrapper (com.alibaba.dubbo.rpc.protocol)
invoke:11, AppNameAppendFilter (com.xxx.log.rpc.dubbo)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:62, ExceptionFilter (com.alibaba.dubbo.rpc.filter)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:42, TimeoutFilter (com.alibaba.dubbo.rpc.filter)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:60, ExecuteLimitFilter (com.alibaba.dubbo.rpc.filter)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:75, MonitorFilter (com.alibaba.dubbo.monitor.support)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:78, TraceFilter (com.alibaba.dubbo.rpc.protocol.dubbo.filter)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:85, AccessLogExtFilter (xxx.qrcode.common.filter.dubbo)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:82, CatTransaction (com.xxx.log.rpc.dubbo)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:73, ContextFilter (com.alibaba.dubbo.rpc.filter)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:138, GenericFilter (com.alibaba.dubbo.rpc.filter)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:38, ClassLoaderFilter (com.alibaba.dubbo.rpc.filter)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:38, EchoFilter (com.alibaba.dubbo.rpc.filter)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
reply:104, DubboProtocol$1 (com.alibaba.dubbo.rpc.protocol.dubbo)
handleRequest:96, HeaderExchangeHandler (com.alibaba.dubbo.remoting.exchange.support.header)
received:173, HeaderExchangeHandler (com.alibaba.dubbo.remoting.exchange.support.header)
received:51, DecodeHandler (com.alibaba.dubbo.remoting.transport)
run:57, ChannelEventRunnable (com.alibaba.dubbo.remoting.transport.dispatcher)
runWorker:1145, ThreadPoolExecutor (java.util.concurrent)
run:615, ThreadPoolExecutor$Worker (java.util.concurrent)
run:745, Thread (java.lang)

是在事务开始的时候,就开始获取连接,而不是等到执行sql的时候才获取连接。

进入service

正式进入service类的业务方法的第一行代码,然后开始执行业务逻辑。

步骤
1.第一个sql
2.第二个sql
3.业务代码执行完成,进入事务拦截器
4.方法结束

执行sql的时候,所有sql都不需要再获取连接了,因为进入事务方法的时候被事务拦截器拦截的时候,就已经获取了连接,而且整个事务方法的所有sql都共用同一个连接。

事务拦截器收尾工作

调用栈

returnObject:1393, GenericObjectPool (org.apache.commons.pool.impl) //不是真的关闭,而是归还连接到连接池
close:90, PoolableConnection (org.apache.commons.dbcp)
close:191, PoolingDataSource$PoolGuardConnectionWrapper (org.apache.commons.dbcp) //关闭连接

doCloseConnection:341, DataSourceUtils (org.springframework.jdbc.datasource) //关闭连接
closeConnection:97, LocalDataSourceConnectionProvider (org.springframework.orm.hibernate3)

closeConnection:474, ConnectionManager (org.hibernate.jdbc) //关闭连接
cleanup:408, ConnectionManager (org.hibernate.jdbc)
close:347, ConnectionManager (org.hibernate.jdbc) //关闭连接
close:343, SessionImpl (org.hibernate.impl)

closeSession:802, SessionFactoryUtils (org.springframework.orm.hibernate3)
closeSessionOrRegisterDeferredClose:788, SessionFactoryUtils (org.springframework.orm.hibernate3) //关闭会话
doCleanupAfterCompletion:738, HibernateTransactionManager (org.springframework.orm.hibernate3)
cleanupAfterCompletion:1009, AbstractPlatformTransactionManager (org.springframework.transaction.support) //清理资源
processCommit:805, AbstractPlatformTransactionManager (org.springframework.transaction.support)
commit:724, AbstractPlatformTransactionManager (org.springframework.transaction.support)
commitTransactionAfterReturning:475, TransactionAspectSupport (org.springframework.transaction.interceptor) //提交事务
invokeWithinTransaction:270, TransactionAspectSupport (org.springframework.transaction.interceptor) //事务拦截器
invoke:94, TransactionInterceptor (org.springframework.transaction.interceptor)
proceed:172, ReflectiveMethodInvocation (org.springframework.aop.framework)
invoke:91, ExposeInvocationInterceptor (org.springframework.aop.interceptor)
proceed:172, ReflectiveMethodInvocation (org.springframework.aop.framework)
intercept:631, CglibAopProxy$DynamicAdvisedInterceptor (org.springframework.aop.framework)
merModifyNoAudit:-1, UrmtminfService$$EnhancerByCGLIB$$57be0f77 (xxx.qrcode.register.dbservice.impl)
merModifyNoAudit:517, QrcodeRegisterServer (xxx.qrcode.register.remoteserver.impl)
invokeMethod:-1, Wrapper20 (com.alibaba.dubbo.common.bytecode)
doInvoke:47, JavassistProxyFactory$1 (com.alibaba.dubbo.rpc.proxy.javassist)
invoke:76, AbstractProxyInvoker (com.alibaba.dubbo.rpc.proxy)
invoke:52, DelegateProviderMetaDataInvoker (com.alibaba.dubbo.config.invoker)
invoke:56, InvokerWrapper (com.alibaba.dubbo.rpc.protocol)
invoke:11, AppNameAppendFilter (com.xxx.log.rpc.dubbo)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:62, ExceptionFilter (com.alibaba.dubbo.rpc.filter)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:42, TimeoutFilter (com.alibaba.dubbo.rpc.filter)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:60, ExecuteLimitFilter (com.alibaba.dubbo.rpc.filter)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:75, MonitorFilter (com.alibaba.dubbo.monitor.support)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:78, TraceFilter (com.alibaba.dubbo.rpc.protocol.dubbo.filter)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:85, AccessLogExtFilter (xxx.qrcode.common.filter.dubbo)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:82, CatTransaction (com.xxx.log.rpc.dubbo)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:73, ContextFilter (com.alibaba.dubbo.rpc.filter)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:138, GenericFilter (com.alibaba.dubbo.rpc.filter)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:38, ClassLoaderFilter (com.alibaba.dubbo.rpc.filter)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:38, EchoFilter (com.alibaba.dubbo.rpc.filter)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
reply:104, DubboProtocol$1 (com.alibaba.dubbo.rpc.protocol.dubbo)
handleRequest:96, HeaderExchangeHandler (com.alibaba.dubbo.remoting.exchange.support.header)
received:173, HeaderExchangeHandler (com.alibaba.dubbo.remoting.exchange.support.header)
received:51, DecodeHandler (com.alibaba.dubbo.remoting.transport)
run:57, ChannelEventRunnable (com.alibaba.dubbo.remoting.transport.dispatcher)
runWorker:1145, ThreadPoolExecutor (java.util.concurrent)
run:615, ThreadPoolExecutor$Worker (java.util.concurrent)
run:745, Thread (java.lang)

步骤
主要是释放资源,
1.关闭会话
关闭hibernate会话。
2.关闭连接
最终只是归还连接到连接池,并没有真的关闭。

归还连接到连接池

GenericObjectPool

public void returnObject(T obj) throws Exception {
  try {
    this.addObjectToPool(obj, true); //归还连接到连接池
  } catch (Exception var7) {
    if (this._factory != null) {
      try {
        this._factory.destroyObject(obj);
      } catch (Exception var6) {
      }

      synchronized(this) {
        --this._numActive;
      }

      this.allocate();
    }
  }

}
private void addObjectToPool(T obj, boolean decrementNumActive) throws Exception {
  boolean success = true;
  if (this._testOnReturn && !this._factory.validateObject(obj)) {
    success = false;
  } else {
    this._factory.passivateObject(obj);
  }

  boolean shouldDestroy = !success;
  boolean doAllocate = false;
  synchronized(this) { //有锁
    if (this.isClosed()) {
      shouldDestroy = true;
    } else if (this._maxIdle >= 0 && this._pool.size() >= this._maxIdle) {
      shouldDestroy = true;
    } else if (success) {
      if (this._lifo) {
        this._pool.addFirst(new ObjectTimestampPair(obj)); //归还连接到连接池,连接池其实就是一个连接对象集合
      } else {
        this._pool.addLast(new ObjectTimestampPair(obj));
      }

      if (decrementNumActive) {
        --this._numActive;
      }

      doAllocate = true;
    }
  }

  if (doAllocate) {
    this.allocate();
  }

  if (shouldDestroy) {
    try {
      this._factory.destroyObject(obj);
    } catch (Exception var10) {
    }

    if (decrementNumActive) {
      synchronized(this) {
        --this._numActive;
      }

      this.allocate();
    }
  }

}

总结

主要是通过源码的调用栈去看整个流程,一目了然,非常清晰。