2011-10-08 5 views
5

Węzeł działa doskonale dla mnie. Mam bardzo specyficzną aplikację serwerową, która zasadniczo akceptuje żądania wykonania konkretnej procedury związanej z procesorem i wykonuje program w języku C, aby to zrobić. Chodzi o to, że jeśli mam wielu klientów, jest bardzo prawdopodobne, że otrzymam wiele wersji tego samego żądania. Byłoby miłą optymalizacją, aby jakoś poradzić sobie z tym wyraźnie, poprzez zaimplementowanie pamięci podręcznej z blokadą określonego klucza, aby inni klienci po prostu czekali na to żądanie i skopiowali odpowiedź.Jak utworzyć pamięć podręczną w węźle node.js, która obsługuje jawnie dla jednoczesnych duplikatów żądań dla operacji związanej z procesorem

Ale jestem nowy w węźle, więc nie wiem jak ustawić to w moim podstawowym mechanizmie obsługi żądań routera węzła. Oczywiście mogłem to zrobić w języku x używając podstawowych operacji współbieżności, ale wiem, że węzeł jest zorientowany na zdarzenia i myślę, że można to zrobić całkiem elegancko w zdarzeniu. Pomysły?

Odpowiedz

0

W świecie JavaScript po stronie klienta zwykle buforujesz elementy w tablicy. Jestem też nowy w węźle, więc przebacz, jeśli nie jest to odpowiedź, której szukasz, ale warto spróbować.

Po uruchomieniu serwera można ustawić pustą tablicę i zapisać wyniki za pomocą specjalnego skrótu na podstawie otrzymanego żądania. To wydaje się realnym rozwiązaniem.

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

myślę, że jesteś na dobrej drodze, moim głównym problemem jest to, czy muszę obsłużyć do współbieżności podczas sprawdzania tablicę pod kątem klucz i sposób obsługi oczekiwania na odpowiedź, aby wrócić, jeśli klucz jest zarejestrowany, ale wartość nie jest jeszcze dostępna. to, czego naprawdę potrzebuję, to jakiś mechanizm współbieżności w połączeniu ze sposobem zarejestrowania zdarzenia dla klientów, aby się obudzić, gdy wartość stanie się dostępna. to jest część, w której naprawdę utknąłem na – William

+0

zgaduję, że mógłbym mieć pamięć podręczną, która utrzymuje emiter zdarzenia dla każdego klucza, aby umożliwić rejestrację? wtedy muszę po prostu poradzić sobie z współbieżnością – William

0

Łatwy peasy .. node.js jest pojedynczy gwintowany tak, że pierwszy wniosek związany CPU blokuje serwer tak .. tak memoize wyniki. Zasadniczo ustawiasz hasz z żądanym kluczem, a przed wywołaniem programu C sprawdź hasz. Jeśli tam jest, zwróć to, gotowe. Jeśli tak nie jest, uruchom program C, wklej wyniki w krzyżyk na żądany klucz przed powrotem, następnie powrócić.

+0

tak, mam na imię cache, ale problem jest konsekwencją. Nauczyłem się myśleć o możliwym "zamawianiu", ale nie rozumiem wystarczająco dobrze planowania węzła. Czy mówisz, że wszystkie operacje są atomowe? tj. nie muszę się martwić o żądanie wątku A, zadanie początkowe wątku A, żądanie wątku B, zadanie początkowe wątku B, wątek A zwraca, pamięć podręczna aktualizacji, wątek B zwraca, aktualizuje pamięć podręczną. Widzisz, co mam na myśli? – William

+0

Brak wątków. No dobrze, * 1 * wątek. W związku z tym wszystkie wydarzenia są zaplanowane wspólnie. Dlatego musisz uważać na programy obsługi zdarzeń, które dużo robią; ma "podłogę" tak długo, jak chce, aż do jej powrotu. Tak więc, żądanie A przychodzi, żądanie A rozpoczyna przetwarzanie, żądanie B przychodzi, ale pętla zdarzeń nie powróciła, więc żądanie B pozostaje w kolejce gniazda, dopóki program obsługi żądania A nie zwróci. –

3

Kilka powyższych odpowiedzi, ale żadna z nich nie traktuje poprawnie żądania równoległego do tego samego zasobu.

Nie musisz martwić się o współbieżność podczas sprawdzania klucza pamięci podręcznej, ponieważ węzeł jest środowiskiem jednowątkowym. Wszystkie twoje działania są rzeczywiście atomowe. Wszystkie operacje asynchroniczne w węźle spowodują jednak akceptację kolejnych żądań. Zatem trzeba obsłużyć jednoczesnych żądań nakładających się tu rozwiązany z rejestracji obserwatorów do 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"); 
Powiązane problemy