Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is commons-pool2 pooling technology?

2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article introduces the relevant knowledge of "what is commons-pool2 pooling technology". In the operation of actual cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

I. Preface

We often come into contact with various pooling technologies or concepts, including object pooling, connection pooling, thread pooling and so on. The biggest advantage of pooling technology is to achieve the reuse of objects, especially when creating and using large objects or valuable resources (HTTP connection objects, MySQL connection objects) can greatly save system overhead, and it is also very important to improve the overall performance of the system.

Under concurrent requests, if you need to create / close MySQL connections for hundreds of query operations at the same time, create a processing thread for each HTTP request, or create a parsing object for each picture or XML parsing without using pooling technology, it will bring great load challenges to the system.

II. Analysis of commons-pool2 pooling technology

More and more frameworks are choosing to use apache commons-pool2 for pooled management. The logic of jedis-cluster,commons-pool2 work is shown in the following figure:

2.1 Core three elements 2.1.1 ObjectPool

Object pool, which is responsible for managing the life cycle of objects, and provides the function of counting active objects and idle objects in object pool.

2.1.2 PooledObjectFactory

The object factory class is responsible for the creation, initialization, destruction and verification of the object state. The commons-pool2 framework itself provides the default abstract implementation BasePooledObjectFactory, which the business side only needs to inherit when using, and then implement the warp and create methods.

2.1.3 PooledObject

A pooled object is a wrapper class that needs to be put into an ObjectPool object. Added some additional information, such as status information, creation time, activation time and so on. Commons-pool2 provides two implementations of DefaultPooledObject and PoolSoftedObject. PoolSoftedObject inherits from DefaultPooledObject, but the difference is that it uses SoftReference to implement soft references to objects. When getting an object, it is also obtained through SoftReference.

2.2 object pool logic analysis 2.2.1 object pool interface description

1) when we use commons-pool2, applications acquire or release objects based on object pooling. The core APIs of object pooling include the following:

