Overview
During the operation of the project, some operations on the system resource consumption is large, such as the establishment of database connections, the establishment of REDIS connections, and so on, we want to create multiple connection objects at one time, and in the future when we need to use the created connection directly, to improve performance. The pool technology uses pool technology to improve application service performance by initializing some of the more resource-intensive objects ahead of time, and saving the initialized objects to the pool for the purpose of improving the use of the database's JDBC Connection pool and Jedis connection pool.
Apache-commons-pool2 provides a set of standard interfaces for pool technology and common logic for implementation, and we just need to implement the methods that are abstracted from them. This blog post mainly shares applications based on Apache-commons-pool2 to implement GRPC connection pooling.
About GRPC related content, if you want to understand the basic implementation method, you can refer to my other blog (portal): http://blog.51cto.com/andrewli/2058908
Core components
Let's take a look at some of the core components involved in the APACHE-COMMONS-POOL2 specification interface, including:
- Objectpool
Object pools, which are used to store objects and to manage the incoming and outbound pools of objects. The implementation class for the object pool is genericobjectpool<t>;
- Poolconfig
Pool properties, which are used to set some configuration information for the connection pool, such as the maximum pool capacity, the processing logic after the pool capacity, and so on. The implementation class for the pool attribute is: genericobjectpoolconfig;
- Objectfactory
Object Factory, generate a new object instance when needed, and put it into the pool. The interface of the object factory is: interface pooledobjectfactory<t>;
- Clientobject
The pool object, which is created by the object factory and placed into the object pool, needs to be fetched from the object pool when it is used, executes the business logic of the object, and then puts it back into the object pool. The interface of the pool object is: interface pooledobject<t>. Core component dependencies and dependencies between their workflow interfaces and classesBefore combing the core component workflow related to connection pooling, let's look at the inheritance and implementation relationships between the classes and interfaces involved in the core component.
Inheritance relationships for Object pool classes
The topmost interface of an object pool is Objectpool<t>, which defines the basic methods of object pooling, including the addition, removal, validation, and return of objects, and the number of objects in the idle sleep state, the number of objects in the active state, the emptying pool, and the shutdown pool.
Abstract class Basegenericobjectpool<t>, defines the initial configuration of the object pool, and implements the basic interface method of the object pool.
The pool class genericobjectpool<t> inherits the abstract class Basegenericobjectpool<t>, and implements the Objectpool<t> interface. It adds attributes such as Object factory, map to store all objects, chained blocking queue for storing idle objects, number of objects currently created, and so on.
Because the Genericobjectpool<t> class supports the paradigm, all we have to do is specify the pool object type <t> returned by the Genericobjectpool<t> pool class, and set the Object factory class, configuration class, and other pool properties , or inherit the Genericobjectpool class to add more custom pool attributes.
Inheritance relationships for Pool attribute classes
The topmost interface of the pool attribute is interface cloneable, which is implemented by the abstract class Baseobjectpoolconfig and defines the default pool configuration properties.
The Genericobjectpoolconfig class inherits the Baseobjectpoolconfig and also defines the default pool configuration property values.
We can use the Genericobjectpoolconfig class directly or inherit the Genericobjectpoolconfig class to set custom pool configuration properties to suit your needs.
Inheritance relationships for object classes within a pool
The In-Pool object class implements the upper-level pooledobject<t> interface, which defines the various methods that a pool object needs to implement.
In addition, the in-pool object classes need to define the member properties required by the class itself and the business methods that need to be implemented.
- Inheritance relationships for object factory classes
The object factory class implements the topmost pooledobjectfactory<t> interface, which defines the core functional methods of the object factory, including: creating objects, destroying objects, validating objects, activating objects, and Passivation objects.
Work flow
Based on the above analysis of the class inheritance relationships of the core components, we can comb out a process to gradually implement the individual components and combine them into a set of connection pool architectures for our business. Let's take a look at how this process is defined.
(1) Define our pool of object class Clientobject, and combine our actual business to implement the method of upper interface.
(2) Define the object factory class Clientfactory, and combine our actual business to implement the method of upper interface.
(3) Define the Pool attribute class Clientpoolconfig and set the property values in conjunction with our actual requirements.
(4) Using the object pool Genericobjectpool, specify the generic type genericobjectpool<clientobject>.
Core business logic inside the connection pool:
The creation and return logic of the objects in the pool is the key to the pool technology, and you can see the Borrowobject method of the pool object to understand this part of the details.
Application Practice Code Implementation
Based on the analysis of the characteristics and implementation process of the apache-commons-pool2, we carry out code practice based on the GRPC Client connection pool application scenario, including implementing the object class Clientobject in the pool and implementing the Object factory class Clientfactory.
Specific code can be entered in my Baidu network disk download, links as follows:
Https://pan.baidu.com/s/1eaGpz6XN2a3ssw0eYsNLww
Code testing
To verify the role of our GRPC connection pool, I wrote a test method that simulates the scenario of opening 10 threads, looping 10 times per thread using the GRPC connection to send a message to the GRPC server, and then looking at the number of connection objects created in the thread pool, The number of times each connection object has been used in the thread pool.
By testing the output, I have concluded that 100 GRPC connections and messages are required when no connection pooling is used, and that a total of 2 GRPC connections are required to send 100 messages after the connection pool is used, and each connection is called 50 times.
The test code is as follows.
Package Com.cmcc.littlec.grpc.poolclient;import Com.cmcc.littlec.grpc.util.constants;import Org.apache.commons.pool2.impl.genericobjectpool;import Org.apache.commons.pool2.impl.GenericObjectPoolConfig; public class Test {@SuppressWarnings ("unchecked") public static genericobjectpool<clientobject> Getclientpool () {Clientpoolfactory factory = new Clientpoolfactory (Constants.grpchost, Constants.grpcport); Genericobjectpoolconfig config = new Genericobjectpoolconfig (); Config.setmaxidle (8); Config.setminidle (3); Config.setmaxtotal (18); Config.settestonborrow (TRUE); Config.settestonreturn (TRUE); genericobjectpool<clientobject> Clientpool = new genericobjectpool<clientobject> (factory, config); return clientpool; } public static void Main (string[] args) {final genericobjectpool<clientobject> Clientpool = Getclientpo OL (); for (int i=0; i<10; i++) {Thread t = new threAD (New Runnable () {@Override public void run () {try { for (int i = 0; i < i++) {Clientobject client = Clientpool.borrowobject (); String str = "Hello, grpc client_" + i;//parameter try {Client.sayhello (str); }catch (Exception e) {client.invalidate (); } System.out.println ("Thread:" + thread.currentthread (). GetName () + "; Clientpool Size: "+ clientpool.getcreatedcount ()); System.out.println ("Clientobj:" +client.tostring ()); Clientpool.returnobject (client); }} catch (Exception e) {System.out.println (E.getmessage ()); } } }); T.start (); try {if (i%2==0) {thread.sleep (5000L);//Pause 5S after creation of every two threads}CATC H (Exception e) {}}}}
Implementing GRPC Client connection pooling based on Apache-commons-pool2