26

I am looking at http://mongodb.github.io/node-mongodb-native/driver-articles/mongoclient.html and when you scroll to the section "A replicaset connect using no acknowledgment by default and readPreference for secondary"

it stated a connection string to replica set like this:

MongoClient.connect("mongodb://localhost:30000,localhost:30001/integration_test_?w=0&readPreference=secondary", function(err, db) {

}

I do not understand why we need to specify 2 hosts. I thought the MongoDB documentation already stated that the replica set is transparent to client. That means, the client just need to connect to the primary replica set and MongoDB will do the job. Hence, the connection should just contain 1 host. MongoDB doc stated that there must be at least 3 hosts in a replica set and this connection string only specified 2 hosts.

In addition, why the connection string is not stating the "replicaSet" ?

Muhammad Tariq
  • 3,318
  • 5
  • 38
  • 42
Mark Thien
  • 1,108
  • 2
  • 22
  • 35
  • 1
    You are specifying more than one host in your connect string to cover the case of the Mongo PRIMARY moving around as physical mongod's come and go (server down, network path makes it unavailable, etc). The more info you give the MongoClient here, the more resilient it is to overcoming the edge cases of a replset operating without all of its members. – Bob Kuhar May 30 '14 at 18:13

2 Answers2

45

The multiple servers in the connection string serve as a seed list for discovering the connection mode. You are correct in that you could just specify the primary server and things would work perfectly. That is, until the primary server goes down or is very busy. By specifying multiple machines in the connection string, you give the client more than one location to query for the replica set configuration.

When the connection mode resolves to a replica set (see more below), the driver will find the primary server even if it is not in the seed list, as long as at least one of the servers in the seed list responds (the response will contain the full replica set and the name of the current primary). In addition, other secondaries will also be discovered and added (or removed) into the mix automatically, even after initial connection. This will enable you to add and remove servers from the replica set and the driver will handle the changes automatically.

To answer your final question, because specifying multiple servers is ambiguous as to whether or not it is a replica set or multiple mongos (in a sharded setup), the driver will go through a discovery phase of connecting to the servers to determine their type. This has a little overhead at connection time and can be avoided by specifying a connection mode in the connection string - hence the replicaSet keyword. So while it is not necessary, it can speed up your connection times to explicitly state the servers are in a replica set in the connection string.

Brian Knight
  • 4,970
  • 28
  • 34
  • 2
    In my experience, the problem isn't when "the primary goes down or is very busy" that is the problem with just specifying the current primary in the connect string is if this single server is down at the time your application is trying to build a MongoClient. In all of our applications, the MongoClient is established once and maintained by a Singleton. As the primary moves around, the MongoClient tracks it. On the other hand, we always specify the whole collection of replica set seeds to cover the "application restart" case. – Bob Kuhar May 30 '14 at 18:09
  • 1
    How about an arbiter? If I have 5 MongoDB servers, one of which is an arbiter, should that arbiter be in the list of servers of the MongoClient connect string? An arbiter stores no data so it cannot serve any data, and can never become the primary. Though it should know which server is the Primary. – Crash Override Apr 30 '17 at 19:20
4

Since MongoDB 3.6 one can use DNS Seedlist Connection Format.

For example,
mongodb+srv://server.example.com/ might turn into to the following connection string mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/?replicaSet=mySet&authSource=authDB.

Once your records are set up, you can easily change port numbers without impacting clients and also add and remove cluster members

Muhammad Tariq
  • 3,318
  • 5
  • 38
  • 42
silk
  • 131
  • 4
  • Want to confirm that `mongodb1.example.com` is the hostname of the machine, right ? – Muhammad Tariq Mar 12 '21 at 08:35
  • It’s just a hostname that corresponds to a DNS SRV record. You should set up the DNS names for your nodes (for instance in AWS Route 53). As an example, here is a MongoDB Atlas connection string: `mongodb+srv://:@cluster0.q3qpe.mongodb.net/myFirstDatabase?retryWrites=true&w=majority` for these 3 nodes: `cluster0-shard-00-01.q3qpe.mongodb.net:27017`, `cluster0-shard-00-00.q3qpe.mongodb.net:27017`, `cluster0-shard-00-02.q3qpe.mongodb.net:27017` – silk Mar 12 '21 at 14:46