/ * add object instances to object pool * / void addObject () throws Exception, IllegalStateException, UnsupportedOperationException;/*** get objects from object pool * / T borrowObject () throws Exception, NoSuchElementException, IllegalStateException;/*** invalid objects * / void invalidateObject (T obj) throws Exception;/*** release objects to object pool * / void returnObject (T obj) throws Exception

In addition to the interface itself, object pooling also supports setting the maximum number of objects, retention time, and so on. The core parameter items of object pool include maxTotal,maxIdle,minIdle,maxWaitMillis,testOnBorrow and so on.

2.2.2 object creation decoupling

Object factory is the core link used to generate objects in commons-pool2 framework. Business needs to implement the corresponding object factory implementation class themselves in the process of use. Through the factory pattern, it realizes the decoupling of object pool and object generation and implementation process details. Each object pool should have member variables of object factory, so as to realize the logical decoupling of object pool itself and object generation.

Our idea can be further verified by the code:

Public GenericObjectPool (final PooledObjectFactory factory) {this (factory, new GenericObjectPoolConfig ());} public GenericObjectPool (final PooledObjectFactory factory, final GenericObjectPoolConfig config) {super (config, ONAME_BASE, config.getJmxNamePrefix ()); if (factory = = null) {jmxUnregister (); / / tidy up throw new IllegalArgumentException ("factory may not be null");} this.factory = factory IdleObjects = new LinkedBlockingDeque (config.getFairness ()); setConfig (config);} public GenericObjectPool (final PooledObjectFactory factory, final GenericObjectPoolConfig config, final AbandonedConfig abandonedConfig) {this (factory, config); setAbandonedConfig (abandonedConfig);}

You can see that the construction methods of the object pool depend on the object construction factory PooledObjectFactory, which is generated based on the parameters defined in the object pool and the object construction factory.

/ * add objects to the object pool, which is generally used when preloading * / @ Overridepublic void addObject () throws Exception {assertOpen (); if (factory = = null) {throw new IllegalStateException ("Cannot add objects without a factory.");} final PooledObject p = create (); addIdleObject (p);}

The create () method, based on the object generated by the object factory, continues to follow the code to confirm the logic

Final PooledObject psettry {p = factory.makeObject (); if (getTestOnCreate () & &! factory.validateObject (p)) {createCount.decrementAndGet (); return null;}} catch (final Throwable e) {createCount.decrementAndGet (); throw e;} finally {synchronized (makeObjectCountLock) {makeObjectCount--; makeObjectCountLock.notifyAll ();}}

The operation of factory.makeObject () is confirmed here, and the above conjecture is confirmed, which generates the corresponding object based on the object factory.

In order to better realize the use of objects in the object pool and track the state of objects, the concept of pooled object PooledObject is used in the commons-pool2 framework. PooledObject itself is a generic class, and provides a method for getObject () to get the actual object.

2.2.3 Source Code Analysis of object Pool

After the above analysis, we know that the object pool carries the management of the life cycle of objects, including the control of the number of objects in the whole object pool, and then we analyze how to achieve it through the source code of GenericObjectPool.

Double-end queue LinkedBlockingDeque is used to store objects in the object pool. LinkedBlockingDeque supports two strategies of FIFO and FILO, and the cooperation of queue operation is realized based on AQS.

LinkedBlockingDeque provides the operation of inserting and removing elements at the end of the queue and the head of the queue. Related operations are performed by setting two state variables, notFull and notEmpty, in the queue of locking operations that are added to the reentry lock. When the operation of elements is performed on the queue, the corresponding operations such as await and notify will be triggered.

/ * * first node * Invariant: (first = = null & & last = = null) | * (first.prev = = null & & first.item! = null) * / private transient Node first; / / @ GuardedBy ("lock") / * * Last node * Invariant: (first = = null & & last = = null) | * (last.next = = null & last.item! = null) * / private transient Node last / / @ GuardedBy ("lock") / * * current queue length * / private transient int count; / / @ GuardedBy ("lock") / * * maximum queue capacity * / private final int capacity;/** master lock * / whether the private final InterruptibleReentrantLock lock;/** queue is an empty status lock * / whether the private final Condition notEmpty;/** queue is full status lock * / private final Condition notFull

The core points of the queue are:

1. All the move-in, move-out, and initialize construction elements in the queue are locked based on the master lock.

two。 The offer and pull of the queue support setting the timeout parameter, mainly through the coordination of the two state Condition. For example, when performing an offer operation, if the operation is not successful, it waits based on the notFull state object.

Public boolean offerFirst (final E e, final long timeout, final TimeUnit unit) throws InterruptedException {Objects.requireNonNull (e, "e"); long nanos = unit.toNanos (timeout); lock.lockInterruptibly (); try {while (! linkFirst (e)) {if (nanos = capacity) {return false;} final Node l = last; final Node x = new Node (e, l, null); last = x; if (first = null) {first = x } else {l.next = x;} + + count; notEmpty.signal (); return true;} 2.3 Core business process 2.3.1 pooled object state change

The above figure is the state machine diagram of PooledObject. Blue indicates the status and red indicates the methods related to ObjectPool. The status of PooledObject is: IDLE, ALLOCATED, RETURNING, ABANDONED, INVALID, EVICTION, EVICTION_RETURN_TO_HEAD

All states are defined in the PooledObjectState class, some of which are temporarily unused, so I won't repeat them here.

2.3.2 object pool browObject process

The first step is to determine whether to call the removeAbandoned method for tag deletion based on the configuration.

The second step is to try to get or create an object. The source code process is as follows:

/ / 1. Try to get an object from a double-ended queue. The pollFirst method is a non-blocking method p = idleObjects.pollFirst (); if (p = = null) {p = create (); if (p! = null) {create = true;}} if (blockWhenExhausted) {if (p = null) {if (borrowMaxWaitMillis)

< 0) { //2、没有设置最大阻塞等待时间,则无限等待 p = idleObjects.takeFirst(); } else { //3、设置最大等待时间了,则阻塞等待指定的时间 p = idleObjects.pollFirst(borrowMaxWaitMillis, TimeUnit.MILLISECONDS); } }} 示意图如下所示: 第三步、调用allocate使状态更改为ALLOCATED状态。 第四步、调用工厂的activateObject来初始化对象,如果发生错误,请调用destroy方法来销毁对象,例如源代码中的六个步骤。 第五步、调用TestFactory的validateObject进行基于TestOnBorrow配置的对象可用性分析,如果不可用,则调用destroy方法销毁对象。3-7步骤的源码过程如下所示: //修改对象状态if (!p.allocate()) { p = null;}if (p != null) { try { //初始化对象 factory.activateObject(p); } catch (final Exception e) { try { destroy(p, DestroyMode.NORMAL); } catch (final Exception e1) { } } if (p != null && getTestOnBorrow()) { boolean validate = false; Throwable validationThrowable = null; try { //验证对象的可用性状态 validate = factory.validateObject(p); } catch (final Throwable t) { PoolUtils.checkRethrow(t); validationThrowable = t; } //对象不可用,验证失败,则进行destroy if (!validate) { try { destroy(p, DestroyMode.NORMAL); destroyedByBorrowValidationCount.incrementAndGet(); } catch (final Exception e) { // Ignore - validation failure is more important } } }}2.3.3 对象池returnObject的过程执行逻辑 第一步、调用markReturningState方法将状态更改为RETURNING。 第二步、基于testOnReturn配置调用PooledObjectFactory的validateObject方法以进行可用性检查。如果检查失败,则调用destroy消耗该对象,然后确保调用idle以确保池中有IDLE状态对象可用,如果没有,则调用create方法创建一个新对象。 第三步、调用PooledObjectFactory的passivateObject方法进行反初始化操作。 第四步、调用deallocate将状态更改为IDLE。 第五步、检测是否已超过最大空闲对象数,如果超过,则销毁当前对象。 第六步、根据LIFO(后进先出)配置将对象放置在队列的开头或结尾。

(schematic diagram of restore operation queue)

2.4 extension and reflection 2.4.1 alternative implementation of LinkedBlockingDeque

In the above analysis, double-ended queue and condition in java are used in commons-pool2 to achieve the management of objects in the queue and the coordination between different threads to obtain and release objects. Is there any other scheme that can achieve similar results? The answer is yes.

The purpose of using double-end queues to operate is to isolate idle objects from active objects. In essence, we use two queues to store idle queues and current active objects respectively, and then uniformly use an object lock. The same goal can also be achieved. The general idea is as follows:

1) the two-end queue is changed to two one-way queues to store idle and active objects, and the synchronization and coordination between queues can be accomplished through the wait and notify of object locks.

Public class PoolState {protected final List idleObjects = new ArrayList (); protected final List activeObjects = new ArrayList (); / /...}

2) when acquiring an object, the original LIFO or FIFO of the two-end queue becomes the object obtained from the idle queue idleObjects, and then after the acquisition is successful and the object status is legal, the object is added to the active object collection activeObjects. If the object needs to wait, the PoolState object lock should enter the waiting state through wait operation.

3) when releasing an object, the element is first deleted from the active object collection activeObjects, and after the deletion is completed, the object is added to the free object collection idleObjects. It should be noted that the state of the object also needs to be verified during the object release process. When the object state is illegal, the object should be destroyed and should not be added to the idleObjects. After the release is successful, PoolState wakes up the acquisition operation in the wait through notify or notifyAll.

4) to ensure the thread safety of active queues and idle queues, locking operations are required to acquire and release objects, which is the same as in commons2-pool.

2.4.2 self-protection mechanism of object pool

When we use commons-pool2 to get an object, we will block waiting for the acquisition element (or create a new object) from the double-end queue. However, if it is an exception of the application, when returnObject or invalidObject has not been called, then the object in the object pool may rise all the time. When you go to call borrowObject after you go online, you will wait or wait for a timeout and cannot get the object.

In order to avoid the problems analyzed above, commons-pool2 provides two self-protection mechanisms:

2.4.2.1 threshold-based detection

When getting objects from the object pool, it will check the proportion of active objects and free objects in the current object pool. When there are very few idle objects and a large number of active objects, it will trigger the collection of free objects. The specific verification rule is as follows: if the number of objects in the current object pool is less than 2 idle states or if the number of active > the maximum number of objects-3, start leak cleanup when borrow objects. Open the true via AbandonedConfig.setRemoveAbandonedOnBorrow.

/ / determine whether to call the removeAbandoned method final AbandonedConfig ac = this.abandonedConfig;if (ac! = null & & ac.getRemoveAbandonedOnBorrow () & & (getNumIdle ()) for tag deletion according to the configuration

< 2) && (getNumActive() >

GetMaxTotal ()-3) {removeAbandoned (ac);}

2.4.2.2 Asynchronous scheduling thread detection

When AbandonedConfig.setRemoveAbandonedOnMaintenance is set to true, the leaked objects will be cleaned up while the maintenance task is running, and the interval between the execution of the maintenance task will be set by setting setTimeBetweenEvictionRunsMillis.

(asynchronous detection thread Evictor sequence diagram)

Detect and recycle to implement logical analysis:

The startEvictor method is called at the end of the inner logic of the constructor. The purpose of this method is to start the collector to monitor the collection of idle objects after the object pool has been constructed. StartEvictor is defined in the BaseGenericObjectPool (abstract) class, the parent class of GenericObjectPool, so let's take a look at the source code of this method.

The following setting parameters are executed in the constructor

Public final void setTimeBetweenEvictionRunsMillis (final long timeBetweenEvictionRunsMillis) {this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; startEvictor (timeBetweenEvictionRunsMillis);}

The scheduled cleanup task is started if and only if the timeBetweenEvictionRunsMillis parameter is set.

Final void startEvictor (final long delay) {synchronized (evictionLock) {EvictionTimer.cancel (evictor, evictorShutdownTimeoutMillis, TimeUnit.MILLISECONDS); evictor = null; evictionIterator = null; / / if delay 0) {evictor = new Evictor (); EvictionTimer.schedule (evictor, delay, delay);}

Follow up the code to find that the implementation logic of the cleanup method set in the scheduler is actually defined in the object pool, that is, it is implemented by GenericObjectPool or GenericKeyedObjectPool, and then we continue to explore how the object pool carries out object collection.

A), core parameters:

MinEvictableIdleTimeMillis: specify the maximum retention time for idle objects, after which will be recycled. If it is not configured, it will not be reclaimed out of date.

SoftMinEvictableIdleTimeMillis: a millisecond value that specifies that only if the number of idle objects exceeds the minIdle setting, and an idle object exceeds this idle time, it can be recycled.

MinIdle: the minimum number of spatial objects to be retained in the object pool.

B), recycling logic

And an object recycling policy API EvictionPolicy, which can be expected that the recycling of the object pool will be associated with the above parameter items and interface EvictionPolicy. The following content will be found in the follow-up code. You can see that when it is determined that the object pool can be recycled, destroy is directly called for recycling.

Boolean evict;try {evict = evictionPolicy.evict (evictionConfig, underTest, idleObjects.size ());} catch (final Throwable t) {/ / Slightly convoluted as SwallowedExceptionListener / / uses Exception rather than Throwable PoolUtils.checkRethrow (t); swallowException (new Exception (t)); / / Don't evict on error conditions evict = false;} if (evict) {/ / if it can be recycled, call destroy directly to recycle destroy (underTest); destroyedByEvictorCount.incrementAndGet ();}

In order to improve the efficiency of recycling, further status judgment and processing will be carried out when the recovery policy determines that the status of the object is not evict. The specific logic is as follows:

1. An attempt is made to activate the object. If the activation fails, the object is no longer alive. Call destroy directly to destroy it.

two。 If the activation object is successful, the status of the object will be checked by the validateObject method. If the verification fails, the object is not available and needs to be destroyed.

Boolean active = false;try {/ / call activateObject to activate the idle object, essentially not to activate, / / but through this method to determine whether it is still alive or not, there may be some resource opening behavior in this step. Factory.activateObject (underTest); active = true;} catch (final Exception e) {/ / if an exception occurs during activation, the idle object has been lost. / / call the destroy method to destroy underTest destroy (underTest); destroyedByEvictorCount.incrementAndGet ();} if (active) {/ / verify the validity of if (! factory.validateObject (underTest)) {/ / if the verification fails, the object is no longer available for destroy (underTest); destroyedByEvictorCount.incrementAndGet () } else {try {/ * * because parity also activates idle objects and allocates additional resources, then the resources opened up in activateObject are released through passivateObject. * / factory.passivateObject (underTest);} catch (final Exception e) {/ / if passivateObject fails, it can also indicate that the free object underTest is not available destroy (underTest); destroyedByEvictorCount.incrementAndGet ();}} "what is commons-pool2 pooling technology" ends here, thank you for your reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report