2013-04-25 106 views
20

我想通過Mongoose設置MongoDB自動重新連接功能。我試圖通過該選項的每種方式都沒有影響,或者至少不會發射該事件。貓鼬autoReconnect選項

我已經試過:

mongoose.createConnection("mongodb://localhost:27017/test", { auto_reconnect: true }); 
mongoose.createConnection("mongodb://localhost:27017/test", { autoReconnect: true }); 
mongoose.createConnection("mongodb://localhost:27017/test", { server: { auto_reconnect: true } }); 
mongoose.createConnection("mongodb://localhost:27017/test", { server: { autoReconnect: true } }); 

如果其中一個是正確的,應該被觸發reconnected事件,應該在控制檯中記錄的消息,但是這永遠不會發生。

如果在重新連接之前有延遲,有誰知道如何配置它?

在此先感謝

對於任何人尋找到這一點,採取貓鼬庫看看thisthis問題。

+0

autoReconnect的是默認啓用的,所以你不要你不必自己啓用它。另外,對於「重新連接」事件的附加監聽器,您是在模擬實際的重新連接情況? – robertklep 2013-04-26 06:32:55

+0

我將該事件附加到此'createConnection()'調用的返回。我的事件與'connected' /'disconnected'事件正常工作。 – gustavohenke 2013-04-26 12:34:11

+0

那麼你如何測試重新連接? – robertklep 2013-04-26 14:14:44

回答

38

我和你有同樣的問題,而robertklep的解決方案也不適合我。當MongoDB服務停止時,我發現觸發了一個錯誤事件,但connection.readyState仍然是1(連接)。這可能是它沒有自動重新連接的原因。

這是我現在有:

var db = mongoose.connection; 

    db.on('connecting', function() { 
    console.log('connecting to MongoDB...'); 
    }); 

    db.on('error', function(error) { 
    console.error('Error in MongoDb connection: ' + error); 
    mongoose.disconnect(); 
    }); 
    db.on('connected', function() { 
    console.log('MongoDB connected!'); 
    }); 
    db.once('open', function() { 
    console.log('MongoDB connection opened!'); 
    }); 
    db.on('reconnected', function() { 
    console.log('MongoDB reconnected!'); 
    }); 
    db.on('disconnected', function() { 
    console.log('MongoDB disconnected!'); 
    mongoose.connect(dbURI, {server:{auto_reconnect:true}}); 
    }); 
    mongoose.connect(dbURI, {server:{auto_reconnect:true}}); 
+1

在斷開連接時重新連接是錯誤的。相反,你應該監視錯誤,並從那裏重新連接 – Andy 2014-11-19 11:19:30

+4

貓鼬不會因錯誤而斷開連接,所以我必須明確斷開它才能重新連接 – 2014-11-20 11:41:01

+0

對於那些有興趣閱讀**官方貓鼬'連接'文檔**的人。 http://mongoosejs.com/docs/3.0.x/docs/api.html#connection_Connection – zurfyx 2017-01-25 17:58:28

3

確保貓鼬也是要連接到蒙戈的唯一途徑。 在我的情況下,我使用connect-mongo以Express方式存儲會話,但是自v0.4.0起,默認情況下它沒有將auto_reconnect設置爲true。

10

http://bites.goodeggs.com/posts/reconnecting-to-mongodb-when-mongoose-connect-fails-at-startup/

彈撥這爲我工作:

var mongoose = require('mongoose') 
var mongoUrl = "mongodb://localhost:27017/test" 

var connectWithRetry = function() { 
    return mongoose.connect(mongoUrl, function(err) { 
    if (err) { 
     console.error('Failed to connect to mongo on startup - retrying in 5 sec', err); 
     setTimeout(connectWithRetry, 5000); 
    } 
    }); 
}; 
connectWithRetry(); 
+0

這對我有用! – 2014-11-08 00:33:51

1

這裏是一個改進,克萊夫的回答,設置最低連接嘗試之間5秒鐘。

