Сокеты не закрываются при использовании Node.js http.get

OS X 10.8.3

Node 0.10.0

Я использую модуль "http" для запросов API графиков Facebook.

Вот параметры, которые я передаю в 'http.get':

var options = {host: 'graph.facebook.com',
               port: 80,
               path: '/' + fb_id + '/picture'};  //fb_id is a Facebook user identifier

Мой код выглядит следующим образом:

http.get(options,
  function(res) {
    ...some stuff...
    DONE(RESULT);  //DONE is a callback function
  }).on('error', function(e) {
       ...some error handling...
});

Я наблюдаю, что я могу делать столько запросов, сколько значение http.globalAgent.maxSockets. Как только я дойду до этого множества запросов, следующий вызов http.get никогда (видимо) не подключается. Я проверял, что я не получаю ошибок в запросах.

Как будто сокеты не закрываются после ответа.

Есть ли что-то, что мне нужно сделать как часть обработчика ответа, чтобы убедиться, что сокет закрыт?

Являются ли эти сокеты не закрытыми из-за поведения keepalive по умолчанию?

Как мне отладить это?

Ответ 1

Попробуйте установить agent: false в параметрах. Поведение по умолчанию действительно должно поддерживать открытые соединения для HTTP keep-alive:

var options = {host: 'graph.facebook.com',
               port: 80,
               path: '/' + fb_id + '/picture',
               agent: false};

Ответ 2

Node http-модуль утверждает, что агент по умолчанию использует глобальный агент: http://nodejs.org/api/http.html#http_http_globalagent, что означает, что keep-alive является общим, независимо от того, который инициирует запрос.

BTW, отвечая на комментарий Wes от 9 апреля 13 в 20:47: неважно, сколько раз вы загружаете модуль node, он будет загружаться только один раз и делиться всеми модулями.

То, что вы испытываете, - проблема исчерпания пула. Самый простой способ избежать этого - использовать новый агент (http://nodejs.org/api/http.html#http_class_http_agent) с вашими желаемыми maxSockets. Помните, что создаваемый вами агент может быть разделен между модулями, если вы поместите его в экспорт этого модуля (модули в node с сохранением состояния!!!).

Ответ 3

Я испытал такое же поведение, за исключением того, что мои соединения были, наконец, повторно использованы после периода ожидания. Проверьте, будут ли соединения повторно использоваться через определенный промежуток времени (пару минут), а также проверьте, содержат ли заголовки ответов "Connection: keep-alive".

Если в этом случае возможным решением было бы использовать заголовок "Соединение: Закрыть" вместо keep-alive, то пустые соединения можно было бы использовать повторно, как в обычной настройке. Я не уверен, что это приводит к любым проблемам производительности с использованием конечных точек facebook.

var options = {host: 'graph.facebook.com',
               port: 80,
               path: '/' + fb_id + '/picture',
               headers: { 'Connection':'Close' }
};

Для меня использование агента: false не работает, потому что огромное количество запросов, которые я отправил, исчерпало ресурсы сервера.