C3p0 ---- unable to obtain the link

Source: Internet
Author: User

Recently, other projects often fail to get links, and I am curious to play with them. The plug-in used is c3p0 + spring + ibatis, of course, the transaction management configuration is as follows:

1 <bean id = "datasource" class = "com. mchange. v2.c3p0. combopooleddatasource "2 destroy-method =" close "> 3 <property name =" driverclass "value =" $ {JDBC. driverclassname} "/> 4 <property name =" jdbcurl "value =" $ {JDBC. URL} "/> 5 <property name =" user "value =" $ {JDBC. username} "/> 6 <property name =" password "value =" $ {JDBC. password} "/> 7 <property name =" minpoolsize "value =" $ {datasource. minpoolsize} "/> 8 <proper Ty name = "maxpoolsize" value = "$ {datasource. maxpoolsize} "/> 9 <property name =" initialpoolsize "value =" $ {datasource. initialpoolsize} "/> 10 <property name =" maxidletime "value =" $ {datasource. maxidletime} "/> 11 <property name =" maxstatements "value =" $ {datasource. maxstatements} "/> 12 <property name =" idleconnectiontestperiod "value =" $ {datasource. idleconnectiontestperiod} "/> 13 <property name =" acquireincrem Ent "value =" $ {datasource. acquireincrement} "/> 14 <property name =" acquireretryattempts "value =" $ {datasource. acquireretryattempts} "/> 15 <property name =" breakafteracquirefailure "value =" $ {datasource. breakafteracquirefailure} "/> 16 <property name =" checkouttimeout "value =" $ {datasource. checkouttimeout} "/> 17 <property name =" numhelperthreads "value =" $ {datasource. numhelperthreads} "/> 18 </bean> 19 20 <! -- Transaction Management --> 21 <bean id = "transactionmanager" 22 class = "org. springframework. JDBC. datasource. datasourcetransactionmanager "> 23 <property name =" datasource "ref =" datasource "/> 24 </bean> 25 26 <! -- Transaction interceptor --> 27 <bean id = "transactioninterceptor" 28 class = "org. springframework. transaction. interceptor. transactioninterceptor "> 29 <property name =" transactionmanager "ref =" transactionmanager "/> 30 <property name =" transactionattributes "> 31 <! -- The following defines the attributes of transaction propagation: key indicates the method --> 32 <props> 33 <prop key = "insert *"> propagation_required </prop> 34 <prop key = "Update *"> propagation_required </prop> 35 <prop key = "delete *"> propagation_required </prop> 36 <prop key = "select *"> propagation_required, readonly </prop> 37 <prop key = "get *"> propagation_required, readonly </prop> 38 <prop key = "query *"> propagation_required, readonly </prop> 39 <prop key = "pagequery *"> propaga Tion_required, readonly </prop> 40 <prop key = "*"> propagation_required </prop> 41 </props> 42 </property> 43 </bean> 44 <! -- Beanname auto proxy to define the interceptor --> 45 46 <bean47 class = "org. springframework. AOP. framework. autoproxy. beannameautoproxycreator "> 48 <property name =" beannames "> 49 <list> 50 <! -- Configure the service for Transaction Management --> 51 <value> * service </value> 52 <value> * serviceimpl </value> 53 </List> 54 </property> 55 <property name = "interceptornames"> 56 <list> 57 <value> transactioninterceptor </value> 58 </List> 59 </property> 60 </bean>

The configuration above is a little long. Let's take a few important instructions:

datasource.minPoolSize=30datasource.maxPoolSize=80datasource.initialPoolSize=40datasource.maxIdleTime=60datasource.acquireIncrement=5

datasource.idleConnectionTestPeriod=60datasource.maxStatements=0datasource.acquireRetryAttempts=30datasource.breakAfterAcquireFailure=falsedatasource.testConnectionOnCheckout=falsedatasource.checkoutTimeout=20000datasource.numHelperThreads=10

The configuration is normal, and the number of task threads increases from 3 to 10 by default. This is also desirable because the minpoolsize is 30 and the pool created during initialization is 40, increase the number of links each time.

