As for how to handle node.js service connection to MongoDB, I have looked up a lot of Chinese and English materials, and found that there is no solution that is quite suitable for my expected capabilities, so after some official documentation research, The following method of connecting MongoDB is summarized (using the MongoDB ODM Mongoose, which is most commonly used in Node.js platform), and it is boldly called “best practice”, hoping to throw a spark and get more professional answers. Without further ado, first the code:

const mongoose = require('mongoose')
const config = require('./config')


if (process.env.NODE_ENV === 'development') {
  mongoose.set('debug'.true)    /* A */
}

mongoose.set('bufferCommands'.false)  /* B */

function connectMongoDB(address) {
  try {
    mongoose.connect(address, { 
      useNewUrlParser: true.bufferMaxEntries: 0   /* B */
      autoReconnect: true   /* C, default is true, you can ignore it */
      poolSize: 5           /* D, default is 5, you can ignore it */
    })
    
    const db = mongoose.connection
    db.on('error', (error) => {
      console.log(`MongoDB connecting failed: ${error}`)
    })
    db.once('open', () = > {console.log('MongoDB connecting succeeded')})return db
  } catch (error) {
    console.log(`MongoDB connecting failed: ${error}`)}}const mongoInstance = connectMongoDB(config.database.mongo)
module.exports = {
    mongoInstance
}
Copy the code

This set of connections can meet the following requirements, which are also summarized from the requirements that my service needs to meet:

  1. The development environment can print detailed database operation information
  2. After the database is disconnected, all the commands related to database read and write operations return an error immediately, instead of waiting for reconnection, which causes the interface to time out
  3. After the service is started and successfully connected to the database, if the database is interrupted due to a fault, the service automatically tries to reconnect the database until the connection is successful
  4. No manual handling of connection counts is required

Let’s look at the configuration for each requirement piece by piece:

  1. See note A, set ‘debug’ to true in the development environment and the database will print collection methods and arguments to the console.
  2. See note B in two places, here is a passage from the Mongoose documentbufferMaxEntriesExplanation:

bufferMaxEntries – The MongoDB driver also has its own buffering mechanism that kicks in when the driver is disconnected. Set this option to 0 and set bufferCommands to false on your schemas if you want your database operations to fail immediately when the driver is not connected, as opposed to waiting for reconnection.

The idea is that setting bufferMaxEntries to 0 and bufferCommands to false will cause drivers to fail immediately if they do not connect to the database, rather than waiting to reconnect. In my opinion, this is a better experience than waiting for the database to reconnect until the response times out.

  1. See note C, this is actually the default setting of Mongoose. Its config parameter autoReconnect defaults to true when connecting to the database. See the documentation for its meaning:

autoReconnect – The underlying MongoDB driver will automatically try to reconnect when it loses connection to MongoDB. Unless you are an extremely advanced user that wants to manage their own connection pool, do not set this option to false.

If you are not an advanced user, do not change this parameter.

  1. See note D. For MongoDB connection pooling problems, it is recommended not to handle them manually. Mongoose itself maintains a connection pool with a default maximum of 5, and you should only consider increasing poolSize if you find that some slow queries may block fast queries. Of course, this number can not be set too large, MongoDB default is a connection to start a thread to service, too many connections switching system overhead will be very large.

Of course, there is a drawback to this set of “best practices” : if the service fails to connect to the database after initial startup (such as when the database is down), the service does not attempt to reconnect to the database. The solution is to try reconnecting in the ‘error’ event listener callback of the Mongoose connection. However, you need to set the maximum retry times; otherwise, memory leaks occur. The tricky part is that if the first connection doesn’t work, trying to reconnect a few times in a short period of time doesn’t seem to help. Therefore, it is important to keep the database connectable when using this connection method. Or if readers have a better solution, they would like to comment.

To the end.

This article was first published on my blog (click here to view it).