Rozważmy następujący prosty node.js Zastosowanie:Węzeł js - http.request() problemy z zestawianiem połączeń
var http = require('http');
http.createServer(function() { }).listen(8124); // Prevent process shutting down
var requestNo = 1;
var maxRequests = 2000;
function requestTest() {
http.request({ host: 'www.google.com', method: 'GET' }, function(res) {
console.log('Completed ' + (requestNo++));
if (requestNo <= maxRequests) {
requestTest();
}
}).end();
}
requestTest();
To sprawia 2000 żądań HTTP do google.com, jedną po drugiej. Problem polega na zażądaniu nr 5 i wstrzymaniu na około 3 minuty, a następnie kontynuowaniu przetwarzania żądań 6 - 10, a następnie wstrzymaniu na kolejne 3 minuty, a następnie żądaniu 11-15, wstrzymaniu i tak dalej. Edit:Próbuję zmienić www.google.com localhost, bardzo podstawowa aplikacja node.js prowadzę maszynę, która zwraca „Hello World”, ja nadal się 3 minuty pauzy.
Teraz czytam mogę zwiększyć limit puli połączeń:
http.globalAgent.maxSockets = 20;
Teraz jeśli go uruchomić, to przetwarza żądania 1 - 20, a następnie zatrzymuje się na 3 minuty, a następnie żąda 21 - 40, a następnie zatrzymana , i tak dalej.
Wreszcie, po trochę badań, nauczyłem mogłem wyłączyć połączenie łączenie całości przez ustawienie agent: false
w opcjach kupna:
http.request({ host: 'www.google.com', method: 'GET', agent: false }, function(res) {
...snip....
... i będzie ona przebiegać przez wszystkich 2000 wniosków dobrze.
Moje pytanie, czy to dobry pomysł, aby to zrobić? Czy istnieje niebezpieczeństwo, że mógłbym otrzymać zbyt wiele połączeń HTTP? I dlaczego zatrzymuje się na 3 minuty, z pewnością, gdybym skończył połączenie, powinien dodać go z powrotem do puli, aby był gotowy na kolejną prośbę, dlaczego więc czeka 3 minuty? Przebacz mojej niewiedzy.
W takim razie jaka jest najlepsza strategia dla aplikacji Node.js, która generuje potencjalnie dużą liczbę żądań HTTP bez blokowania lub awarii?
Używam Node.js w wersji 0.10 na Mac OSX 10.8.2.
Edit: Znalazłem jeśli przekonwertować powyższy kod w pętli for i starają się ustalić kilka połączeń w tym samym czasie, zaczynam się błędy po około 242 połączeń. Błąd jest:
Error was thrown: connect EMFILE
(libuv) Failed to create kqueue (24)
... i kod ...
for (var i = 1; i <= 2000; i++) {
(function(requestNo) {
var request = http.request({ host: 'www.google.com', method: 'GET', agent: false }, function(res) {
console.log('Completed ' + requestNo);
});
request.on('error', function(e) {
console.log(e.name + ' was thrown: ' + e.message);
});
request.end();
})(i);
}
Nie wiem, czy mocno załadowana aplikacja node.js może kiedykolwiek osiągnąć, że wiele jednoczesnych połączeń.
Wyczerpuje się deskryptor plików, który na OSX jest domyślnie ograniczony do raczej niskiego 256. Możesz zwiększyć tę liczbę, używając 'ulimit -n 2048', która umożliwiłaby kolejny proces Node uruchamiany z tej samej powłoki, aby otworzyć te 2000 połączeń z Google ** w tym samym czasie **, ale to naprawdę nie jest to, o czym myślę . Nie jestem pewien, skąd pochodzą 3 minuty, brzmi jak dławienie w puli połączeń (czy może Google dusi cię?). – robertklep
Dzięki za informacje na temat deskryptorów plików OSX, ma to większy sens. Domyślam się, że nie byłoby problemu na stronie na żywo działającej pod Linuksem. Ale co do czasu oczekiwania na 3 minuty, dostaję to, jeśli trafię na lokalnie działającą aplikację internetową Node.js na moim komputerze. –
Czytanie [this] (http://nodejs.org/api/http.html#http_class_http_agent), Zastanawiam się, czy 3-minutowy limit czasu jest utrzymywaniem limitu czasu dla serwerów Google (chociaż jeśli rozumiem dokumenty poprawnie, jako dopóki będziesz żądał, nie powinien czekać, aż te alimenty wygaśnie przed uruchomieniem nowego żądania ...) – robertklep