¿Por qué node.js solo procesa seis solicitudes a la vez?

Tenemos un servidor node.js que implementa una API REST como un proxy para un servidor central que tiene una API REST ligeramente diferente y desafortunadamente asimétrica.

Nuestro cliente, que se ejecuta en varios navegadores, le pide al servidor nodo que obtenga las tareas del servidor central. El servidor de nodo obtiene una lista de todos los identificadores de tareas desde el central y los devuelve al cliente. El cliente luego realiza dos llamadas a la API REST por cada id a través del proxy.

Por lo que puedo decir, todo esto se hace de forma asincrónica. En el registro de la consola, se ve así cuando inicio el cliente:

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

Esto toma un par de segundos para obtener la lista del servidor central. Tan pronto como recibe la respuesta, el servidor muestra esto muy rápidamente:

 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 

Luego, cada vez que un par de estas solicitudes obtiene un resultado del servidor central, otras dos líneas se descomponen rápidamente.

Parece que nuestro servidor node.js solo está dispuesto a tener seis solicitudes a la vez.

No hay límites de conexión TCP impuestos por Node. (El punto es que es altamente concurrente y puede manejar miles de conexiones simultáneas.) Su sistema operativo puede limitar las conexiones TCP.

Es más probable que esté accediendo a algún tipo de limitación de su servidor back-end, o está llegando al límite de conexión de la biblioteca HTTP incorporada, pero es difícil de decir sin más detalles sobre ese servidor o su implementación de Node.

La biblioteca HTTP incorporada de Node (y obviamente todas las bibliotecas construidas sobre ella, que son más) mantiene un grupo de conexiones (a través de la clase Agent ) para que pueda utilizar HTTP keep-alives. Esto ayuda a boost el rendimiento cuando ejecuta muchas solicitudes al mismo servidor: en lugar de abrir una conexión TCP, hacer una solicitud HTTP, obtener una respuesta, cerrar la conexión TCP y repetir; Se pueden emitir nuevas solicitudes en conexiones TCP reutilizadas.

En el nodo 0.10 y anterior, el Agente HTTP solo abrirá 5 conexiones simultáneas a un único host de manera predeterminada. Puede cambiar esto fácilmente: (suponiendo que haya require d el módulo HTTP como http )

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

el nodo 0.12 establece el maxSockets predeterminado para Infinity .

Es posible que desee mantener algún tipo de límite de conexión en su lugar. No querrás abrumar por completo a tu servidor back-end con cientos de solicitudes HTTP en un segundo: el rendimiento probablemente sea peor que si solo permites que el grupo de conexiones del Agente haga lo suyo, acelerando las solicitudes para no sobrecargar tu servidor. Su mejor apuesta será realizar algunos experimentos para ver cuál es el número óptimo de solicitudes concurrentes en su situación.

Sin embargo, si realmente no desea la agrupación de conexiones, puede omitir el grupo por completo: el agent enviado a false en las opciones de solicitud:

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

En este caso, no habrá absolutamente ningún límite en las solicitudes HTTP concurrentes.

Es el límite en el número de conexiones concurrentes en el navegador:

¿Cuántas solicitudes concurrentes de AJAX (XmlHttpRequest) están permitidas en navegadores populares?

He votado las otras respuestas, ya que me ayudaron a diagnosticar el problema. La clave era que el límite del socket de ese nodo era 5, y yo estaba obteniendo 6 a la vez. 6 es el límite en Chrome, que es lo que estaba usando para probar el servidor.

¿Cómo está obteniendo datos del servidor central? “El nodo no limita las conexiones” no es del todo exacto cuando se realizan solicitudes HTTP con el módulo http . Las solicitudes de clientes realizadas de esta manera utilizan la instancia http.globalAgent de http.Agent , y cada http.Agent tiene una configuración llamada maxSockets que determina cuántos sockets puede tener el agente abierto para cualquier host dado; esto está predeterminado a 5.

Por lo tanto, si está utilizando http.request o http.get (o una biblioteca que se basa en esos métodos) para obtener datos de su servidor central, puede intentar cambiar el valor de http.globalAgent.maxSockets (o modificar esa configuración en cualquier instancia de http.Agent que esté usando).

Ver:

  • documentación http.Agent
  • documentación de agent.maxSockets
  • Documentación http.globalAgent
  • Opciones que puede pasar a http.request , incluido un parámetro de agent para especificar su propio agente

He visto el mismo problema en mi servidor. Solo procesaba 4 solicitudes. Como ya se explicó desde 0.12, maxsockets está predeterminado en infinito. Eso abruma fácilmente al servidor. Limitar las solicitudes para decir 10 por

 http.globalAgent.maxSockets = 20; 

resolvió mi problema

¿Estás seguro de que solo devuelve los resultados al cliente? Nodo procesa todo en un hilo. Entonces, si realiza un análisis de respuesta sofisticado o cualquier otra cosa que no ceda, entonces bloquearía todas sus solicitudes.