Подтвердить что ты не робот

Node.js http.get зависает после 5 запросов к удаленному сайту

Я пишу простой конечный пункт api, чтобы определить, сможет ли мой сервер добраться до Интернета. Он отлично работает, но после 5 запросов (ровно 5, каждый раз) запрос зависает. То же самое происходит, когда я переключаю Google на Hotmail.com, что заставляет меня думать, что это что-то на моем конце. Нужно ли закрывать запросы http.get? У меня создалось впечатление, что эта функция автоматически закрывает запросы.

// probably a poor assumption, but if Google is unreachable its generally safe to say     that the server can't access the internet
// using this client side in the dashboard to enable/disable internet resources

app.get('/api/internetcheck', function(req, res) {
console.log("trying google...");
    http.get("http://www.google.com", function(r){
        console.log("Got status code!: " +r.statusCode.toString());
        res.send(r.statusCode.toString());
        res.end();
        console.log("ended!"); 
    }).on('error', function(e) {
        console.log("Got error: " + e.message);
    });
});
4b9b3361

Ответ 1

Здесь причина "точно 5": https://nodejs.org/docs/v0.10.36/api/http.html#http_agent_maxsockets

Внутренне модуль http использует класс агента для управления HTTP-запросами. Этот агент будет по умолчанию разрешать максимум 5 открытых подключений к одному и тому же HTTP-серверу.

В вашем коде вы не используете фактический ответ, отправленный Google. Таким образом, агент предполагает, что вы не закончили с запросом и не откроете соединение. Итак, после 5 запросов агент больше не позволит вам создавать новое соединение и начнет ждать завершения любого из существующих подключений.

Очевидным решением было бы просто использовать данные:

http.get("http://www.google.com", function(r){
  r.on('data', function() { /* do nothing */ });
  ...
});

Если вы столкнулись с проблемой, что ваш трафик /api/internetcheck называется много, поэтому вам нужно разрешить более 5 одновременных подключений, вы можете либо увеличить размер пула подключений, либо просто полностью отключить агент (хотя вы все равно придется потреблять данные в обоих случаях);

// increase pool size
http.globalAgent.maxSockets = 100;

// disable agent
http.get({ hostname : 'www.google.com', path : '/', agent : false }, ...)

Или, возможно, используйте HEAD запрос вместо GET.

(PS: в случае, если http.get генерирует ошибку, вы все равно должны завершить HTTP-ответ, используя res.end() или что-то подобное).

ПРИМЕЧАНИЕ: в Node.js версиях >= 0.11, maxSockets установлено значение Infinity.

Ответ 2

Если вы подождете достаточно долго, 5 запросов будут тайм-аут, а следующие 5 будут обрабатываться, поэтому приложение не будет действительно висит, потому что в конечном итоге он обработает все запросы.

Чтобы ускорить процесс, вам нужно что-то сделать с данными ответа, такими как r.on('data', function() {});