MongoDB에 안정적으로 다시 연결
업데이트: 드라이버에서 3.2에 대해 2.1 버전을 사용하고 있습니다.
MongoDB를 사용하는 노드 애플리케이션이 있습니다.제가 가지고 있는 문제는 어떤 이유로든 MongoDB 서버가 다운되면 애플리케이션이 다시 연결되지 않습니다.이 문제를 해결하기 위해, 저는 이 공식적인 튜토리얼의 코드를 기반으로 테스트를 진행했습니다.
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를 중지하고 다시 시작하는 것입니다.자, 이제 시작합니다.
테스트 1: mongod를 10초간 정지시킵니다.
MongoDb를 10초 동안 중지하면 원하는 결과가 나옵니다. 10초 동안 쿼리 실행을 중지하고 서버가 back ip가 되면 쿼리를 모두 실행합니다.
테스트 2: mongod를 30초 동안 정지
정확히 30초 후에 다음 메시지가 표시됩니다.
{ [MongoError: topology was destroyed] name: 'MongoError', message: 'topology was destroyed' }
insert
{ [MongoError: topology was destroyed] name: 'MongoError', message: 'topology was destroyed' }
문제는 지금부터 mongod를 다시 시작하면 연결이 다시 설정되지 않는다는 것입니다.
해결책?
이 문제에 해결책이 있습니까?만약 그렇다면, 여러분은 그것이 무엇인지 알고 있나요?일단 내 앱이 "topology was destropped"를 토하기 시작하면, 모든 것을 다시 작동시키는 유일한 방법은 전체 앱을 다시 시작하는 것입니다.
연결 실패 후 mongo nodejs 드라이버를 다시 연결하는 방법을 제어하는 두 가지 연결 옵션이 있습니다.
- reconnectTries: 재연결 시도 횟수(기본값 30회)
- 다시 연결간격:서버가 재시도 간격(기본값 1000ms) 동안 대기합니다.
즉, mongo는 기본적으로 30번 연결을 계속 시도하고 재시도할 때마다 1초 동안 기다립니다.그렇기 때문에 30초 후에 오류가 나타나기 시작합니다.
당신은 이 샘플과 같이 당신의 필요에 따라 이 2개의 파라미터를 수정해야 합니다.
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)
});
기본 30번 대신 60번 시도합니다. 즉, 60초 후에 다시 연결 시도가 중지되면 오류가 표시됩니다.
. : " / 청 요 이 참 앱 때 기 는 리 려 면 방 하 합 지 다 통 야 니 옵 을 고 션 해 과 것 다 을 연 지 시 다 까 기 만 결 료 될 간 이 ▁the ▁option / ▁sid ▁if ▁pass ▁from ▁to 참 : en request ▁app ▁you ▁have 요 ▁the ▁untilbufferMaxEntries: 0
이에 대한 대가는 짧은 네트워크 중단 동안에도 요청이 중단된다는 것입니다.
json:"mongodb": "3.1.3"
기존 연결 다시 연결
설정된에 대한 하려면 미설정연된연결구미면조려를 할 수 .reconnectTries
/reconnectInterval
옵션(기본값 및 여기서 추가 설명서)을 참조하십시오.
초기 연결 다시 연결
초기 연결의 경우 오류가 발생하면 mongo 클라이언트가 다시 연결되지 않습니다(아래 참조).그렇게 해야 한다고 생각하지만, 그 사이에 라이브러리를 사용하여 다음과 같은 해결 방법을 만들었습니다(지수적 백오프 전략 사용).
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
기본적으로 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) {
});
mongodb 드라이버 3.1.10을 사용하여 다음과 같이 연결을 설정할 수 있습니다.
MongoClient.connect(connectionUrl, {
reconnectInterval: 10000, // wait for 10 seconds before retry
reconnectTries: Number.MAX_VALUE, // retry forever
}, function(err, res) {
console.log('connected')
})
지정할 필요가 없습니다.autoReconnect: true
기본값이기 때문입니다.
연결 재시도 제한을 초과했을 수 있기 때문에 발생한 것입니다.재시도 횟수가 많으면 TCP 연결이 끊어지고 유휴 상태가 됩니다.따라서 재시도 횟수를 늘리고 연결 재시도 간격을 늘리는 것이 좋습니다.
아래 옵션 사용:
retryMiliSeconds {Number, default:5000}, number of milliseconds between retries.
numberOfRetries {Number, default:5}, number of retries off connection.
자세한 내용은 이 링크 https://mongodb.github.io/node-mongodb-native/driver-articles/mongoclient.html 를 참조하십시오.
솔루션:
MongoClient.connect("mongodb://localhost:27017/integration_test_?", {
db: {
native_parser: false,
retryMiliSeconds: 100000,
numberOfRetries: 100
},
server: {
socketOptions: {
connectTimeoutMS: 500
}
}
}, callback)
드라이버 버전에 따라 동작이 다를 수 있습니다.드라이버 버전을 언급해야 합니다.
드라이버 버전 : 2.2.10 (하드웨어) mongob 버전 : 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);
두 번째 인수를 사용하여 서버 옵션을 전달할 수 있습니다.
만약 당신이 당신의 스키마에 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.
})();
언급URL : https://stackoverflow.com/questions/39785036/reliably-reconnect-to-mongodb
'source' 카테고리의 다른 글
그룹화 기능(적용, 기준, 집계) 및 *적용 제품군 (0) | 2023.07.06 |
---|---|
Array .find() 메서드 매개 변수가 vuex에 정의되지 않았습니다. (0) | 2023.07.06 |
main 앞에 함수 호출 (0) | 2023.07.01 |
ASP.NET MVC에서 비동기 메서드를 실행하고 잊습니다. (0) | 2023.07.01 |
Python 프로젝트에서 단일 실행 파일 생성 (0) | 2023.07.01 |