A large proportion of support requests to MongoLab are questions about how to properly configure and use a particular MongoDB driver.
This blog post is the third of a series where we are covering each of the major MongoDB drivers in depth. The driver we'll be covering here is the PHP driver, developed and maintained by the MongoDB, Inc. team (primarily @derickr, @bjori and @jmikola).
In this post:
The PHP MongoDB driver
This post aims to help you understand how to configure and use the PHP driver effectively in your MongoDB application. For your reference, you can find the complete documentation for the PHP driver on the PHP community site.
A simple PHP example
You can find a straightforward example on connecting, inserting, updating and querying using the PHP driver in MongoLab's Language Center.
Production-ready connection settings
We often see incorrect configurations of the driver, particularly around timeouts and replica set connections. To help you connect to MongoLab (or any cloud MongoDB) using the PHP driver, we've provided the following MongoLab-recommended settings:
Additional connection options that are supported by the PHP driver can be found here.
PHP driver tips & tricks
Index builds can sometimes block new connections
When establishing a connection to a MongoDB replica set, the driver first attempts to connect and authenticate to each non-hidden node in the cluster. If a node is "down", it will be passed over. However, if a node is "up" but holding the write lock such that the 'authenticate' command cannot execute, the driver will then hang. This is common when building indexes since, in all MongoDB versions before 2.6, all index builds (background or foreground) will build in the foreground on secondaries.
In version 1.5.3 of the PHP driver (to be released soon) there will be an improvement that allows the driver to bypass authentication to the secondary node building an index. Please note that this only applies if the secondary is undergoing an Initial Sync. A further release will address this issue during any type of foreground index build.
Consider lowering is_master_interval from its default
For applications with demanding availability requirements, we recommend examining the default PHP driver runtime configuration settings (set in the php.ini file). In particular, the mongo.is_master_interval option controls how quickly the driver can recover after replica set cluster elections.
The is_master_interval option (default: 15 seconds) sets the interval that the driver sends "isMaster" requests to each mongod instance. These requests help the driver determine the topology of the replica set; specifically, the request checks to see if a specific node is the primary and can receive writes.
We recommend experimenting with lowering this value to 1 or 2 seconds so that your driver can quickly locate a primary after an election or failover. Of course, depending on how many clients you have you will want a value that does not ping your servers too often.
Also keep in mind that when an election or failover results in a change in the primary server, there will always be a few seconds where your driver will receive a "MongoConnectionException" with message "No candidate servers found." It's important to handle these exceptions in your code so that your application does not terminate.
Understand how connections are handled and configure connectionTimeoutMS
The PHP driver does not use connection pooling. Therefore it is recommended that you create one connection to your database per PHP process.
However, if you are building a web application it is likely that you will have many PHP worker processes (and in the worst-case a new PHP process per HTTP request). This creates a scenario where you are potentially creating a lot of new database connections, since the PHP driver cannot share connections between processes. Because of this, PHP apps can be especially vulnerable to temporary conditions that impede the creation of initial database connections (network blips, busy servers, etc...).
To help in this regard we recommend that you customize the connectionTimeoutMS option and be aware of the mongo.ping_interval option in php.ini.
The PHP driver does not explictly define a default connection timeout. Instead, the default value is determined by the default_socket_timeout setting in the php.ini file (default: 60 seconds). With this default, your driver will wait up to 60 seconds while connecting before timing out. Given that each request may have to endure this timeout, you may want to lower it.
We highly recommend explicitly setting the connectionTimeoutMS option via connection string URI options. One approach is to experiment with values between 5 to 30 seconds. Another approach would be to configure your connection timeout to 1 second and then upon retry progressively increase the timeout value to 30 seconds.
The second setting to be aware of is mongo.ping_interval, which is set in the php.ini file and has a default value of 5 seconds. This option sets the interval that the driver sends ping requests to each mongod instance to find a "down" node. mongo.ping_interval is used in conjunction with the PHP driver's concept of a server "blacklist", which tracks these "down" nodes.
The PHP driver server "blacklist" tells the driver which nodes it should ignore (not connect to) for ping_interval seconds. In a case where the ping_interval value is 5, the driver will attempt to connect to a "down" node (we'll call it node X), timeout, then move on to the next node. Since this connection timed out, the driver adds node X to the "blacklist". New connections will now know to bypass node X. After 5 seconds, the blacklist is cleared and new connections will attempt to connect to node X once again.
We don't have a specific recommendation for mongo.ping_interval, however the concepts behind it are good to know if you're using the driver in production.
You're all set!
We hope this post helps you make the most out of the PHP driver. If you have any tips and tricks that you'd like to share please post in comments or write to us at firstname.lastname@example.org so we can pass on the knowledge. Happy hacking!