2011-10-08 18 views
5

Así que el nodo funciona muy bien para mí. Tengo una aplicación de servidor muy específica que básicamente acepta solicitudes para realizar un procedimiento determinado de CPU y ejecuta un programa C para hacerlo. La cosa es que, si tengo varios clientes, es muy probable que obtenga múltiples versiones de la misma solicitud. Sería una buena optimización manejarlo de alguna manera explícitamente, implementando un caché con algo de bloqueo en una clave particular, para que otros clientes simplemente esperen a que la solicitud regrese y copie su respuesta.Cómo crear una memoria caché en node.js que maneja explícitamente solicitudes duplicadas simultáneas para una operación vinculada a la CPU

Pero soy nuevo en el nodo, por lo que no sé cómo instalar esto en mi mecanismo de controlador de petición de enrutador de nodo básico. Obviamente, podría hacerlo en lenguaje x usando primitivas básicas de concurrencia, pero sé que ese nodo está orientado a eventos y creo que esto podría hacerse con bastante elegancia de un modo evocado. Ideas?

Respuesta

0

En el mundo del lado del cliente de JavaScript, normalmente guarda en caché los elementos en una matriz. También soy nuevo en el nodo, así que disculpe si esta no es la respuesta que está buscando, pero vale la pena intentarlo.

Puede configurar una matriz vacía cuando el servidor se inicia y almacenar los resultados con un hash especial de algún tipo en función de la solicitud recibida. Esto parece una solución viable.

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

Creo que estás en el camino correcto, mi principal preocupación es si tengo que manejar para la concurrencia al comprobar la matriz para la clave y cómo manejar la espera de que la respuesta regrese si la clave está registrada pero el valor aún no está disponible. lo que realmente necesito es un mecanismo de concurrencia de algún tipo junto con una forma de registrar un evento para que los clientes se despierten cuando el valor esté disponible. esa es la parte en la que estoy realmente atrapado en – William

+0

¿Supongo que podría tener la caché que mantiene un emisor de eventos para cada clave que te permita registrarte? entonces solo tengo que lidiar con la concurrencia – William

0

Easy peasy .. Node.js tiene un solo subproceso, por lo que la primera solicitud de CPU está bloqueando el servidor de todos modos ... así que memorice los resultados. Básicamente, configura un hash con la clave solicitada y, antes de llamar al programa C, verifica el hash. Si está allí, devuélvela, estás listo. Si no es así, ejecute el programa C, inserte los resultados en el hash en la clave solicitada antes de devolver, y luego return.

+0

, sí, hombre, entiendo qué es un caché, pero el problema es la consistencia. Me han enseñado a pensar sobre cualquier posible "orden" pero no entiendo lo suficiente la programación del nodo. ¿Estás diciendo que todas las operaciones son atómicas? es decir, no necesito preocuparme por la solicitud del subproceso A, el subproceso Un trabajo de inicio, la solicitud del subproceso B, el trabajo de inicio del subproceso B, los retornos del subproceso A, la memoria caché de las actualizaciones, las devoluciones del subproceso B y la memoria caché de actualizaciones. ¿Ves lo que quiero decir? – William

+0

Sin hilos. Bueno, está bien, * 1 * hilo. Por lo tanto, todos los eventos se programan de forma cooperativa. Es por eso que debes tener cuidado con los manejadores de eventos que hacen mucho; tiene el 'piso' durante el tiempo que quiera, hasta que regrese. Entonces, ingresa la Solicitud A, la Solicitud A comienza a procesar, la Solicitud B entra, pero el ciclo de eventos no ha regresado, por lo que la solicitud B permanece en la cola del socket hasta que el controlador de la Solicitud A regrese. –

3

Varias respuestas arriba, pero ninguna realmente trata las solicitudes paralelas al mismo recurso correctamente.

No necesita preocuparse por la concurrencia al verificar la clave de caché, ya que el nodo es un entorno de subproceso único. Todas tus acciones son de hecho atómicas. Sin embargo, todas las operaciones de sincronización en el nodo harán que acepte más solicitudes. Por lo tanto usted necesita para manejar las solicitudes concurrentes se superponen, aquí resuelto con el registro de observadores 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"); 
Cuestiones relacionadas