14

I tried to connect to MongoDB replicaSet via mongoose. I used this link.
Configuration json:

"mongoose": {
   "uri": "mongodb://localhost:27022/chat,localhost:27021,localhost:27020",
   "options": {
       "replset": { "rs_name": "rs0" },
       "server": {
           "poolSize": 3,
           "socketOptions": {
               "keepAlive": 1
           }
       }
    }
}

Mongoose connect:

var mongoose = require('mongoose');
mongoose.connect(config.get('mongoose:uri'), config.get('mongoose:options'));

And after launching application i got exception:

Error: host must be specified [undefined]
at new exports.ConnectionPool (c:\Users\lor1an\Downloads\prj_chat-master\prj_chat-master\node_modules\mongodb\lib\mongodb\connection\connection_pool.js:18:11)
at Server.connect (c:\Users\lor1an\Downloads\prj_chat-master\prj_chat-master\node_modules\mongodb\lib\mongodb\connection\server.js:335:25)
at Db.open (c:\Users\lor1an\Downloads\prj_chat-master\prj_chat-master\node_modules\mongodb\lib\mongodb\db.js:264:23)
at MongoStore._open_database (c:\Users\lor1an\Downloads\prj_chat-master\prj_chat-master\node_modules\connect-mongo\lib\connect-mongo.js:174:15)
at MongoStore._get_collection (c:\Users\lor1an\Downloads\prj_chat-master\prj_chat-master\node_modules\connect-mongo\lib\connect-mongo.js:169:14)
at MongoStore.get (c:\Users\lor1an\Downloads\prj_chat-master\prj_chat-master\node_modules\connect-mongo\lib\connect-mongo.js:213:10)
at Object.session [as handle] (c:\Users\lor1an\Downloads\prj_chat-master\prj_chat-master\node_modules\connect\node_modules\express-session\index.js:215:11)
at next (c:\Users\lor1an\Downloads\prj_chat-master\prj_chat-master\node_modules\connect\lib\proto.js:194:15)
at Object.module.exports [as handle] (c:\Users\lor1an\Downloads\prj_chat-master\prj_chat-master\middleware\resExtensions.js:21:2)
at next (c:\Users\lor1an\Downloads\prj_chat-master\prj_chat-master\node_modules\connect\lib\proto.js:194:15)

Db: chat, primary server: localhost:27022.

Also I tried remove two other servers (keeping only the primary one in config json) and I saw that it knows about the secondary servers (I used log). I think it's about mongodb meta-data. But when I shutdown primary one, it finished its work (no wonder), I need it so it can use the secondary one instead.
Any ideas?

lor1an
  • 654
  • 2
  • 6
  • 14

4 Answers4

17

We use this:

if(config.db.indexOf('replicaSet') > - 1) {
  dbOptions = {
    db: {native_parser: true},
    replset: {
      auto_reconnect:false,
      poolSize: 10,
      socketOptions: {
        keepAlive: 1000,
        connectTimeoutMS: 30000
      }
    },
    server: {
      poolSize: 5,
      socketOptions: {
        keepAlive: 1000,
        connectTimeoutMS: 30000
      }
    }
  };
}

var db = mongoose.connect(config.db, dbOptions);

where

config.db =  'mongodb://USER:PW@host1:port1,host2:port2/DBNAME?replicaSet=RSNAME'

Auto_reconnect is off as per https://team.goodeggs.com/reconnecting-to-mongodb-when-mongoose-connect-fails-at-startup-83ca8496ca02

malix
  • 3,566
  • 1
  • 31
  • 41
  • 1
    @lor1an As pointed out in this answer, your dbname should come *after* the list of host:ports. So your connection string should be: `mongodb://localhost:27022,mongodb://localhost:27021,mongodb://localhost:27020/chat` – MForMarlon Mar 11 '15 at 21:43
  • 1
    Note that keepAlive is a number, not a boolean value, that represents the number of ms the connection needs to timeout until a new connection is made. For this reason, setting it to 1 is a very bad idea because mongoose will make new connections when it actually shouldn't. – Andrew Rasmussen Mar 18 '16 at 21:29
  • I had this enabled in production and my application was making thousands of connections and it constantly took my DB down, causing it to step down and switch to my replica (and back, etc.). Highly recommended to set keepAlive to a larger value such as 1000. – Andrew Rasmussen Mar 18 '16 at 21:29
  • 2
    @arasmussen yeah but i think connectTimeoutMS is the number of ms the connection needs to timeout until a new connection is made. but i dont know what is this keep alive and, also malix can you please tell me why we have to set auto_reconnect: as false ?? – Sudhanshu Gaur Mar 25 '16 at 18:41
  • 1
    then why have you set auto_reconnect false ?? – Sudhanshu Gaur Mar 25 '16 at 20:24
  • Our app's domain restarts on connection failure. – malix Mar 26 '16 at 14:43
  • That link about auto_reconnect is broken. – UpTheCreek Jan 10 '18 at 15:05
  • 1
    @UpTheCreek fixed – malix Jan 11 '18 at 20:03
8

I had trouble with this too. What I learned from the experience is:

The "server" block is only invoked when the connection URI contain a single non clustered connection (aka a single connection string).

The "replset" block is only invoked when the connection URL contains a list of comma separated connection strings (aka replication set).

var options = {

    db: {
        native_parser: true
    },

    // This block gets run for a non replica set connection string (eg. localhost with a single DB)
    server: {
        poolSize: 5,
        reconnectTries: Number.MAX_VALUE,
        ssl: false,
        sslValidate: false,
        socketOptions: {
            keepAlive: 1000,
            connectTimeoutMS: 30000
        }
    },

    // This block gets run when the connection string indicates a replica set (comma seperated connections)
    replset: {
        auto_reconnect: false,
        poolSize: 10,
        connectWithNoPrimary: true,
        ssl: true,
        sslValidate: false,
        socketOptions: {
            keepAlive: 1000,
            connectTimeoutMS: 30000
        }
    }
};

This block worked on both localhost and the production env. Hope it helps.

ChrisRich
  • 8,300
  • 11
  • 48
  • 67
7

Your connection string is probably invalid. You should provide URI for every replica set member:

"uri": "mongodb://db0.example.com:27017,db1.example.com:27017,db2.example.com:27017/admin?replicaSet=myRepl"

You should check replica set connection section in the Mongoose documentation.

Christian P
  • 12,032
  • 6
  • 60
  • 71
1
# mongoose connect secondary replicateSet

<pre>
let url = 'mongodb://mongo01:1001,mongo02:1002/db_name?replicaSet=xxx-replica' 
// 1 

let conn = mongoose.createConnection(url, {user:'xxx', pass:'xxx', autoIndex: false, replset: {readPreference: 'secondary'}});

// 2  

let conn = mongoose.createConnection(url, {user:'xxx', pass:'xxx', autoIndex: false});
let schema =  new mongoose.Schema({},{read:'secondary'});
let model = conn.model(modelName, schema);

//3
let conn = mongoose.createConnection(url, {user:'xxx', pass:'xxx', autoIndex: false};
let schema = new mongoose.Schema({});
let model = conn.model(modelName, schema);
model.find().read('secondary').then(info => {});

</pre>
Jack LI
  • 57
  • 4