2012-08-03 17 views
32

Questo è un po 'poco chiaro per me (sto solo iniziando con Node e Mongo), e mi preoccupa davvero a causa delle prestazioni e della tensione del server (che credo sia un'altra domanda, ma arriverò a quello alla fine del post).Qual è la procedura migliore per le connessioni MongoDB su Node.js?

Quindi, assumendo sto scrivendo un API con Node.js e Restify, dove ogni endpoint API corrisponde ad una funzione, devo:

a) aprire la connessione db e memorizzarlo in un globale var, e quindi basta usarlo in ogni funzione?
Esempio:

// 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) aprire la connessione db e poi basta mettere tutto in una chiusura gigante?
Esempio:

// 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) aprire e chiudere il db ogni volta che è necessario?
Esempio:

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

Quest'ultimo è quello che vorrei fare di intuizione, ma allo stesso tempo non mi sento del tutto comodo fare questo. Non mette troppo a dura prova il server Mongo? Soprattutto quando (e spero di arrivarci) ottengono centinaia - se non migliaia - di chiamate come questa?

Grazie in anticipo.

+1

Si noti che per l'opzione B, è possibile evitare facilmente la chiusura massiccia utilizzando le funzioni con nome, evitando così l'inferno di callback. Detto questo, se stai usando il nodo, stai usando i moduli (spero!) Che significa che è OK avere (un piccolo numero di dichiarate!) Variabili globali - non inquinano lo spazio dei nomi di nessuno, poiché nulla lascia il File '.js' ad eccezione delle esportazioni del modulo. – Gijs

+0

Grazie! Quindi mi suggerisci di usare l'opzione B? Ho scavato intorno al [gruppo di Google] del driver (https://groups.google.com/forum/?fromgroups#!forum/node-mongodb-native) e tutti sembrano suggerire qualche forma di riutilizzo della connessione (la maggior parte di loro in realtà suggerisce qualcosa come l'opzione B). – ArturoVM

+0

D'altra parte, ho letto da qualche parte che fare tutto sotto la stessa connessione sta bloccando, vanificando lo scopo della natura asincrona di Node. – ArturoVM

risposta

11

Mi piace MongoJS un sacco. Ti permette di usare Mongo in modo molto simile alla riga di comando predefinita ed è solo un wrapper sul driver Mongo ufficiale. Apri il DB solo una volta e specifica quali collezioni utilizzerai. È anche possibile omettere le raccolte se si esegue il nodo 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

Lo amo davvero! : D Grazie mille. Ma, come ho detto a Gijs nei commenti della mia risposta, ho letto da qualche parte che fare tutto sotto lo stesso collegamento provoca il blocco del codice. Sai se questo è vero? – ArturoVM

+0

Io non la penso così. Avrebbe sconfitto lo scopo. Credo che le connessioni al database avvengano tramite socket. I socket eseguono su reti qualcosa di molto simile a ciò che fa Node durante la lettura di file con flussi. Un ReadStream legge il file in piccoli blocchi e genera eventi quando li riceve. Penso che i socket facciano lo stesso con i blocchi di rete. Vedi http://nodejs.org/api/net.html#net_class_net_socket – juandopazo

+0

Il blocco o il non blocco dipende dall'API. Quindi l'esempio sopra sembra che si bloccherebbe nel senso che il 'server.get (...)' non viene eseguito fino a quando non ci si connette al DB (è puramente quello che sembra, non mi è familiare con MongoJS). Tuttavia, dato che probabilmente hai bisogno del DB per fare * qualsiasi cosa *, non è necessariamente così male, anche se hai molte di queste dipendenze che impiegano molto tempo per essere eseguite, sarebbe meglio usare una soluzione con i futures/promesse/callback come nella soluzione di @scttnlsn. – Gijs

6
  • Opzione A non è una grande idea in quanto non v'è alcuna garanzia che il DB sarà finito apertura prima una richiesta HTTP viene gestita (concesso questo è molto improbabile)
  • Opzione C è anche non è l'ideale in quanto inutilmente apre e chiude la connessione DB

Il modo in cui mi piace gestirlo è l'utilizzo di posticipi/promesse. Ci sono un sacco di diverse librerie promessa disponibili per il nodo, ma l'idea di base è quella di fare qualcosa di simile:

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

Credo Mongoose gestisce le connessioni in un modo che ricorda vagamente questo.

+0

Grazie. Ho guardato in Mongoose e apparentemente non fa le cose in modo molto diverso dal pilota ufficiale. Attiva semplicemente un evento quando termina l'apertura della connessione e, mentre non è collegato, esegue il buffering delle operazioni in modo da non doversene preoccupare. Guarderò la cosa promessa, però :) – ArturoVM

+0

La libreria presentata di seguito, MongoJS, è in realtà un esempio molto migliore di utilizzo delle promesse (si chiamano comunque i futures). – scttnlsn

Problemi correlati