[MONGODB] MongoDB의 연결을 처리하는 올바른 방법은 무엇입니까?
MONGODBMongoDB의 연결을 처리하는 올바른 방법은 무엇입니까?
나는 함께 기본 Node.js를가 10gen에 의해 드라이브를 사용하여 MongoDB (2.2.2)와 Node.js를 사용해보십시오.
첫째 모든 것을 잘 갔다. 동시성 벤치마킹 부분에 올 때, 많은 오류가 발생했습니다. 1000 concurrencies와 자주 연결 / 닫기는 MongoDB를 같은 오류로 인해 더 이상 요청을 거부 될 수 있습니다 :
Error: failed to connect to [localhost:27017]
Error: Could not locate any valid servers in initial seed list
Error: no primary server found in set
또한, 명시 적으로 가까운없이 클라이언트 종료를 많이, 그것은 감지하고 그들을 닫습니다 MongoDB를 분 할게요합니다. 어떤 유사한 연결 문제가 발생합니다. (연결 상태를 확인 /var/log/mongodb/mongodb.log 사용)
내가 많이 노력했다. 매뉴얼에 따르면, MongoDB를 연결 제한이 없지만, poolSize 옵션은 나에게 아무런 영향이없는 것으로 보인다.
난 단지 노드 MongoDB의 네이티브 모듈에서 함께 일했다, 나는 매우 확실 결국 문제의 원인을 모르겠어요. 그 외 어떤 다른 언어와 드라이버의 성능에 대한?
PS : 현재, 자기 유지 풀을 사용하는 것은 내가 알아 낸 유일한 해결책이지만, 그것을 사용하여 복제 세트의 문제를 해결할 수 없습니다. 내 테스트에 따르면, 복제 세트는 훨씬 덜 연결을 한 후 독립하여 MongoDB을 보인다. 이런 일이 발생하지만 왜 아무 생각이 없습니다.
동시성 테스트 코드 :
var MongoClient = require('mongodb').MongoClient;
var uri = "mongodb://192.168.0.123:27017,192.168.0.124:27017/test";
for (var i = 0; i < 1000; i++) {
MongoClient.connect(uri, {
server: {
socketOptions: {
connectTimeoutMS: 3000
}
},
}, function (err, db) {
if (err) {
console.log('error: ', err);
} else {
var col = db.collection('test');
col.insert({abc:1}, function (err, result) {
if (err) {
console.log('insert error: ', err);
} else {
console.log('success: ', result);
}
db.close()
})
}
})
}
일반 풀 솔루션 :
var MongoClient = require('mongodb').MongoClient;
var poolModule = require('generic-pool');
var uri = "mongodb://localhost/test";
var read_pool = poolModule.Pool({
name : 'redis_offer_payment_reader',
create : function(callback) {
MongoClient.connect(uri, {}, function (err, db) {
if (err) {
callback(err);
} else {
callback(null, db);
}
});
},
destroy : function(client) { client.close(); },
max : 400,
// optional. if you set this, make sure to drain() (see step 3)
min : 200,
// specifies how long a resource can stay idle in pool before being removed
idleTimeoutMillis : 30000,
// if true, logs via console.log - can also be a function
log : false
});
var size = [];
for (var i = 0; i < 100000; i++) {
size.push(i);
}
size.forEach(function () {
read_pool.acquire(function (err, db) {
if (err) {
console.log('error: ', err);
} else {
var col = db.collection('test');
col.insert({abc:1}, function (err, result) {
if (err) {
console.log('insert error: ', err);
} else {
//console.log('success: ', result);
}
read_pool.release(db);
})
}
})
})
해결법
-
==============================
1.Node.js를 단일 때문에 당신이 열고 각 요청의 연결 종료해서는 안 스레드 (다른 멀티 스레드 환경에서 할 것 같은합니다.)
Node.js를 단일 때문에 당신이 열고 각 요청의 연결 종료해서는 안 스레드 (다른 멀티 스레드 환경에서 할 것 같은합니다.)
이것은 MongoDB를 Node.js를 클라이언트 모듈을 작성한 사람에서 인용 한 것입니다 :
-
==============================
2.헥터의 조언에보고 한 후. 나는 MongoDB를의 연결이 내가 사용하는 다른 데이터베이스는 매우 다르다 찾을 수 있습니다. 가장 큰 차이점은 nodejs에서 기본 드라이브 : MongoClient에 의해 정의 된 풀 사이즈 각 MongoClient 열을 위해 자신의 연결 풀을 가지고
헥터의 조언에보고 한 후. 나는 MongoDB를의 연결이 내가 사용하는 다른 데이터베이스는 매우 다르다 찾을 수 있습니다. 가장 큰 차이점은 nodejs에서 기본 드라이브 : MongoClient에 의해 정의 된 풀 사이즈 각 MongoClient 열을 위해 자신의 연결 풀을 가지고
server:{poolSize: n}
그래서 poolSize 오픈 5 MongoClient 연결 : 100 수단 MongoDB를 대상 URI에 5 * 100 = 500 연결 총. 이 경우, 자주 열고 닫기 MongoClient 연결은 확실히 거대한 호스트에 대한 부담과 마지막으로 연결 문제가 원인 일 것이다. 내가 처음에 너무 많은 문제를 가지고 왜의 그.
내가 피할 부하 피크 GET 연결 오류로, 각각 별개의 URI와 단일 연결을 저장하고 poolSize 같은 크기 제한 간단한 병렬를 사용하여 연결 풀을 사용할 수 있도록하지만 내 코드로, 그런 식으로 writen있다.
여기 내 코드는 다음과 같습니다
/*npm modules start*/ var MongoClient = require('mongodb').MongoClient; /*npm modules end*/ // simple resouce limitation module, control parallel size var simple_limit = require('simple_limit').simple_limit; // one uri, one connection var client_pool = {}; var default_options = { server: { auto_reconnect:true, poolSize: 200, socketOptions: { connectTimeoutMS: 1000 } } } var mongodb_pool = function (uri, options) { this.uri = uri; options = options || default_options; this.options = options; this.poolSize = 10; // default poolSize 10, this will be used in generic pool as max if (undefined !== options.server && undefined !== options.server.poolSize) { this.poolSize = options.server.poolSize;// if (in)options defined poolSize, use it } } // cb(err, db) mongodb_pool.prototype.open = function (cb) { var self = this; if (undefined === client_pool[this.uri]) { console.log('new'); // init pool node with lock and wait list with current callback client_pool[this.uri] = { lock: true, wait: [cb] } // open mongodb first MongoClient.connect(this.uri, this.options, function (err, db) { if (err) { cb(err); } else { client_pool[self.uri].limiter = new simple_limit(self.poolSize); client_pool[self.uri].db = db; client_pool[self.uri].wait.forEach(function (callback) { client_pool[self.uri].limiter.acquire(function () { callback(null, client_pool[self.uri].db) }); }) client_pool[self.uri].lock = false; } }) } else if (true === client_pool[this.uri].lock) { // while one is connecting to the target uri, just wait client_pool[this.uri].wait.push(cb); } else { client_pool[this.uri].limiter.acquire(function () { cb(null, client_pool[self.uri].db) }); } } // use close to release one connection mongodb_pool.prototype.close = function () { client_pool[this.uri].limiter.release(); } exports.mongodb_pool = mongodb_pool;
from https://stackoverflow.com/questions/15680985/what-is-the-right-way-to-deal-with-mongodb-connections by cc-by-sa and MIT license
'MONGODB' 카테고리의 다른 글
[MONGODB] 어떻게 몽구스 모델의 메소드를 정의합니까? (0) | 2019.12.22 |
---|---|
[MONGODB] 몽고없이 유성 (0) | 2019.12.22 |
[MONGODB] 공식 C #을 드라이버를 사용하여 MongoDB에 삽입 (0) | 2019.12.22 |
[MONGODB] 여기서 _id의 배열의 선택 MongoDB를? (0) | 2019.12.22 |
[MONGODB] 쿼리는 MongoDB를 가진 마지막으로 X 분의 데이터를 얻을 수 있습니다 (0) | 2019.12.22 |