2011-10-08 8 views
5

Quindi il nodo funziona perfettamente per me. Ho un'applicazione server molto specifica che accetta essenzialmente richieste per eseguire una particolare procedura legata alla CPU, ed esegue un programma C per farlo. Il fatto è che, se ho più client, è molto probabile che otterrò più versioni della stessa richiesta. Sarebbe una buona ottimizzazione gestirla in qualche modo in modo esplicito, implementando una cache con qualcosa di un lock su una particolare chiave, in modo che altri client attenderanno semplicemente che quella richiesta ritorni e copi la sua risposta.Come creare una cache in node.js che gestisce esplicitamente richieste simultanee duplicate per un'operazione legata alla CPU

Ma io sono nuovo per il nodo, quindi non so come farlo nel mio meccanismo di base del gestore di richieste router-nodo. Ovviamente potrei farlo in linguaggio x usando primitive di concorrenza di base, ma so che il nodo è orientato all'evento e penso che questo potrebbe essere fatto in modo elegante in un modo event. Idee?

risposta

0

Nel mondo lato client di JavaScript, si memorizzano in genere gli elementi in una matrice. Anch'io sono nuovo al nodo, quindi scusami se questa non è la risposta che stai cercando, ma vale la pena provare.

È possibile impostare un array vuoto all'avvio del server e memorizzare i risultati con un hash speciale di qualche tipo in base alla richiesta ricevuta. Questa sembra una soluzione fattibile.

E.g.

var http = require('http'); 
var cache = []; 
http.createServer(function (req, res) { 
    var obj; 
    if(!cache[key]) { 
     obj = .... // logic that gets results 
     cache[obj.key] = obj; 
    } else { 
     obj = cache[key]; 
    } 
}).listen(1337, "127.0.0.1"); 
+0

Penso che tu sia sulla strada giusta, la mia preoccupazione principale è se ho bisogno di gestire per la concorrenza quando si controlla l'array per la chiave e come gestire l'attesa che la risposta torni se la chiave è registrata ma il valore non è ancora disponibile. ciò di cui ho veramente bisogno è un meccanismo di concorrenza di qualche tipo associato a un modo per registrare un evento affinché i client si sveglino quando il valore diventa disponibile. questa è la parte in cui sono davvero bloccato su – William

+0

suppongo che potrei avere la cache che gestisce un emettitore di eventi per ogni chiave per consentire la registrazione? quindi devo solo fare i conti con la concorrenza – William

0

Easy Peasy .. Node.js è a thread singolo, in modo che prima CPU richiesta legata sta bloccando il server comunque .. in modo Memoize i risultati. In sostanza, si imposta un hash con la chiave richiesta, e prima di chiamare il programma C, controllare l'hash. Se è lì, restituiscilo, sei fatto. In caso contrario, eseguire il programma C, incollare i risultati nell'hash alla chiave richiesta prima di ritornare, quindi il ritorno.

+0

sì, io mangio quello che è un cache, ma i problemi sono la coerenza. Mi è stato insegnato a pensare a qualsiasi "ordinamento" possibile, ma non capisco abbastanza bene la programmazione del nodo. stai dicendo che tutte le operazioni sono atomiche? non ho bisogno di preoccuparmi per la richiesta di thread A, il thread di un processo di avvio, la richiesta di thread B, il processo di avvio del thread B, il thread A restituisce, aggiorna la cache, il thread B restituisce, aggiorna la cache. Capito quello che intendo? – William

+0

Nessun thread. Bene, ok, * 1 * thread. Quindi, tutti gli eventi sono pianificati in modo cooperativo. Ecco perché devi stare attento ai gestori di eventi che fanno molto; ha il 'pavimento' per tutto il tempo che vuole, finché non ritorna. Quindi, la richiesta A entra, la richiesta A inizia l'elaborazione, la richiesta B entra, ma il ciclo degli eventi non è tornato, quindi la richiesta B rimane nella coda del socket fino a quando il gestore della richiesta A non ritorna. –

3

Diverse risposte sopra, ma nessuna realmente tratta le richieste parallele alla stessa risorsa correttamente.

Non è necessario preoccuparsi della concorrenza durante il controllo della chiave di cache, poiché il nodo è un ambiente a thread singolo. Tutte le tue azioni sono davvero atomiche. Tuttavia, tutte le operazioni asincrone nel nodo causeranno l'accettazione di ulteriori richieste. Quindi è necessario per gestire le richieste simultanee sovrapposte, qui risolto con la registrazione osservatori a un EventEmmiter:

var http = require('http'), EventEmitter = require('events').EventEmitter; 
var cache = {}; 

http.createServer(function (req, res) { 
    var key = someMagic(req), cached = cache[key]; // get some unique request identifier 

    if (!cached) { // if we've never seen this request before 
    cached = new EventEmitter(); // make this cache entry an event emitter 
    cached.status = 'running'; 
    handleAsyncRequest(function(result) { // your request handling is probably asynchronous, call this callback when you're done 
     cached.response = result; // memoize data 
     cached.status = 'finished'; 
     cached.emit('finished'); // notify all observers waiting for this request 
    }); 

    } else { 
    switch(cached.status) { // if existing request, check if it's still running or finished 
     case 'finished': 
     res.end(cached.response); // send cached response immediately if request has finished 
     break; 
     case 'running': 
     // subscribe as observer; send response when request is finished 
     cached.once('finished', function() { res.end(cached.response); }); 
     break; 
    } 
    } 
}).listen(1337, "127.0.0.1"); 
Problemi correlati