In a previous article, we introduced the execution process of the balaner of mongos. In the Balancer: run () method in the source code, we briefly stated that in order to connect to the configserver, balancer links and performs corresponding operations by constructing ScopedDbConnection, because the space limit at that time is limited, but the link is moved by pooling, today, I will introduce how mongodb uses pooling to manage linked objects to improve link efficiency.
Now, let's start with today's text!
First, let's take a look at the run () method of the balancer class. The relevant code is as follows:
// Balance. cpp
Void Balancer: run (){
......
While (! InShutdown () {// loop until the program is interrupted or closed
Try {
......
ScopedDbConnection conn (config );
......
Conn. done (); // place conn in the Link pool (for other subsequent operations)
Sleepsecs (_ balancedLastTime? 5: 10 );
}
Catch (std: exception & e ){
......
}
}
}
In the above method, the ScopedDbConnection declaration ends when the implementation of the done () method ends. The system will obtain a link object from the link pool. If there is no link, it will be created directly. If the link is created, it is added to the pool. Let's take a look at its class diagram below:
The classes circled in the red box in the figure are connpool. the h header file contains the defined class information, and these classes (for example, ScopedDbConnection, as mentioned in the code above) will contain a DBClientBase attribute pointer, while the definition of DBClientBase is located in dbclient. the h header file mainly defines the operations (CRUD) that are frequently performed when the client connects to the mongodb server ).
There are many classes in the figure, mainly including:
ScopedDbConnection: the database connection class in the pool. It applies the crud operation by holding the DBClientBase pointer.
DBConnectionPool: database connection pool class, defining the creation, acquisition, flush, and maintenance of links.
PoolForHost: This object provides stack-based Management of pool linked objects.
The following describes the construction method of ScopedDbConnection. the execution process is as follows:
// Connpool. cpp
ScopedDbConnection: ScopedDbConnection (const Shard & shard)
: _ Host (shard. getConnString (), _ conn (pool. get (_ host )){
}
The _ host (shard. getConnString () only binds the mongo service address to the _ host attribute of ScopedDbConnection. The important thing is _ conn (pool. get (_ host), which obtains a link from the pool (pool type: DBConnectionPool). If the pool does not exist, a link is created and returned, as follows (for details, see the Notes ):
// Connpool. cpp
DBClientBase * DBConnectionPool: get (const ConnectionString & url ){
// Obtain a link object from the pool
DBClientBase * c = _ get (url. toString ());
// Return directly if obtained
If (c ){
OnHandedOut (c); // execute the hook method defined during retrieval
Return c;
}
String errmsg;
C = url. connect (errmsg );
Uassert (13328, _ name + ": connect failed" + url. toString () + ":" + errmsg, c );
// Construct a link object with a url as the link address and return the object
Return _ finishCreate (url. toString (), c );
}
In the above method, the line of code _ get (url. toString () is mainly used to obtain objects from the pool. Its implementation code is as follows:
DBClientBase * DBConnectionPool: _ get (const string & ident ){
Scoped_lock L (_ mutex );
PoolForHost & p = _ pools [ident]; // obtain the specified link pool
Return p. get ();
}
The _ pools type is defined as follows for ing from "server name" to "corresponding link pool", because different servers correspond to different link pools:
Typedef map <string, PoolForHost, serverNameCompare> PoolMap;
After finding the corresponding link pool, return the reference of the PoolForHost object corresponding to the pool. This object provides stack-based Management of pool link objects. The get () method is defined as follows:
// Connpool. cpp
DBClientBase * PoolForHost: get (){
Time_t now = time (0 );
While (! _ Pool. empty ()){
StoredConnection SC = _ pool. top (); // retrieve the top link of the stack.
_ Pool. pop (); // removes the elements at the top of the stack.
If (SC. OK (now) // if the link is idle for less than 1 hour
Return SC. conn;
Delete SC. conn; // release the linked object
}
Return NULL; // if no valid link exists, null is returned.
}
Now let's focus on the following line of code in the main flow DBClientBase * DBConnectionPool: get (const ConnectionString & url) method:
// Connpool. cpp
// Return directly if obtained
If (c ){
OnHandedOut (c); // execute the hook method defined during retrieval
Return c;
}
This method is called by a hook method. Its implementation method is somewhat complicated, much like the Observer (Observer) mode in the setting mode. Let's take a look at the class diagram of this mode first:
For details about this mode, refer to the relevant information or search for it on google. I will not explain it here.
Here we will first look at the specific implementation of this method (the onCreate and onHandedOut methods are similar, Here we only describe onHandedOut ):
Vo