var db = mongoose.connection; 
var lastReconnectAttempt; //saves the timestamp of the last reconnect attempt 
db.on('error', function(error) { 
    console.error('Error in MongoDb connection: ' + error); 
    mongoose.disconnect(); 
}); 
db.on('disconnected', function() { 
    console.log('MongoDB disconnected!'); 
    var now = new Date().getTime(); 
    // check if the last reconnection attempt was too early 
    if (lastReconnectAttempt && now-lastReconnectAttempt<5000) { 
     // if it does, delay the next attempt 
     var delay = 5000-(now-lastReconnectAttempt); 
     console.log('reconnecting to MongoDB in ' + delay + "mills"); 
     setTimeout(function() { 
      console.log('reconnecting to MongoDB'); 
      lastReconnectAttempt=new Date().getTime(); 
      mongoose.connect(dbURI, {server:{auto_reconnect:true}}); 
     },delay); 
    } 
    else { 
     console.log('reconnecting to MongoDB'); 
     lastReconnectAttempt=now; 
     mongoose.connect(dbURI, {server:{auto_reconnect:true}}); 
    } 

}); 
+2

爲什麼你使用'auto_reconnect:true',不應該是'false',如果你手動重新連接,你爲什麼需要將'auto_reconnect'設置爲'true'? – 2016-04-03 11:27:51

+0

'auto_reconnect:true'只在第一次連接成功時按預期工作。由於某種原因,如果第一次連接失敗,驅動程序再也沒有嘗試過。因此,您在這裏找到所有這些解決方法。也就是說,我認爲你可以放棄這個選項,因爲無論如何它默認爲true。 – joeytwiddle 2017-04-17 03:00:26

9

近日,筆者調查與MongoDB VAR Mongoose自動重新連接。這裏有一個問題,當在disconnected事件處理程序中調用mongoose.connect時,它會觸發無限循環。 Why the SIGINT signal is blocked when mongoose auto reconnect

解決方案的一個解決方案可能是mongoose.connect()僅在與MongoDB之前沒有連接時才被調用。 auto_reconnect標誌可能會使貓鼬自動與MongoDB重新連接。這裏是代碼片段。

var mongoose = require('mongoose'); 

var isConnectedBefore = false; 
var connect = function() { 
    mongoose.connect('mongodb://localhost/' + + 'test_dev', {server: { auto_reconnect: true }}); 
}; 
connect(); 

mongoose.connection.on('error', function() { 
    console.log('Could not connect to MongoDB'); 
}); 

mongoose.connection.on('disconnected', function(){ 
    console.log('Lost MongoDB connection...'); 
    if (!isConnectedBefore) 
     connect(); 
}); 
mongoose.connection.on('connected', function() { 
    isConnectedBefore = true; 
    console.log('Connection established to MongoDB'); 
}); 

mongoose.connection.on('reconnected', function() { 
    console.log('Reconnected to MongoDB'); 
}); 

// Close the Mongoose connection, when receiving SIGINT 
process.on('SIGINT', function() { 
    mongoose.connection.close(function() { 
     console.log('Force to close the MongoDB conection'); 
     process.exit(0); 
    }); 
}); 
+0

對我來說這是最好的答案。無限循環是我的問題。謝謝兄弟 – emilioriosvz 2016-08-22 11:24:16

4

只是爲了子孫後代着想,因爲大多數這些答案都老了,你不應該需要處理這個問題的任何更多,因爲現在是烤成的mongodb的NodeJS司機。引述kdmon

...reconnecting is now baked into mongoose and enabled by default. But it might be useful to know that Mongoose by default will only try reconnecting for 30s and then give up. Set the server.reconnectTries option to increase the number of times mongoose will try to reconnect. For example, you can tell mongoose to never stop trying to reconnect like this:

mongoose.connect(uri, { server: { reconnectTries: Number.MAX_VALUE } }); 

See connection docs and server options defaults for details

+0

使用這個標誌的問題是它將貓鼬的調用變成了阻塞調用,即他們不會返回,直到數據庫再次啓動。在我的情況下,我從一個快速應用程序調用貓鼬,我們希望返回一個錯誤,而不是阻止請求。 – Ismael 2016-11-07 14:54:15

+0

我希望這是真的。如果在運行期間連接丟失,這是事實。但是,如果* first *連接嘗試失敗(因爲mongo數據庫已關閉),則驅動程序不會重試。 – joeytwiddle 2017-04-17 03:04:13

2

@克萊夫的answer非常好。儘管如此,由於使用mongoosePromise我每次嘗試失敗後得到以下警告:

(node:18123) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): MongoError: failed to connect to server [localhost:27017] on first connect

ES6版(帶無極)

