2013-03-28 5 views
21

मैं modeodb (2.2.2) के साथ node.js को देशी node.js ड्राइव का उपयोग करके 10gen तक कोशिश करता हूं।मोंगोब कनेक्शन से निपटने का सही तरीका क्या है?

पहले सब कुछ ठीक हो गया। लेकिन जब समेकन बेंचमार्किंग भाग में आते थे, तो कई त्रुटियां हुईं। लगातार कनेक्ट/बंद 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 का उपयोग करना)

मैंने बहुत कोशिश की है। मैनुअल के मुताबिक, मोंगोडब में कनेक्शन सीमा नहीं है, लेकिन पूलसाइज विकल्प मेरे लिए कोई प्रभाव नहीं पड़ता है।

जैसा कि मैंने नोड-मोंगोड-मूल मॉड्यूल में केवल इसके साथ काम किया है, मुझे पूरा यकीन नहीं है कि अंततः समस्या का कारण क्या हुआ। अन्य भाषाओं और ड्राइवरों में प्रदर्शन के बारे में क्या?

पीएस: वर्तमान में, स्वयं रखरखाव पूल का उपयोग करना एकमात्र समाधान है जिसे मैंने पाया, लेकिन इसका उपयोग करके प्रतिकृति सेट के साथ समस्या का समाधान नहीं हो सकता है। मेरे परीक्षण के मुताबिक, प्रतिकृति सेट लगता है कि स्टैंडअलोन मोंगोडब बहुत कम कनेक्शन लेता है। लेकिन यह नहीं पता कि ऐसा क्यों होता है।

कन्करेंसी परीक्षण कोड:

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); 
      }) 
     } 
    }) 
}) 

उत्तर

22

Node.js के बाद से ही लड़ी आप नहीं खोलने और (आप की तरह प्रत्येक अनुरोध पर कनेक्शन बंद करने की जानी चाहिए अन्य बहु थ्रेडेड वातावरण में करेंगे।)

यह उस व्यक्ति से उद्धरण है जिसने मोंगोडीबी नोड.जेएस क्लाइंट मॉड्यूल लिखा:

"जब आप अपना ऐप बूट करते हैं और डीबी ऑब्जेक्ट का पुन: उपयोग करते हैं तो आप MongoClient.connect खोलते हैं। यह प्रत्येक सिंगलटन कनेक्शन पूल नहीं है। कनेक्ट करें नया कनेक्शन पूल बनाता है। तो यह एक बार एक [घ] खोलने सभी अनुरोध भर में पुन: उपयोग। "- christkv https://groups.google.com/forum/#!msg/node-mongodb-native/mSGnnuG8C1o/Hiaqvdu1bWoJ

+0

हालांकि Node.js एक भी प्रक्रिया और घटना मॉडल, का उपयोग करता है लेकिन आईओ कार्यों हमेशा async होना चाहिए। जो मुझे लगता है कि मेरे मुद्दों का कारण नहीं हो सकता है। लेकिन, मैं उद्धृत तरीके से कोशिश करूंगा, धन्यवाद। – Jack

+2

आप अपने पहले उदाहरण में बिंदु खो रहे हैं; वह कोड आपके मोंगो ऐप को 1000 बार शुरू करने के बराबर है। आपको केवल अपने ऐप में एक बार कनेक्ट होना चाहिए। –

+0

हां, यह समस्या है, और कारण मोंगो क्लाइंट एक कनेक्शन पूल है जो अन्य डीबीएस की तुलना में अधिक महंगा हो जाता है। लेकिन नोड.जेएस एकल प्रक्रिया मॉडल के साथ समस्या नहीं है। – Jack

3

हेक्टर की सलाह में देखने के बाद। मुझे लगता है कि मैंने कभी भी इस्तेमाल किए गए कुछ अन्य डेटाबेस से मोंगोड का कनेक्शन काफी अलग है। मुख्य अंतर यह है NodeJS में देशी की दूरी पर है: MongoClient अपने आप कनेक्शन पूल के लिए प्रत्येक MongoClient खोला है, जो पूल आकार

server:{poolSize: n} 

तो द्वारा परिभाषित किया गया है, poolSize के साथ खुला 5 MongoClient संबंध नहीं है: 100, जिसका मतलब कुल 5 * 100 = लक्ष्य Mongongb उरी के लिए 500 कनेक्शन। इस मामले में, अक्सर खुले & बंद मोंगो क्लाइंट कनेक्शन निश्चित रूप से मेजबान के लिए एक बड़ा बोझ होगा और अंततः कनेक्शन की समस्याएं पैदा करेगा। यही कारण है कि मुझे पहली जगह में इतनी परेशानी मिली।

लेकिन जैसा कि मेरे कोड को इस तरह से लिखा गया है, इसलिए मैं प्रत्येक विशिष्ट यूआरआई के साथ एक कनेक्शन को स्टोर करने के लिए एक कनेक्शन पूल का उपयोग करता हूं, और पूल साइज़ के समान आकार के समान समानांतर लिमिटर का उपयोग करता हूं, लोड पीक से कनेक्शन त्रुटियों से बचने के लिए ।

यहाँ मेरी कोड है:

/*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; 
+0

हैलो, मुझे इस समस्या का सामना करना पड़ा। और क्या आप 'var simple_limit = आवश्यकता (' simple_limit ') से पहले जा सकते हैं। simple_limit; 'simple_limit.js कोड? और 'mongodb_pool' का उपयोग कैसे करें? धन्यवाद ~ – Eddy

संबंधित मुद्दे

 संबंधित मुद्दे