Почему node.js обрабатывает только шесть запросов одновременно?

У нас есть сервер node.js, который реализует REST API в качестве прокси-сервера для центрального сервера, который имеет несколько иной и, к сожалению, асимметричный REST API.

Наш клиент, который работает в разных браузерах, просит сервер node получить задания с центрального сервера. Сервер node получает список всех идентификаторов задач из центрального и возвращает их клиенту. Затем клиент делает два вызова API REST на один идентификатор через прокси.

Насколько я могу судить, все это делается асинхронно. В журнале консоли это выглядит так, когда я запускаю клиент:

Requested GET URL under /api/v1/tasks/*: /api/v1/tasks/

Это займет пару секунд, чтобы получить список с центрального сервера. Как только он получит ответ, сервер выдает это очень быстро:

Requested GET URL under /api/v1/tasks/id/:id :/api/v1/tasks/id/438
Requested GET URL under /api/v1/workflow/id/:id :/api/v1/workflow/id/438
Requested GET URL under /api/v1/tasks/id/:id :/api/v1/tasks/id/439
Requested GET URL under /api/v1/workflow/id/:id :/api/v1/workflow/id/439
Requested GET URL under /api/v1/tasks/id/:id :/api/v1/tasks/id/441
Requested GET URL under /api/v1/workflow/id/:id :/api/v1/workflow/id/441

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

Итак, кажется, что наш сервер node.js только хочет иметь шесть запросов за раз.

Ответ 1

Это ограничение на количество одновременных подключений в браузере:

Сколько одновременных запросов AJAX (XmlHttpRequest) разрешено в популярных браузерах?

Я поддержал другие ответы, так как они помогли мне диагностировать проблему. Подсказка заключалась в том, что ограничение node сокета было 5, и я получал 6 за раз. 6 - это ограничение в Chrome, которое я использовал для тестирования сервера.

Ответ 2

Пределы подключения TCP не налагаются самим Node. (Все дело в том, что он очень параллелен и может обрабатывать тысячи одновременных подключений.) Ваша ОС может ограничить TCP-соединения.

Скорее всего, вы либо нажмете какое-то ограничение на ваш сервер, либо натолкнулись на встроенный лимит подключения к библиотеке HTTP, но неясно сказать, что этот сервер или ваша реализация Node.

Node встроенная библиотека HTTP (и, очевидно, все библиотеки, построенные поверх нее, которые больше всего) поддерживают пул соединений (через Agent), чтобы он мог использовать HTTP-keep-alives. Это помогает повысить производительность при запуске множества запросов на один и тот же сервер: вместо открытия TCP-соединения, создания HTTP-запроса, получения ответа, закрытия TCP-соединения и повторения; новые запросы могут быть выданы при повторных использования TCP-соединений.

В Node 0.10 и более ранних версиях HTTP-агент будет открывать только 5 одновременных подключений к одному хосту по умолчанию. Вы можете легко это изменить: (если вы используете require d HTTP-модуль как http)

http.globalAgent.maxSockets = 20; // or whatever

Node 0.12 устанавливает значение по умолчанию maxSockets в Infinity.

Возможно, вы захотите сохранить какой-то лимит подключения. Вы не хотите полностью подавлять ваш серверный сервер сотнями HTTP-запросов под вторым – производительность, скорее всего, будет хуже, чем если бы вы просто позволили пулу подключений агента делать что-то, подавая запросы, чтобы не перегружать ваш сервер. Лучше всего провести несколько экспериментов, чтобы узнать, какое оптимальное количество одновременных запросов находится в вашей ситуации.

Однако, если вам действительно не нужен пул соединений, вы можете просто полностью обходить пул – отправлено Agent в false в параметрах запроса:

http.get({host:'localhost', port:80, path:'/', agent:false}, callback);

В этом случае ограничений на одновременные HTTP-запросы не будет.

Ответ 3

Как вы получаете данные с центрального сервера? "Node не ограничивает соединения" не совсем точно при выполнении HTTP-запросов с модулем http. Запросы клиентов, сделанные таким образом, используют экземпляр http.globalAgent http.Agent, и каждый http.Agent имеет параметр с именем maxSockets, который определяет, сколько сокетов агент может открыть для любого данного хоста; это значение по умолчанию равно 5.

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

См:

Ответ 4

Я видел ту же проблему на моем сервере. Он обрабатывал только 4 запроса. Как пояснялось уже с 0.12 maxsockets по умолчанию бесконечно. Это легко подавляет разорение. Ограничение запросов 10 словами

http.globalAgent.maxSockets = 20;

решил мою проблему.

Ответ 5

Вы уверены, что он просто возвращает результаты клиенту? Node обрабатывает все в одном потоке. Поэтому, если вы выполняете какой-то причудливый разбор ответов или что-то еще, что не уступает, тогда оно блокирует все ваши запросы.