Search code examples
node.jsmongodbherokucompose-db

Check queued reads/writes for MongoDB


I feel like this question would have been asked before, but I can't find one. Pardon me if this is a repeat.

I'm building a service on Node.js hosted in Heroku and using MongoDB hosted by Compose. Under heavy load, the latency is most likely to come from the database, as there is nothing very CPU-heavy in the service layer. Thus, when MongoDB is overloaded, I want to return an HTTP 503 promptly instead of waiting for a timeout.

I'm also using REDIS, and REDIS has a feature where you can check the number of queued commands (redisClient.command_queue.length). With this feature, I can know right away if REDIS is backed up. Is there something similar for MongoDB?

The best option I have found so far is polling the server for status via this command, but (1) I'm hoping for something client side, as there could be spikes within the polling interval that cause problems, and (2) I'm not actually sure what part of the status response I want to act on. That second part brings me to a follow up question...

I don't fully understand how the MondoDB client works with the server. Is one connection shared per client instance (and in my case, per process)? Are queries and writes queued locally or on the server? Or, is one connection opened for each query/write, until the database's connection pool is exhausted? If the latter is the case, it seems like I might want to keep an eye on the open connections. Does the MongoDB server return such information at other times, besides when polled for status?

Thanks!


Solution

  • MongoDB connection pool workflow-

    Every MongoClient instance has a built-in connection pool. The client opens sockets on demand to support the number of concurrent MongoDB operations your application requires. There is no thread-affinity for sockets.

    The client instance, opens one additional socket per server in your MongoDB topology for monitoring the server’s state.

    The size of each connection pool is capped at maxPoolSize, which defaults to 100.

    When a thread in your application begins an operation on MongoDB, if all other sockets are in use and the pool has reached its maximum, the thread pauses, waiting for a socket to be returned to the pool by another thread.

    You can increase maxPoolSize:

    client = MongoClient(host, port, maxPoolSize=200)
    

    By default, any number of threads are allowed to wait for sockets to become available, and they can wait any length of time. Override waitQueueMultiple to cap the number of waiting threads. E.g., to keep the number of waiters less than or equal to 500:

    client = MongoClient(host, port, maxPoolSize=50, waitQueueMultiple=10)
    

    Once the pool reaches its max size, additional threads are allowed to wait indefinitely for sockets to become available, unless you set waitQueueTimeoutMS:

    client = MongoClient(host, port, waitQueueTimeoutMS=100)
    

    Reference for connection pooling- http://blog.mongolab.com/2013/11/deep-dive-into-connection-pooling/