2013-09-14 6 views
5

У меня возникли проблемы с одновременным выполнением одновременных запросов с моего простого сервера node.js с помощью mongoDB.Node.js и mongoDB, обслуживающие одновременные запросы

То, что я делаю, отправляет запросы в формате оболочки mongo, анализирует их и отправляет данные из mongoDB.

Но мне кажется, что он не может обслуживать несколько запросов в то же время, по какой-то причине .. (BTW, я использую его локально)

EDIT: я иногда получаю эту ошибку в моей клиентской программе:

"Stream Error. URL: http://localhostlink:1337"

, который я также получить, когда сервер не работает ...

EDIT2: я удалил db.close заявления.

Является ли кластер действительно правильным решением здесь, потому что я просто обновляю приложение, чтобы обслуживать 4 одновременных запроса, которых все равно будет недостаточно.

Должен ли я полностью реорганизовать сервер каким-либо другим способом? Я просто хочу иметь возможность подавать несколько запросов на данные из mongoDB.

EDIT3:

Это нормально, что я сначала создать сервер, а затем подключение к Монго, или я должен создать сервер внутри функции MongoClient.connect (...)?

Это код моего (unoptimised) сервера:

var http = require('http'); 
var qs = require('querystring'); 
var mongo =require('mongodb'); 
var MongoClient = mongo.MongoClient; 
var result; 
var response; 
var ObjectId = require('mongodb').ObjectID; 
var myDb; 



http.createServer(function (request, res) { 
    console.log("creating server..."); 
    MongoClient.connect("mongodb://127.0.0.1:27017/lalal", function(err, db) { 
     if(err) { return console.dir(err); } 
if (request.method == 'POST') { 
     var body = ''; 
     response = res; 
     request.on('data', function (data) { 
      body += data; 
      // 1e6 === 1 * Math.pow(10, 6) === 1 * 1000000 ~~~ 1MB 
      if (body.length > 1e6) { 
      //  FLOOD ATTACK OR FAULTY CLIENT, NUKE REQUEST 
       request.connection.destroy(); 
      } 
     }); 
     request.on('end', function() { 

      var clientData = qs.parse(body); 
      var parts = clientData.data.split("."); 
      var collectionName = parts.shift(); 
      var queryBig = parts.join("."); 
      var queryParts = queryBig.split("("); 
      var method = queryParts[0]; 
      var query = queryParts.join("("); 

      console.log("query:"+query); 
      console.log("method:"+method); 
      console.log("collection:"+collectionName); 

      var callback; 
      switch(method){ 

       case 'find': 
       callback = '.toArray(findCallback);'; 
       break; 
       case 'insert': 
       query = query.substring(0, query.length - 1); 
       callback = ',insertCallback);'; 
       break; 
       case 'remove': 
       query = query.substring(0, query.length - 1); 
       callback = ',removeCallback);' 
       break; 
       case 'save': 
       query = query.substring(0, query.length - 1); 
       callback = ',saveCallback);' 
       break; 
       case 'update': 
       query = query.substring(0, query.length - 1); 
       callback = ',updateCallback);' 
       break; 


      } 
     if(query.indexOf('"_id"') != -1) 
     { 

     var indexHelper = query.indexOf('"_id"')+7; 
     var s = query.substring(indexHelper, query.length); 

     var indexOfQuote = s.indexOf('"') 
     var restOfQuery = s.substring(indexOfQuote+1,s.length); 

     var key = s.substring(0,indexOfQuote); 

     query = query.substring(0,indexHelper-1) + 'new ObjectId("'+key +'")'+restOfQuery; 

     } 
//  Connect to the db 


//  myDb = db; 
     var collection = db.collection(collectionName); 

     var command = 'collection.'+query+callback; 
     console.log("command:"+command); 
     eval(command); 


      function findCallback(err, items){ 

       console.log(items); 

       response.writeHead(200, {'Content-Type': 'text/plain'}); 
       response.end(JSON.stringify(items)); 



      } 

      function insertCallback(err, objects) { 

       console.log(objects); 

       if (err) console.warn(err.message); 
       if (err && err.message.indexOf('E11000 ') !== -1) { 
        response.writeHead(200, {'Content-Type': 'text/plain'}); 
        response.end('"error":"_id already exists"'); 
       } 
       else{ 
        response.writeHead(200, {'Content-Type': 'text/plain'}); 
        response.end(JSON.stringify(objects)); 
       } 


      } 

      function removeCallback(err, numberOfRemovedDocs) { 

       response.writeHead(200, {'Content-Type': 'text/plain'}); 
       response.end(JSON.stringify(numberOfRemovedDocs)); 

      } 

      function saveCallback(err, result) { 

       response.writeHead(200, {'Content-Type': 'text/plain'}); 
       response.end(JSON.stringify(result)); 

      } 

      function updateCallback(err, numberOfUpdatedDocs) { 

       response.writeHead(200, {'Content-Type': 'text/plain'}); 
       response.end(JSON.stringify(numberOfUpdatedDocs)); 

      } 





     }); 
    } 
}); 
}).listen(1337, '127.0.0.1'); 



console.log('Server running at http://127.0.0.1:1337/'); 
+1

Хотя там много кода, и я, разумеется, не просмотрел его полностью, вы должны только открыть соединение с БД один раз и оставить его открытым для жизни процесса узла. – WiredPrairie

+0

Может быть, эта часть «myDb = db;» в MongoClient.connect, откуда возникает проблема? потому что он больше не асинхронен? Потому что я передаю ссылку на глобально доступную переменную, поэтому, когда приходит новый запрос, она принимает значение – deloki

+0

'db.close()' почему вы закрываете соединение? – WiredPrairie

ответ

3

Проблема вы видите, потому что node.js однопоточен. То есть, он будет отправлять один запрос за раз (это действительно хорошо, поскольку он помогает избежать ошибок, вызванных обработкой глобальной переменной). Если вы отправили ответ перед выполнением своих запросов, вы увидите параллельное выполнение запроса. Однако, учитывая то, как вы структурировали свою программу, вам может быть лучше использовать модуль «cluster». В приведенном ниже коде будут запущены четыре одновременных процесса.

var cluster = require('cluster'); 

if (cluster.isMaster) { 
    for (var i = 0; i < 4; i++) { 
     cluster.fork(); 
    } 

    cluster.on('exit', function (worker, code, signal) { 
     cluster.fork(); 
    }); 
} 
else { 
    // run your node.js + MongoDB code here 
} 

PS. Вам не нужно закрывать соединение db при использовании MongoClient.connect, так как этот API использует пул соединений, который управляет вашими подключениями.

+0

Является ли кластер действительно правильным решением здесь? Я просто обновляю свой сервер, чтобы обслуживать 4 одновременных запроса? Для меня все еще недостаточно. – deloki

+1

@deloki Каждый экземпляр кластера имеет свой собственный пул соединений, поэтому может быть до 4 * (размер пула) запросов MongoDB в данный момент времени. Размер пула по умолчанию равен 5, но вы можете сделать его тем большим, каким хотите. – JohnnyHK

+0

@JohnnyHK Хорошо, спасибо. Итак, это лучший способ достижения одновременных запросов БД с отправкой данных ответа как полезной нагрузки? Если бы не то, что было бы лучшим способом? – deloki

Смежные вопросы