2012-08-03 22 views
32

Esto es algo que no está claro para mí (estoy empezando con Node y Mongo), y realmente me preocupa por el rendimiento y la tensión del servidor (que supongo que es otra pregunta, pero llegaré a eso al final de la publicación).¿Cuál es la mejor práctica para las conexiones de MongoDB en Node.js?

Así, suponiendo que estoy escribiendo una API con Node.js y Restify, donde cada punto final de la API corresponde a una función, debería:

a) abrir la conexión db y almacenarlo en un mundial var, y luego solo usar eso en cada función?
Ejemplo:

// requires and so on leave me with a db var, assume {auto_reconnect: true} 
function openDB() { 
    db.open(function(err, db) { 
     // skip err handling and so on 
     return db; 
    } 
} 

var myOpenDB = openDB(); // use myOpenDB in every other function I have 

b) abrir la conexión db y luego sólo hay que poner todo en un cierre gigante?
Ejemplo:

// same as above 
db.open(function(err, db) { 
    // do everything else here, for example: 
    server.get('/api/dosomething', function doSomething(req, res, next) { // (server is an instance of a Restify server) 
     // use the db object here and so on 
    }); 
} 

c) abrir y cerrar la db cada vez que se necesita?
Ejemplo:

// again, same as above 
server.get('/api/something', function doSomething(req, res, next) { 
    db.open(function(err, db) { 
     // do something 
     db.close(); 
    }); 
}); 

server.post('/api/somethingelse', function doSomethingElse(req, res, next) { 
    db.open(function(err, db) { 
     // do something else 
     db.close(); 
    }); 
}); 

Esto último es lo que haría de la intuición, pero al mismo tiempo no me siento del todo cómodo haciendo esto. ¿No pone demasiada tensión en el servidor de Mongo? Especialmente cuando (y espero llegar a eso) recibe cientos, si no miles, de llamadas como esta.

Gracias de antemano.

+1

Tenga en cuenta que para la opción B, puede evitar fácilmente el cierre masivo mediante el uso de funciones con nombre, evitando así el retrollamado. Dicho esto, si estás usando un nodo, estás usando módulos (¡espero!) Lo que significa que está bien tener (¡algunas pequeñas cantidades de variables declaradas!) - no contaminarán el espacio de nombres de nadie más, ya que nada deja el archivo '.js' excepto las exportaciones de su módulo. – Gijs

+0

Gracias! Entonces, ¿sugieres que use la opción B? He estado investigando sobre el [grupo de Google] del conductor (https://groups.google.com/forum/?fromgroups#!forum/node-mongodb-native) y todos parecen sugerir alguna forma de reutilización de la conexión (la mayoría de ellos sugieren algo como la opción B). – ArturoVM

+0

Por otro lado, leí en alguna parte que hacer todo bajo la misma conexión es bloqueo, derrotando el propósito de la naturaleza asincrónica de Node. – ArturoVM

Respuesta

11

Me gusta MongoJS mucho. Le permite usar Mongo de una manera muy similar a la línea de comando predeterminada y es solo un envoltorio sobre el controlador oficial de Mongo. Solo abre el DB una vez y especifica qué colecciones usará. Incluso puede omitir las colecciones si ejecuta Node con --harmony-proxies.

var db = require('mongojs').connect('mydb', ['posts']); 

server.get('/posts', function (req, res) { 
    db.posts.find(function (err, posts) { 
    res.send(JSON.stringify(posts)); 
    }); 
}); 
+0

¡Realmente me encanta! : D muchas gracias. Pero, como le dije a Gijs en los comentarios de mi respuesta, leí en alguna parte que hacer todo bajo la misma conexión resulta en código de bloqueo. ¿Sabes si esto es verdad? – ArturoVM

+0

No lo creo. Derrotaría el propósito. Creo que las conexiones a la base de datos se realizan a través de sockets. Los sockets hacen sobre las redes algo muy similar a lo que hace Node cuando lee archivos con Streams. Un ReadStream lee el archivo en pequeños fragmentos y dispara eventos cuando los recibe. Creo que los conectores hacen lo mismo con los trozos de red. Ver http://nodejs.org/api/net.html#net_class_net_socket – juandopazo

+0

El bloqueo o no bloqueo depende de la API. Así que el ejemplo anterior parece que sería un bloqueo en el sentido de que 'server.get (...)' no se ejecuta hasta que se conecte con éxito al DB (eso es exactamente lo que parece, no estoy familiarizado con MongoJS). Sin embargo, dado que probablemente necesite que el DB haga * cualquier cosa *, eso no es necesariamente tan malo, aunque si tiene muchas de estas dependencias que tardan mucho tiempo en ejecutarse, sería mejor usar una solución con futuros/promesas/devoluciones de llamada como en la solución de @scttnlsn. – Gijs

6
  • opción A no es una gran idea ya que no hay garantía de que el PP estará terminado apertura antes de una petición HTTP se maneja (concedida esto es muy poco probable)
  • opción C no es ideal, ya que innecesariamente abre y cierra la conexión DB

La forma en que me gusta manejar esto es utilizar diferidos/promesas. Hay un montón de diferentes bibliotecas promesa disponibles para el nodo pero la idea básica es hacer algo como esto:

var promise = new Promise(); 

db.open(function(err, db) { 
    // handle err 
    promise.resolve(db); 
}); 

server.get('/api/something', function doSomething(req, res, next) { 
    promise.then(function(db) 
     // do something 
    }); 
}); 

Creo Mangosta maneja las conexiones de una manera que se parece vagamente a esto.

+0

Gracias. Miré a Mongoose y aparentemente no hace las cosas de manera muy diferente al conductor oficial. Simplemente activa un evento cuando termina de abrir la conexión y, aunque no está conectado, almacena temporalmente las operaciones para que no tenga que preocuparse por ello. Aunque voy a ver lo que prometo :) – ArturoVM

+0

La biblioteca que se presenta a continuación, MongoJS, es en realidad un ejemplo mucho mejor del uso de promesas (sin embargo, se llaman futuros). – scttnlsn

Cuestiones relacionadas