首页java › JBOSS连接池的启动及prefill配置

JBOSS连接池的启动及prefill配置

jboss连接池的启动,主要就是一些对象的初始化及一个prefill的过程。
prefill参数:在ds.xml中有一个参数,叫prefill,这个值可以设置为true|false,默认为false,这个参数在JBOSS4.0.5版本以上才能被支持。这个参数的设置,决定了连接池在启动时是否会初始化min连接数(最小连接数)。如果设置为true,连接池在启动的时候会进行min值连接数的初始化,但是在应用同时启动时可能导致连接风暴;如果设置为false,则在第一次getconnection时,才启动创建min连接数。

本节主要研究了JBOSS连接池在启动时究竟做了些什么操作,带着好奇心,我们查看JBOSS源码,其实并不难,可以看到在连接池的启动过程中主要涉及到两个类,InternalManagedConnectionPool和PoolFiller。
PoolFiller类:在jboss启动时即开始fillerThread线程的wait,当执行fillPool操作时被唤醒,fillPool操作主要的作用是将JBOSS的连接池填充到min值。当连接池填充到min值之后,线程继续wait。

InternalManagedConnectionPool:这个类是JOBSS连接池管理的核心类,后面几节主要围绕这个类来展开。

InternalManagedConnectionPool类的构造方法和连接池的配置参数紧密相关,如下:

 protected InternalManagedConnectionPool(ManagedConnectionFactory mcf,
 				ConnectionListenerFactory clf,
         Subject subject, ConnectionRequestInfo cri,
          PoolParams poolParams, Logger log)
   {
   		//mcf是连接管工厂
      this.mcf = mcf;
      //连接监听工厂
      this.clf = clf;
      //默认的subject
      defaultSubject = subject;
      //连接请求信息
      defaultCri = cri;
      //连接池参数,主要方法见下面的函数,见附录。
      this.poolParams = poolParams;
      this.maxSize = this.poolParams.maxSize;

      this.log = log;
      this.trace = log.isTraceEnabled();
      //可以使用的连接事件监听器初始化。
      cls = new ArrayList(this.maxSize);
      /*创建一个对应连接事件监听器的信号集,用于连接的获取。
      每次获取连接或者创建连接之前,都需要获取信号量,
      当没有可用的信号量时,表示连接已经到达max值。
      */
      permits = new FIFOSemaphore(this.maxSize);
      /*
      判断jboss配置文件中的prefill设置,默认为false。
      如果设置为true,则将本连接池加入到一个临时pool(LinkedList)的最后,
      加入的方式是串行的(线程安全)。
      */
      if(poolParams.prefill)
      {
      //fillPool主要执行了一个fillToMin的方法,即将连接池中的连接,填充到min值。
         PoolFiller.fillPool(this);

      }
   }

这就是InternalManagedConnectionPool的实例化,很简单,最后一步判断如果参数prefill设置为flase,则没有其它事了,整个过程结束。否则,执行一个fillPool的操作。

先来看一下与PoolFiller类,PoolFiller在构造函数中即完成fillerThread线程的启动,线程启动后由于pools是空的,所以本线程一直处于wait状态,当执行PoolFiller.fillPool(this); 操作时,pools中首先会增加了一个连接池对象(见internalFillPool函数),然后幻醒fillerThread线程,fillerThread线程被唤醒后,因为此时pools已经不为null了,线程开始初始化pools队列中的所有的连接池对象(在并发情况下,可能有多个连接池对象需要初始化,但是连接初始化的过程,是一个线程安全的操作),线程唤醒后主要的操作是将连接池的连接数填充至min值,填充由fillToMin函数来执行。
当pools中所有的连接池对象都填充到min值时,此时pools也被清空了,fillerThread线程继续进行wait,直到下一次fillPool时被唤醒。在连接池启动时只会被fillPool一次,其它的fillPool操作还会在三种情况下发生
1.后面的章节会讲到在removeTimedOut(idle超时清理时,还会调会fillPool操作-即清理Idle连接后,发现小于min值,又需要进行fillPool操作)。
2.在valitionconnection后,紧接着执行fillToMin。(同上)
3.当prefill设置为false,即连接池实例化时没有被fill到min值,在第一次getconnection时,触发这个fillPool操作。

具体如下图所示:

public class PoolFiller implements Runnable
{
   private final LinkedList pools = new LinkedList();

   private final Thread fillerThread;

   private static final PoolFiller filler = new PoolFiller();

   public static void fillPool(InternalManagedConnectionPool mcp)
   {
      filler.internalFillPool(mcp);
   }

   public PoolFiller ()
   {
      fillerThread = new Thread(this, "JCA PoolFiller");
      fillerThread.start();
   }

   public void run()
   {
      ClassLoader myClassLoader = getClass().getClassLoader();
      Thread.currentThread().setContextClassLoader(myClassLoader);
      //keep going unless interrupted
      while (true)
      {
         try
         {
            InternalManagedConnectionPool mcp = null;
            //keep iterating through pools till empty, exception escapes.
            while (true)
            {

               synchronized (pools)
               {
            	 //取出需要处理的连接池,即需要fillToMin的连接池
                  mcp = (InternalManagedConnectionPool)pools.removeFirst();
               }
               //如果没有需要处理的连接池了,则跳出while循环,进行线程的wait。
               if (mcp == null)
                  break;
               //将连接池mcp填充至min值。
               mcp.fillToMin();
            }
         }
         catch (Exception e)
         {
         }

         try
         {
            synchronized (pools)
            {
              /*如果没有需要处理的连接池了,则跳出while循环,
              进行线程的wait,等待下一次执行internalFillPool函数唤醒filltoMin
              */
               while(pools.isEmpty())
               {
                  pools.wait();                        

               }
            }
         }
         catch (InterruptedException ie)
         {
            return;
         }
      }
   }

   private void internalFillPool(InternalManagedConnectionPool mcp)
   {
      synchronized (pools)
      {
    	 /*
    	 将连接池对象加入到pools临时队列里,
    	 这里的pools只是一个临时队列,用于进行fillToMin的操作。
    	 */
         pools.addLast(mcp);
       //notify()会触发器run
         pools.notify();
      }
   }
}

fillToMin函数如下:

public void fillToMin()
   {
      while (true)
      {
         /*
          获取一个信号量 - 防止在连接池快满时,产生竞争
         当所有的连接都被checkd out(即全部被占用)时,避免不需要的fill检查。
         */
         try
         {
        	 //获取信号量,超时时间为jboss数据源配置文件的time out
            if (permits.attempt(poolParams.blockingTimeout))
            {
               try
               {
            	  //判断连接池是否已经shutdown?如果已经shutdown,则直接返回。
                  if (shutdown.get())
                     return;

                  // 判断连接池中的连接是否已经达到min值,如果已经达到,则直接返回。
                  if (getMinSize() - connectionCounter.getGuaranteedCount()

 

发表评论

注意 - 你可以用以下 HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>