Version 1.3 of PHP MongoDB
The driver has rewritten the connection processing library. Compared with the previous version, there have been major changes in the persistent connection and connection pool.
Connection management in version 1.2
Version 1.2 of the driver introduces a connection pool. When executing any query, a connection will be requested from the connection pool, and then returned to the connection pool after completion. Completion here means that the variable holding the connection leaves its scope, here is an example.
The simplest version:
demo->test; $c->insert( array( ‘test’ => ‘yes’ ) ); ?>
← $m leaves the scope and the connection is returned to the connection pool
In the function:
demo->test; $c->insert( array( ‘test’ => ‘ yes’ ) ); } // ← $m leaves the scope, the connection is returned to the connection pool ?>
In some cases, the system may generate a large number of connections, such as referencing connection objects in a complex structure of ORMs/ODMs, as in the following example:
<?php for ($i = ; $i
Connection management in version 1.3
In version 1.3, connection management has been greatly changed. Each worker process (thread, PHP-FPM or Apache
worker), the driver separates the connection management from the Mongo* object to reduce the complexity of the driver. The following uses a single node MongoDB instance to illustrate how the driver handles connections.
When a worker process starts, the MongoDB driver will initialize the connection manager to manage the connection, and there is no connection by default.
Call new on the first request
MongoClient();, the driver creates a new connection and identifies the connection with a hash value. This hash value includes the following parameters: hostname, port, process ID and optional
The replica set name, if it is a password-authenticated connection, also includes the hash value of the database name, user name, and password (for password-authenticated connections, we will discuss it in detail later). transfer
MongoClient::getConnections() method, you can view the hash value corresponding to the connection:
<?php $m = new MongoClient( 'mongodb://whisky:27017/’ ); var_dump( $m->getConnections()[][‘hash’] ); ?>
output:
string(22) “whiskey:27017;-;X;22835”
“-” in the output indicates that the connection does not belong to a replica
set, “X” is a placeholder when there is no username, database and password, and 22835 is the process ID of the current process.
Then the connection will be registered in the connection manager:
Whenever a connection is required, including an insert, delete, update, lookup, or execute command, the driver will ask the manager for an appropriate connection to execute. New is used when requesting a connection
The parameters of MongoClient() and the ID of the current process. Each worker process/thread, the connection manager will have a connection list, and each PHP
The worker will only run one request at the same time, so it only needs one connection with each MongoDB, and it will be reused continuously until PHP
The worker terminates or explicitly calls MongoClient::close() to close the connection.
Replica sets
In an environment where replica sets exist, the situation is a bit different. new
In the connection string of MongoClient(), you need to specify multiple hosts and indicate that the replica set is currently being used:
$m = new
MongoClient(“mongodb://whisky:13000,whisky:13001/?replicaSet=seta”);
The replicaSet parameter cannot be omitted, otherwise the driver will think that you are going to connect three different mongos processes.
At instantiation, the driver checks the topology of the replica set. The output of the following example, shown in the call to new
After MongoClient(), all visible data nodes in the replica set register a connection with the manager:
getConnections() as $c ) { echo $c[‘hash’], “\ n”; } ?>
output:
whiskey:13001;seta;X;32315 whiskey:13000;seta;X;32315
Although there is no whiskey:13000 node in the connection string, it has been noted in the managerRegistered two connections:
The manager contains not only connection hashes and TCP/IP
socket, which also holds which node is the master, and the “distance” of each node. The script below displays this additional information;
getConnections() as $c ) { echo $c[‘hash’], “: \n”, ” – {$c[‘connection’][‘connection_type_desc’]}, “, “{$c[‘connection’][‘ping_ms’]} ms\n”; } ?>
output:
whiskey:13001;seta;X;5776: – SECONDARY, 1 ms
whiskey:13000;seta;X;5776: – PRIMARY, 0 ms
The driver divides operations into two types: write operations, including insert, update, delete, and commands; read operations, including find and findOne. By default, if no read preference parameter is set, the manager will always return connections to the primary node. The read preference parameter can be set via setSlaveOkay(), or it can be set in the connection string:
$m = new
MongoClient(“mongodb://whisky:13000,whisky:13001/?replicaSet=seta&readPreference=secondaryPreferred”);
After adding these parameters, the connection string becomes very long, so the PHP driver allows options to be placed in an array and passed as the second parameter:
$options = array( ‘replicaSet’ => ‘seta’, ‘readPreference’ => ‘secondaryPreferred’, ); $m = new MongoClient(“mongodb://whisky:13000,whisky:13001/”, $options);
For each operation, the driver requests an appropriate connection from the manager. For write operations, the primary’s connection is always returned; for read operations, the secondary’s connection is returned if it is available and “not far” away.
Authenticated Connection
If MongoDB has authentication enabled, then the connection hash will contain the authentication-related hash. In this way, different scripts use different usernames and passwords to connect to different servers on the same MongoDB.
When using different databases, they can be distinguished from each other without misuse of connections. The following example uses the admin username to connect to the admin database, and then observe the changes in the hash value:
getConnections()[][‘hash’] ); ?>
output:
string(64)
“whiskey:27017;-;admin/admin/bda5cc70cd5c23f7ffa1fda978ecbd30;8697”
The “X” part in the previous example has been replaced with a string containing the database name admin, the username admin, and the hash bda5cc70cd5c23f7ffa1fda978ecbd30 calculated from the username, database name, and password hash.
For verification to work correctly, you need to include the database name in the connection string, otherwise it will default to admin.
To use a database after establishing a connection, you need to select the database first, such as:
$collection = $m->demoDb->collection;
$collection->findOne();
If the selected database is the one specified in the connection string, or the database in the connection string is admin, everything works fine. Otherwise, the driver creates a new connection, preventing authentication from being bypassed, as follows:
test2; $collection = $db->collection; var_dump( $collection-> findOne() ); ?>
output:
Fatal error: Uncaught exception ‘MongoCursorException’ with
message ‘whisky:27017: unauthorized db:test2 ns:test2.collection
lock type:0 client:127.0.0.1′ in …/mongo-connect-5.php.txt:6
Because our connection did not perform the authorization verification of the test2 database, it failed. If we perform validation, it works fine:
test2; $db->authenticate(‘user2’, ‘user2’ ); $collection = $db->collection; $collection->findOne(); foreach ( $m->getConnections() as $c ) { echo $c[‘hash’], “\n”; } ?>
output:
whiskey:27017;-;test/user/602b672e2fdcda7b58a042aeeb034376;26983
whiskey:27017;-;test2/user2/984b6b4fd6c33f49b73f026f8b47c0de;26983
There are now two authenticated connections in the manager:
By the way, if you turn on E_DEPRECATED level error prompts, you will see:
Deprecated: Function MongoDB::authenticate() is deprecated in
…/mongo-connect-6.php.txt on line 5
The driver recommends creating two MongoClient objects to accomplish this type of task:
false ) ); $mTest2 = new MongoClient( ‘mongodb://user2:user2 @whisky:27017/test2’, array( ‘connect’ => false ) ); $mTest1->test->test->findOne(); $mTest2->test2->test->findOne(); foreach( $ mTest2->getConnections() as $c ) { echo $c[‘hash’], “\n”; } ?>
The concurrent connections that a single MongoDB server can support are quite limited. If PHP-FPM is used, each worker process has its own independent connection pool, so it is easy to reach the number of connections
upper limit. Therefore, in the production environment, regardless of whether the replica set is used or not, mongos must be deployed, and then PHP-FPM connects to mongos, which can reduce the number of mongod connections and
And short connections can be used between PHP-FPM and mongos (that is, the close function is explicitly called to close the MongoDB connection at the end of each request).
output:
whiskey:27017;-;test/user/602b672e2fdcda7b58a042aeeb034376;26983
whiskey:27017;-;test2/user2/984b6b4fd6c33f49b73f026f8b47c0de;26983
There are now two authenticated connections in the manager:
By the way, if you turn on E_DEPRECATED level error prompts, you will see:
Deprecated: Function MongoDB::authenticate() is deprecated in
…/mongo-connect-6.php.txt on line 5
The driver recommends creating two MongoClient objects to accomplish this type of task:
false ) ); $mTest2 = new MongoClient( ‘mongodb://user2:user2 @whisky:27017/test2’, array( ‘connect’ => false ) ); $mTest1->test->test->findOne(); $mTest2->test2->test->findOne(); foreach( $ mTest2->getConnections() as $c ) { echo $c[‘hash’], “\n”; } ?>
The concurrent connections that a single MongoDB server can support are quite limited. If PHP-FPM is used, each worker process has its own independent connection pool, so it is easy to reach the number of connections
upper limit. Therefore, in the production environment, regardless of whether the replica set is used or not, mongos must be deployed, and then PHP-FPM connects to mongos, which can reduce the number of mongod connections and
And short connections can be used between PHP-FPM and mongos (that is, the close function is explicitly called to close the MongoDB connection at the end of each request).