Design and Principle
The base case
HiKariCP as the default connection pool of SpringBoot2 framework, claimed to be the fastest running connection pool, database connection pool and the previous two mentioned thread pool and object pool, from the principle of design are based on the pooling idea, only in the implementation of their own characteristics; first or see the basic case of HiKariCP usage.
Core related classes
HikariDataSource class: brings together information related to the description of the data source, such as configuration, connection pool, connection object, state management, etc..
HikariConfig class: maintain the configuration of the data source management, and parameter verification, such as userName, passWord, minIdle, maxPoolSize, etc..
HikariPool class: provides the core ability to manage connection pools and objects in the pool, and implements query methods for pool-related monitoring data.
ConcurrentBag class: abandon the blocking queue used in the conventional pool as a container, customize the concurrent container to store connection objects.
PoolEntry class: extends information about connection objects, such as status, time, etc., to facilitate tracking of these instantiated objects in the container.
Through the analysis of several core classes in the connection pool, you can also intuitively appreciate the design principles of the source code, and the previous summary of the application of the object pool has similarities, but different components of different developers in the implementation of the time, have their own abstract logic.
Through the configuration information to build the data source description, in the construction method based on the configuration and then to instantiate the connection pool, in the construction of HikariPool, instantiate the ConcurrentBag container object; the following and then analyze the implementation details from the source code level.
Container ConcurrentBag class provides the PoolEntry type of connected object storage, as well as basic element management capabilities, object state description; although held by the HikariPool object pool class, but the actual logic of the operation is in the class.
The most central of these are
sharedList shared collections,
threadList thread-level caches, and
handoffQueue instant queues.
The IConcurrentBagEntry internal interface in the ConcurrentBag class, implemented by the PoolEntry class, which defines the state of the connection object.
STATE_NOT_IN_USE: unused, i.e., inactive.
STATE_IN_USE: in use.
STATE_RESERVED: reserved state, intermediate state, used when trying to evict a connected object.
the basic ability of the container is used to store the connection object, while the management of the object requires a lot of extended tracking information to effectively complete the identification of various scenarios, at which point it is necessary to resort to the introduction of packaging classes;.
Here it should be noted that the FastList class implements the List interface, customized for HiKariCP components, compared to the ArrayList class, for the pursuit of performance, in the management of the elements, to remove the many range checks.
Based on the conventional use of connection pools to see how the connection object is specifically managed, such as being lent, released, discarded, etc., as well as the state transition process of objects under these operations.
Above loading logic description, has been mentioned in the construction of the data source, will be instantiated according to the configuration of the connection pool, at the time of initialization, based on two core entry points to analyze the source code:
- how many connection objects are instantiated
- connection object conversion packaging object
checkFailFast method is executed in the connection pool construction, within which the MinIdle minimum idle number judgment is performed, and if it is greater than 0, a wrapper object is created and placed in the container.
Two issues need to be noted, the creation of the connection wrapper object, the initial state is 0 that is idle; in addition, although the case set the value of
MinIdle=4, but here the judgment is greater than 0, but also only in the container in advance put a free object.
When fetching the connection object from the pool, the
borrow method in the container class is actually called.
When executing the
borrow method, the following core steps and logic are involved.
- first reverse iterate through the local thread cache and return the object if an idle connection exists; if not, look for the Shared collection.
- Before traversing the Shared shared collection, it marks the number of waiting threads plus one, and returns it directly if there is an idle connection.
- When there is no idle connection in the Shared shared collection either, then the current thread performs
handoffQueuequeue polling for a certain amount of time, possibly with the release of resources, or with newly added resources.
Note that here, when traversing the collection, the objects taken out are judged and updated for status, and if a free object is obtained, it is updated to
IN_USE status and returned.
When releasing a connected object from the pool, the
requite method in the container class is actually called.
When releasing the connection object, first update the object state to idle, then determine whether there is currently a waiting thread, in the
borrow method waiting thread will enter a certain time polling, if not then the object into the local thread cache:.
Note that the state of the connection object involved here from use to
requite as the two core methods in the connection pool, responsible for resource creation and recycling.
Although only part of the source code, but already enough to highlight the author’s ultimate pursuit of performance, such as: local thread cache, custom container types, FastList, etc.; can be commonly adopted must exist many reasons to support.