Taking this opportunity, I read the source code of c3p0 again. I wrote a very simple test. Of course, the configuration is exactly the same, but the structure uses mybatis, And then I only used the get method, assume that all business logic adopts the normal transaction interceptor, that is, all links are used up and the link is returned.

  1. First, from the number of 100 threads, calling the service method using the c3p0 link concurrently found no pressure. Apparently, 100 is too pediatric.
  2. Vigorously add the number of threads to 1000, so there will be some (a few threads cannot get the connection), that is, the method for obtaining the Link Inside c3p0:
     1 private synchronized Object prelimCheckoutResource( long timeout ) 2     throws TimeoutException, ResourcePoolException, InterruptedException 3     { 4         try 5         { 6             ensureNotBroken(); 7  8             int available = unused.size(); 9             if (available == 0)10             {11                 int msz = managed.size();12 13                 if (msz < max)14                 {15                     // to cover all the load, we need the current size, plus those waiting already for acquisition, 16                     // plus the current client 17                     int desired_target = msz + acquireWaiters.size() + 1;18 19                     if (logger.isLoggable(MLevel.FINER))20                         logger.log(MLevel.FINER, "acquire test -- pool size: " + msz + "; target_pool_size: " + target_pool_size + "; desired target? " + desired_target);21 22                     if (desired_target >= target_pool_size)23                     {24                         //make sure we don‘t grab less than inc Connections at a time, if we can help it.25                         desired_target = Math.max(desired_target, target_pool_size + inc);26 27                         //make sure our target is within its bounds28                         target_pool_size = Math.max( Math.min( max, desired_target ), min );29 30                         _recheckResizePool();31                     }32                 }33                 else34                 {35                     if (logger.isLoggable(MLevel.FINER))36                         logger.log(MLevel.FINER, "acquire test -- pool is already maxed out. [managed: " + msz + "; max: " + max + "]");37                 }38 39                 awaitAvailable(timeout); //throws timeout exception40             }

    Wait directly to 39 rows, but it is not difficult to see that available = 0, and then whether or not _ recheckresizepool (); this operation needs to be waited. Here, the wait time is configured with checkouttimeout = 2000. Such a long wait time is available for all resources. According to our previous understanding, c3p0 actually has the right operation to expand the connection pool and contract the number of connections. Looking down, we can see it in _ recheckresizepool () method:

     1   int desired_target = msz + acquireWaiters.size() + 1; 2  3                     if (logger.isLoggable(MLevel.FINER)) 4                         logger.log(MLevel.FINER, "acquire test -- pool size: " + msz + "; target_pool_size: " + target_pool_size + "; desired target? " + desired_target); 5  6                     if (desired_target >= target_pool_size) 7                     { 8                         //make sure we don‘t grab less than inc Connections at a time, if we can help it. 9                         desired_target = Math.max(desired_target, target_pool_size + inc);10 11                         //make sure our target is within its bounds12                         target_pool_size = Math.max( Math.min( max, desired_target ), min );13 14                         _recheckResizePool();15                     }

    When the waiting task is too large, target_pool_size = math. Max (math. Min (max, desired_target), min); Sets target_pool_size to Max.

    1   if ((shrink_count = msz - pending_removes - target_pool_size) > 0)2                 shrinkPool( shrink_count );3             else if ((expand_count = target_pool_size - (msz + pending_acquires)) > 0)4                 expandPool( expand_count );

    The target_pool_size here is the target size currently required by the Business. there is ambiguity here, And msz is the current poolsize,

    Pending_acquires is the number of tasks waiting to obtain resources. It may be large. expand_count = target_pool_size-(msz + pending_acquires)> 0: expand_count = 80-(70 + 100) <0, so when the waiting resource is too large, but the current number of threads is too large, the link is not resized, the reason is here. Instantly concurrent to off-peak value. Therefore, when a new request comes in after waiting for all resources to be timeout to a small value or when a resource is used and the link is returned, the resource will be re-added after the judgment condition is met. As for how to add a task, it is common to say that a thread is required to create a link resource. Therefore, the above 10 threads can only create 10 links at the same time (theoretically, however, the run methods of tasks are instantaneous and can meet the needs of a certain amount of creation.

    Eeeeeeee

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.