Рассмотрим следующий простой Node.js приложения:Node JS - http.request() проблемы с Пулы соединений
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();
Это делает 2000 HTTP запросы на google.com, один за другим. Проблема заключается в том, что он запрашивает номер 5 и приостанавливается примерно на 3 минуты, затем продолжает обработку запросов 6 - 10, затем останавливается еще на 3 минуты, затем запрашивает 11 - 15, паузы и т. Д. Редактировать:Я попытался сменить www.google.com на localhost, чрезвычайно простое приложение Node.js, на котором запущена моя машина, которая возвращает «Hello world», я все равно получаю 3-минутную паузу.
Теперь я прочитал, я могу увеличить лимит пула соединений:
http.globalAgent.maxSockets = 20;
Теперь, если я запускаю его, он обрабатывает запросы 1 - 20, затем делает паузу в течение 3 минут, а затем просит 21 - 40, затем делает паузу , и так далее.
Наконец, после небольшого исследования, я узнал, что я мог бы отключить соединение Объединив полностью установив agent: false
в параметрах запроса:
http.request({ host: 'www.google.com', method: 'GET', agent: false }, function(res) {
...snip....
... и он будет работать на всех 2000 запросов просто отлично.
Мой вопрос: это хорошая идея? Есть ли опасность, что я могу получить слишком много HTTP-соединений? И почему он останавливается на 3 минуты, конечно, если я закончил с соединением, он должен добавить его прямо в бассейн, готовый к следующему запросу, чтобы использовать, так почему он ждет 3 минуты? Простите мое невежество.
Несоблюдение этого, что является лучшей стратегией для приложения Node.js, создающего потенциально большое количество HTTP-запросов без блокировки или сбоя?
Я запускаю версию Node.js 0.10 на Mac OSX 10.8.2.
Edit: Я нашел, если преобразовать приведенный выше код в цикл и попытаться установить кучу соединений в то же время, я начинаю получать ошибки после того, как около 242 соединений. Ошибка:
Error was thrown: connect EMFILE
(libuv) Failed to create kqueue (24)
... и код ...
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);
}
Я не знаю, если сильно загружен Node.js приложение может когда-либо достичь, что большое количество одновременных соединений.
У вас заканчиваются файловые дескрипторы, которые по OSX ограничены относительно низким 256 по умолчанию. Вы можете увеличить этот номер с помощью 'ulimit -n 2048', что позволило бы выполнить последующий процесс Node из одной и той же оболочки, чтобы одновременно открыть эти 2000 соединений с Google ** **, но это не то, что вы хотите, я думаю , Я не уверен, откуда идут 3 минуты, звучит как дросселирование в пуле соединений (или, возможно, Google задушивает вас?). – robertklep
Благодарим за информацию о дескрипторах файла OSX. Я предполагаю, что это не будет проблемой на реальном сайте, работающем в Linux. Но что касается 3 минут ожидания, я понимаю, что если я нахожу локальное веб-приложение Node.js на своей машине. –
Чтение [this] (http://nodejs.org/api/http.html#http_class_http_agent), интересно, будет ли 3-минутный таймаут тайм-аутом keep-alive для серверов Google (хотя, если я правильно понимаю документы, если вы продолжаете запрашивать, он не должен дожидаться истечения срока действия этих авиалиний до начала нового запроса ...) – robertklep