Gary Kipnis Gary Kipnis - 4 months ago 13
Node.js Question

MongoDB Replica Connections from NodeJS

My NodeJS client is able to connect to the MongoDB primary server and interact with it, as per requirements.

I use the following code to build a Server Object

var dbServer = new Server(
host, // primary server IP address
port,
{
auto_reconnect: true,
poolSize: poolSize
});


and the following code to create a DB Object:

var db = new Db(
'MyDB',
dbServer,
{ w: 1 }
);


I was under the impression, that when the primary goes down, the client will automatically figure out that it now needs to talk to one of the secondaries, which will be elected to be a primary.

But when I manually kill the primary server, one of the secondary servers does become the primary (as can be observed from its mongo shell and the fact that it now responds to mongo shell commands), but the client doesn't automatically talk to it. How do I configure NodeJS server to automatically switch to the secondary?

Do, I need to specify all 3 server addresses somewhere? But that doesn't seem like a good solution, as once the primary is back on line, it's IP address will be different from what it originally was.

I feel that I am missing something very basic, please enlighten me :)

Thank You,
Gary

Answer

Well your understanding is part there but there are some problems. The general premise of assigning more than a Single server in the connection is that should that server address be unavailable at the time of connection, then something else from the "seed list" will be chosen in order to establish the connection. This removes a single point of failure such as the "Primary" being unavailable at this time.

Where this is a "replica Set" then the driver will discover the members once connected and then "automatically" switch to the new "Primary" as that member is elected. So this does require that your "replica Set" is actually capable of electing a new "Primary" in order to switch the connection. Additionally, this is not "instantaneous", so there can be a delay before the new "Primary" is promoted and able to accept operations.

Your "auto_reconnect" setting is also not doing what you think it is doing. All this manages is that if a connection "error" occurs, the driver will "automatically" retry the connection without throwing an exception. What you likely really want to do is handle this yourself as you could end up infinitely retrying a connection that just cannot be made. So good code would take this into account, and manage the "re-connect" attempts itself with some reasonably handling and logging.

Your final point on IP addresses is generally addressed by using hostnames that resolve to an IP address where those "hostnames" never change, regardless of what they resolve to. This is equally important for the driver as it is for the "replica set" itself. As indeed if the server members are looking for another member by an IP address that changes, then they do not know what to look for.

So the driver will "fail over" or otherwise select a new available "Primary", but only within the same tolerances that the servers can also communicate with each other. You should seed you connections as you cannot guarantee which node is the "Primary" when you connect. Finally you should use hostnames instead of IP addresses if the latter is subject to change.

The driver will "self discover", but again it is only using the configuration available to the replica set in order to do so. If that configuration is invalid for the replica set, then it is invalid for the driver as well.

Example:

MongoClient.connect("mongodb://member1,member2,member3/database", function(err,db) {

})

Or other with an array of Server objects instead.