복붙노트

[MONGODB] MongoDB의 연결을 처리하는 올바른 방법은 무엇입니까?

MONGODB

MongoDB의 연결을 처리하는 올바른 방법은 무엇입니까?

나는 함께 기본 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. ==============================

    1.Node.js를 단일 때문에 당신이 열고 각 요청의 연결 종료해서는 안 스레드 (다른 멀티 스레드 환경에서 할 것 같은합니다.)

    Node.js를 단일 때문에 당신이 열고 각 요청의 연결 종료해서는 안 스레드 (다른 멀티 스레드 환경에서 할 것 같은합니다.)

    이것은 MongoDB를 Node.js를 클라이언트 모듈을 작성한 사람에서 인용 한 것입니다 :

  2. ==============================

    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;
    
  3. from https://stackoverflow.com/questions/15680985/what-is-the-right-way-to-deal-with-mongodb-connections by cc-by-sa and MIT license