1

I have a mongodb replica set with the following config:

  • M1 primary
  • M2 secondary
  • M3 secondary
  • M4 arbitrator

Here is my Express code to connect to db (I use mongoose as the ODM):

const config = {
  db: `mongodb://${process.env.DB_ADDRESS_1}/${process.env.DB_NAME},
                 ${process.env.DB_ADDRESS_2}/${process.env.DB_NAME},
                 ${process.env.DB_ADDRESS_3}/${process.env.DB_NAME}`,
  dbOptions: {
    server: {
      socketOptions: {
        keepAlive: 1
      },
      poolSize: 5,
      readPreference: 'nearest'
    },
    replSet: {
      rs_name: process.env.REPLICA_SET,
      poolSize: 5,
      readPreference: 'nearest',
      socketOptions: {
        keepAlive: 1,
        connectTimeoutMS: 30000,
        socketTimeoutMS: 0
      }
    },
    db: {
      w: 1,
      numberOfRetries: 2
    }
  }
}
mongoose.connect(config.db, config.dbOptions, (error) => {
  if (error) {
    console.log('Error on connecting to th db: ', error)
    console.log('\x1b[31m', '*** PLEASE CONNECT TO DATABASE BEFORE RUN SERVER', '\x1b[0m')
    process.exit(1)
  }
  callback()
})

The app works as expected. When M1 get down, either M2 or M3 get elected to be the primary, BUT my express app still CAN'T connect to the replica set.

Is there any wrong in my config?

Justin
  • 4,400
  • 2
  • 32
  • 36

2 Answers2

2

Your MongoDB URI connection string is not following the proper format. The database name should be appended after the server list, and not appended on every server. Try:

mongodb://${process.env.DB_ADDRESS_1},
${process.env.DB_ADDRESS_2},
${process.env.DB_ADDRESS_3}
/${process.env.DB_NAME}?replicaSet=${process.env.REPLICA_SET}

See https://docs.mongodb.com/manual/reference/connection-string/#connection-string-options for an example.

On another note, you don't need an arbiter on the replica set. It's not recommended to have an even number of nodes in a replica set, since it requires a majority to elect a primary.

With 4 nodes, if 2 of the nodes are down, the remaining nodes are not able to elect a primary (which is also the case when you have a 3-node replica set). Hence, the additional arbiter doesn't add any value to the replica set. See https://docs.mongodb.com/manual/core/replica-set-architectures/#consider-fault-tolerance for more information.

kevinadi
  • 13,365
  • 3
  • 33
  • 49
  • @Kenvin: could you please take a look at my new issue: https://stackoverflow.com/questions/47478964/express-cant-connect-to-mongodb-replica-set-when-local-mongo-is-stoped thanks! – Justin Nov 24 '17 at 19:18
2

Connection URL should be:

`mongodb://${process.env.DB_ADDRESS_1},${process.env.DB_ADDRESS_2},${process.env.DB_ADDRESS_3}/${process.env.DB_NAME}`

So, there is a list of nodes and after that comes information about the database.

And your setup has one flaw too... When you have three node replica set, you SHOULD NOT have arbitrator as forth! This because, vote count must be odd not even.

JJussi
  • 1,540
  • 12
  • 12
  • Thank you for your helping on the `connection url`. But, as for your advise on the number of nodes, I dont's think so. [Ensure that the replica set has an odd number of voting members](https://docs.mongodb.com/manual/core/replica-set-architectures/#consider-fault-tolerance). I have 3 nodes, when master gone, there are 2 nodes join in voting members, so I think an addition `arbitrator` is the good for the 'odd number of voting members'. – Justin Nov 24 '17 at 10:26
  • It's actually ODD votes, not voting members. Even If one node is down, there is still (in the configuration) information that "should be X nodes" and "majority" is counted from ALL configured members, not those who are up at the current moment. So the voting result is "up members / all votes". When one node is down, result is 2/3 what fulfill majority. This is just to prevent split brain situation when we have network partitioning. – JJussi Nov 24 '17 at 11:46
  • I still don't understand. I have 2 nodes for voting, and 1 arbitrator, that is 3. Is it wrong? – Justin Nov 24 '17 at 16:36
  • could you please take a look at my new issue: https://stackoverflow.com/questions/47478964/express-cant-connect-to-mongodb-replica-set-when-local-mongo-is-stoped thanks – Justin Nov 24 '17 at 19:18
  • It's not "odd voting members at any situation". It should be written "odd configured votes", because you can have (in replica set) nodes what have zero votes and as I wrote earlier, all configured votes counts and that should be odd value. Arbiters are invented to be used only in the situation where your configuration have even votes. – JJussi Nov 25 '17 at 09:05