更新:我在驱动程序上使用2.1版本,而不是3.2
我有一个使用MongoDB的节点应用程序。我遇到的问题是,如果MongoDB服务器因任何原因而关闭,则应用程序不会重新连接。 为了做到这一点,我将测试基于this official tutorial中的代码。
var MongoClient = require('mongodb').MongoClient
, f = require('util').format;
MongoClient.connect('mongodb://localhost:27017/test',
// Optional: uncomment if necessary
// { db: { bufferMaxEntries: 3 } },
function(err, db) {
var col = db.collection('t');
setInterval(function() {
col.insert({a:1}, function(err, r) {
console.log("insert")
console.log(err)
col.findOne({}, function(err, doc) {
console.log("findOne")
console.log(err)
});
})
}, 1000)
});
想法是运行此脚本,然后停止mongod,然后重新启动它。 所以,我们走了:
停止MongoDb 10秒会产生预期的结果:它将停止运行10秒的查询,然后在服务器返回ip后运行所有查询
在30秒后,我开始得到:
{ [MongoError: topology was destroyed] name: 'MongoError', message: 'topology was destroyed' }
insert
{ [MongoError: topology was destroyed] name: 'MongoError', message: 'topology was destroyed' }
问题是,从此开始,当我重新启动mongod时,连接不会重新建立。
此问题是否有解决方案?如果是这样,你知道它是什么吗? 一旦我的应用程序开始呕吐“拓扑被破坏”,让一切恢复工作的唯一方法是重新启动整个应用程序......
答案 0 :(得分:22)
有两个连接选项可以控制连接失败后mongo nodejs驱动程序重新连接的方式
reference on mongo driver docs
这意味着mongo将默认尝试连接30次,并在每次重试前等待1秒。这就是你在30秒后开始看到错误的原因。
您应该根据您的需要调整这两个参数,例如此示例。
var MongoClient = require('mongodb').MongoClient,
f = require('util').format;
MongoClient.connect('mongodb://localhost:27017/test',
{
// retry to connect for 60 times
reconnectTries: 60,
// wait 1 second before retrying
reconnectInterval: 1000
},
function(err, db) {
var col = db.collection('t');
setInterval(function() {
col.insert({
a: 1
}, function(err, r) {
console.log("insert")
console.log(err)
col.findOne({}, function(err, doc) {
console.log("findOne")
console.log(err)
});
})
}, 1000)
});
这将尝试60次而不是默认30次,这意味着当它停止尝试重新连接时,您将在60秒后开始看到错误。
旁注:如果您想阻止应用/请求等到重新连接期限到期,您必须通过选项bufferMaxEntries: 0
。这样做的代价是在短暂的网络中断期间请求也会中止。
答案 1 :(得分:5)
默认情况下,Mongo驱动程序将尝试重新连接30次,每秒一次。之后,它将不再尝试重新连接。
您可以将重试次数设置为Number.MAX_VALUE以使其重新连接"几乎永远":
var connection = "mongodb://127.0.0.1:27017/db";
MongoClient.connect(connection, {
server : {
reconnectTries : Number.MAX_VALUE,
autoReconnect : true
}
}, function (err, db) {
});
答案 2 :(得分:3)
"mongodb": "3.1.3"
要为预先建立的连接微调重新连接配置,可以修改reconnectTries
/ reconnectInterval
选项(default values and further documentation here)。
对于初始连接,mongo客户端在遇到错误时不会重新连接(请参阅下文)。 I believe it should,但与此同时,我已经使用the following workaround库(使用指数补偿策略)创建了promise-retry
。
const promiseRetry = require('promise-retry')
const MongoClient = require('mongodb').MongoClient
const options = {
useNewUrlParser: true,
reconnectTries: 60,
reconnectInterval: 1000,
poolSize: 10,
bufferMaxEntries: 0
}
const promiseRetryOptions = {
retries: options.reconnectTries,
factor: 1.5,
minTimeout: options.reconnectInterval,
maxTimeout: 5000
}
const connect = (url) => {
return promiseRetry((retry, number) => {
console.log(`MongoClient connecting to ${url} - retry number: ${number}`)
return MongoClient.connect(url, options).catch(retry)
}, promiseRetryOptions)
}
module.exports = { connect }
Mongo初始连接错误: failed to connect to server [db:27017] on first connect
答案 3 :(得分:2)
它正在发生,因为它可能超过了重试连接限制。重试次数后,它会破坏TCP连接并变为空闲状态。因此,为了增加重试次数,如果增加连接重试之间的差距会更好。
使用以下选项:
""
<强>解决方案:强>
String content = "ALPHA_/image/journal/article?img_id=24810&t=1475128689597_BRAVO";
String regex = "\\/image\\/journal\\/article\\?img_id=\\d+&t=\\d+";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(content);
if (matcher.find()) {
String replacement = matcher.replaceAll("PK");
System.out.println(replacement); // Will print ALPHA_PK_BRAVO
}
答案 4 :(得分:1)
不同版本的驱动程序的行为可能会有所不同。你应该提一下你的驱动版本。
驱动程序版本:2.2.10(最新) mongo db版本:3.0.7
下面的代码将延长mongod可以恢复的时间。
var MongoClient = require('mongodb').MongoClient
, f = require('util').format;
function connectCallback(err, db) {
var col = db.collection('t');
setInterval(function() {
col.insert({a:1}, function(err, r) {
console.log("insert")
console.log(err)
col.findOne({}, function(err, doc) {
console.log("findOne")
console.log(err)
});
})
}, 1000)
}
var options = { server: { reconnectTries: 2000,reconnectInterval: 1000 }}
MongoClient.connect('mongodb://localhost:27017/test',options,connectCallback);
第二个参数可用于传递服务器选项。
答案 5 :(得分:1)
使用mongodb驱动程序3.1.10,您可以将连接设置为
std::for_each(arguments.begin(), arguments.end(),
[&list](std::tuple<std::string, std::type_index, Value> &arg)
{
if (std::get<2>(arg))
list.push_back(std::make_pair(std::get<0>(arg), std::get<2>(arg)));
}
您不必指定MongoClient.connect(connectionUrl, {
reconnectInterval: 10000, // wait for 10 seconds before retry
reconnectTries: Number.MAX_VALUE, // retry forever
}, function(err, res) {
console.log('connected')
})
,因为这是默认设置。
答案 6 :(得分:0)
如果您在模式上使用Mongoose,则值得在下面考虑我的选择,因为在第一次尝试失败后,mongoose不会再尝试隐式重新连接到mongoDB。
请注意,我正在连接到MongoDB API的Azure CosmosDB。在你的机器上,也许在本地机器上。
下面是我的代码。
const mongoose = require('mongoose');
// set the global useNewUrlParser option to turn on useNewUrlParser for every connection by default.
mongoose.set('useNewUrlParser', true);
// In order to use `findOneAndUpdate()` and `findOneAndDelete()`
mongoose.set('useFindAndModify', false);
async function mongoDbPool() {
// Closure.
return function connectWithRetry() {
// All the variables and functions in here will Persist in Scope.
const COSMODDBUSER = process.env.COSMODDBUSER;
const COSMOSDBPASSWORD = process.env.COSMOSDBPASSWORD;
const COSMOSDBCONNSTR = process.env.COSMOSDBCONNSTR;
var dbAuth = {
auth: {
user: COSMODDBUSER,
password: COSMOSDBPASSWORD
}
};
const mongoUrl = COSMOSDBCONNSTR + '?ssl=true&replicaSet=globaldb';
return mongoose.connect(mongoUrl, dbAuth, (err) => {
if (err) {
console.error('Failed to connect to mongo - retrying in 5 sec');
console.error(err);
setTimeout(connectWithRetry, 5000);
} else {
console.log(`Connected to Azure CosmosDB for MongoDB API.`);
}
});
};}
您可能决定在需要通过依赖注入连接到db的任何地方导出并重用此模块。但是相反,我现在只会显示如何访问数据库连接。
(async () => {
var dbPools = await Promise.all([mongoDbPool()]);
var mongoDbInstance = await dbPools[0]();
// Now use "mongoDbInstance" to do what you need.
})();