我還添加了重新連接之間的小超時在這個版本(完全可選),以防止屏幕(或記錄器)被重複消息淹沒。

import mongoose from 'mongoose'; 

mongoose.Promise = Promise; // Set mongoose to use ES6 Promises. 

const dbURI = 'mongodb://127.0.0.1:27017/myDb'; 
const reconnectTimeout = 5000; // ms. 

function connect() { 
    mongoose.connect(dbURI, { auto_reconnect: true }) 
    .catch(() => {}); // Catch the warning, no further treatment is required 
         // because the Connection events are already doing this 
         // for us. 
} 

const db = mongoose.connection; 

db.on('connecting',() => { 
    console.info('Connecting to MongoDB...'); 
}); 

db.on('error', (error) => { 
    console.error(`MongoDB connection error: ${error}`); 
    mongoose.disconnect(); 
}); 

db.on('connected',() => { 
    console.info('Connected to MongoDB!'); 
}); 

db.once('open',() => { 
    console.info('MongoDB connection opened!'); 
}); 

db.on('reconnected',() => { 
    console.info('MongoDB reconnected!'); 
}); 

db.on('disconnected',() => { 
    console.error(`MongoDB disconnected! Reconnecting in ${reconnectTimeout/1000}s...`); 
    setTimeout(() => connect(), reconnectTimeout); 
}); 

connect(); 

Connection事件的進一步信息。

0

閱讀文檔後,我很肯定你有錯誤的選項。連接選項字符串應該是這樣的:

mongoose.connect("mongodb://localhost:27017/db", { 
    socketOptions: { 
     // This option is on by default, but why not set it explicitly 
     autoReconnect: true 
    }, 
    // This options is 1 second by default, its possible the ha 
    // takes longer than 30 seconds to recover. 
    reconnectInterval: 5000, 
    // This options is 30 by default, why not make it 60 
    reconnectTries: 60 
    }) 

查看此頁面出來:http://mongoosejs.com/docs/api.html

+0

選項隨時間而改變。這個問題是在4年前創建的。 – kentor 2017-11-30 09:26:41

0

基於@zangw答案,我已經與這個數據庫初始化函數完成了我的應用程序

const mongoose = require('mongoose') 
const RETRY_TIMEOUT = 3000 

module.exports = function initDB() { 
    mongoose.Promise = global.Promise 
    const options = { 
    autoReconnect: true, 
    useMongoClient: true, 
    keepAlive: 30000, 
    reconnectInterval: RETRY_TIMEOUT, 
    reconnectTries: 10000 
    } 

    let isConnectedBefore = false 

    const connect = function() { 
    return mongoose.connect(process.env.MONGODB_URL, options) 
     .catch(err => console.error('Mongoose connect(...) failed with err: ', err)) 
    } 

    connect() 

    mongoose.connection.on('error', function() { 
    console.error('Could not connect to MongoDB') 
    }) 

    mongoose.connection.on('disconnected', function() { 
    console.error('Lost MongoDB connection...') 
    if (!isConnectedBefore) { 
     setTimeout(() => connect(), RETRY_TIMEOUT) 
    } 
    }) 
    mongoose.connection.on('connected', function() { 
    isConnectedBefore = true 
    console.info('Connection established to MongoDB') 
    }) 

    mongoose.connection.on('reconnected', function() { 
    console.info('Reconnected to MongoDB') 
    }) 

    // Close the Mongoose connection, when receiving SIGINT 
    process.on('SIGINT', function() { 
    mongoose.connection.close(function() { 
     console.warn('Force to close the MongoDB connection after SIGINT') 
     process.exit(0) 
    }) 
    }) 
} 

有一些差異:我添加了一些選項來防止連接關閉問題 - 30次自動重試後沒有重新連接,只是MongoError:拓撲被破壞了任何操作,沒有重新連接;我也已經添加.catch後連接到防止未處理的承諾拒絕):

1

有多個不重試請求阻塞而重試我必須設置bufferMaxEntries: 0

const dbUri = 'mongodb://localhost/some_db'; 
const dbOptions = { 
    useMongoClient: true, 
    autoReconnect: true, 
    reconnectTries: Number.MAX_VALUE, 
    bufferMaxEntries: 0 
}; 

mongoose.connect(dbUri, dbOptions).catch(err => process.exit(1));