Por qué debería usar un nodo if de Proxy Inverso.js está Listo para la Producción?
fue en El año 2012. PHP y Ruby on Rails reinaron como las tecnologías supremas del lado del servidor para renderizar aplicaciones web. Pero, un nuevo y audaz contendiente tomó a la comunidad por sorpresa, uno que logró manejar conexiones simultáneas de 1 MILLÓN. Esta tecnología no era otra que Nodo.js y ha aumentado constantemente en popularidad desde entonces.
A diferencia de la mayoría de las tecnologías de la competencia de la época, Node.js viene con un servidor web incorporado. Tener este servidor significaba que los desarrolladores podían omitir una gran cantidad de archivos de configuración, como php.ini
y una colección jerárquica de archivos.htaccess
. Tener un servidor web incorporado también ofrecía otras comodidades, como la capacidad de procesar archivos a medida que se cargaban y la facilidad de implementar WebSockets.
Nodo diario.las aplicaciones web basadas en js manejan miles de millones de solicitudes. La mayoría de las compañías más grandes del mundo son impulsadas de alguna manera por Node.js. Para decir ese Nodo.js is Production-Ready es sin duda un eufemismo. Sin embargo, hay un consejo que ha sido válido desde Node.inicio de js: no se debe exponer directamente un nodo.js procesa a la web y en su lugar debe ocultarlo detrás de un proxy inverso. Pero, antes de ver las razones por las que querríamos usar un proxy inverso, primero veamos qué es uno.
Un proxy inverso es básicamente un tipo especial de servidor web que recibe solicitudes, las reenvía a otro servidor HTTP en otro lugar, recibe una respuesta y reenvía la respuesta al solicitante original.
Un proxy inverso no suele enviar la solicitud exacta, sin embargo. Por lo general, modificará la solicitud de alguna manera. Por ejemplo, si el proxy inverso vive en www.example.org:80
, y va a reenviar la solicitud aex.example.org:8080
, probablemente reescribirá el encabezado original Host
para que coincida con el del destino. También puede modificar la solicitud de otras maneras, como limpiar una solicitud mal formada o traducir entre protocolos.
Una vez que el proxy inverso recibe una respuesta, puede traducir esa respuesta de alguna manera. Una vez más, un enfoque común es modificar el encabezado Host
para que coincida con la solicitud original. El cuerpo de las solicitudes también se puede cambiar. Una modificación común es realizar compresión gzip en la respuesta. Otro cambio común es habilitar la compatibilidad con HTTPS cuando el servicio subyacente solo habla HTTP.
Los proxies inversos también pueden enviar solicitudes entrantes a varias instancias de backend. Si un servicio está expuesto en el api.example.org
, un proxy inverso podría enviar solicitudes a api1.internal.example.org
api2
, etc.
Existen muchos proxies inversos diferentes. Dos de los más populares son Nginx y HAProxy. Ambas herramientas son capaces de realizar compresión gzip y agregar soporte HTTPS, y también se especializan en otras áreas. Nginx es la más popular de las dos opciones, y también tiene algunas otras capacidades beneficiosas, como la capacidad de servir archivos estáticos desde un sistema de archivos, por lo que lo usaremos como ejemplo a lo largo de este artículo.
Ahora que sabemos lo que es un proxy inverso, ahora podemos ver por qué querríamos hacer uso de uno con Nodo.js.
¿Por qué debo usar un Proxy Inverso?
La terminación SSL es una de las razones más populares por las que se usa un proxy inverso. Cambiar el protocolo de la aplicación de http
a https
tarda un poco más de trabajo que anexar un s
. Nodo.el propio js puede realizar el cifrado y descifrado necesarios para https
, y se puede configurar para leer los archivos de certificado necesarios.
Sin embargo, la configuración del protocolo utilizado para comunicarse con nuestra aplicación y la administración de certificados SSL que caducan, no es algo que realmente deba preocupar a nuestra aplicación. Verificar certificados en una base de código no solo sería tedioso, sino también un riesgo para la seguridad. La adquisición de certificados desde una ubicación central al iniciar la aplicación también tiene sus riesgos.
Por esta razón, es mejor realizar la terminación SSL fuera de la aplicación, generalmente dentro de un proxy inverso. Gracias a tecnologías como certbot
de Let’s Encrypt, mantener certificados con Nginx es tan fácil como configurar un trabajo cron. Este trabajo puede instalar automáticamente nuevos certificados y reconfigurar dinámicamente el proceso Nginx. Este es un proceso mucho menos disruptivo que, por ejemplo, reiniciar cada nodo.instancia de aplicación js.
Además, al permitir que un proxy inverso realice la terminación SSL, esto significa que solo el código escrito por los autores del proxy inverso tiene acceso a su certificado SSL privado. Sin embargo, si su Nodo.la aplicación js está manejando SSL, luego cada módulo de terceros utilizado por su aplicación, incluso los módulos potencialmente maliciosos, tendrán acceso a su certificado SSL privado.
compresión gzip
la compresión gzip es otra característica que debe descargar de la aplicación a un proxy inverso. las directivas de compresión gzip son algo que se establece mejor a nivel de organización, en lugar de tener que especificar y configurar para cada aplicación.
Es mejor usar un poco de lógica al decidir qué gzip. Por ejemplo, los archivos que son muy pequeños, quizás más pequeños que 1 kb, probablemente no valgan la pena comprimirlos, ya que la versión comprimida con gzip a veces puede ser más grande, o la sobrecarga de CPU de tener al cliente descomprimiendo el archivo podría no valer la pena. Además, cuando se trata de datos binarios, dependiendo del formato, es posible que no se beneficie de la compresión. gzip también es algo que no se puede habilitar o deshabilitar simplemente, requiere examinar el encabezado entrante Accept-Encoding
para algoritmos de compresión compatibles.
Clustering
JavaScript es un lenguaje de subproceso único y, en consecuencia, un nodo.js ha sido tradicionalmente una plataforma de servidor de un solo subproceso (sin embargo, el soporte de subprocesos de trabajo actualmente experimental disponible en Node.js v10 tiene como objetivo cambiar esto). Esto significa obtener la mayor cantidad de rendimiento de un nodo.la aplicación js como sea posible requiere ejecutar aproximadamente el mismo número de instancias que hay núcleos de CPU.
Nodo.js viene con un módulo incorporado cluster
que puede hacer precisamente eso. Las solicitudes HTTP entrantes se realizarán a un proceso maestro y luego se enviarán a los trabajadores del clúster.
Sin embargo, escalar dinámicamente los trabajadores de clúster requeriría un cierto esfuerzo. Por lo general, también hay una sobrecarga adicional al ejecutar un nodo adicional.proceso js como proceso maestro de despacho. Además, escalar procesos en diferentes máquinas es algo que cluster
no puede hacer.
Por estas razones, a veces es mejor usar un proxy inverso para enviar solicitudes al nodo en ejecución.procesos js. Estos proxies inversos se pueden configurar dinámicamente para apuntar a nuevos procesos de aplicación a medida que llegan. En realidad, una aplicación solo debe preocuparse por hacer su propio trabajo, no debe preocuparse por administrar múltiples copias y enviar solicitudes.
Enrutamiento empresarial
Cuando se trata de aplicaciones web masivas, como las creadas por empresas de varios equipos, es muy útil tener un proxy inverso para determinar a dónde reenviar las solicitudes. Por ejemplo, las solicitudes realizadas a example.org/search/*
se pueden enrutar a la aplicación de búsqueda interna, mientras que otras solicitudes realizadas a example.org/profile/*
se pueden enviar a la aplicación de perfil interno.
Estas herramientas permiten otras funciones potentes, como sesiones adhesivas,implementaciones Azules / verdes, pruebas A / B, etc. He trabajado personalmente en una base de código donde dicha lógica se realizaba dentro de la aplicación y este enfoque hacía que la aplicación fuera bastante difícil de mantener.
Beneficios de rendimiento
Nodo.js es altamente maleable. Es capaz de servir activos estáticos desde un sistema de archivos, realizar compresión gzip con respuestas HTTP, viene con soporte incorporado para HTTPS y muchas otras características. Incluso tiene la capacidad de ejecutar varias instancias de una aplicación y realizar su propio envío de solicitudes, a través del módulo cluster
.
Y, sin embargo, en última instancia, es nuestro mejor interés dejar que un proxy inverso maneje estas operaciones por nosotros, en lugar de tener nuestro Nodo.la aplicación js lo hace. Aparte de cada una de las razones enumeradas anteriormente, otra razón para querer hacer estas operaciones fuera del Nodo.js se debe a la eficiencia.
El cifrado SSL y la compresión gzip son dos operaciones altamente vinculadas a la CPU. Las herramientas dedicadas de proxy inverso, como Nginx y HAProxy, normalmente realizan estas operaciones más rápido que Node.js. Tener un servidor web como Nginx leyendo contenido estático del disco va a ser más rápido que Node.js también. Incluso la agrupación en clústeres a veces puede ser más eficiente, ya que un proxy inverso como Nginx usará menos memoria y CPU que un nodo adicional.proceso js.
Pero, no te fíes de nuestra palabra. Veamos algunos puntos de referencia!
La siguiente prueba de carga se realizó utilizando siege
. Ejecutamos el comando con un valor de concurrencia de 10 (10 usuarios simultáneos haciendo una solicitud) y el comando se ejecutaría hasta que se hicieran 20.000 iteraciones (para 200.000 solicitudes totales).
Para comprobar la memoria, ejecutamos el comando pmap <pid> | grep total
varias veces a lo largo de la vida útil del punto de referencia y luego promediamos los resultados. Cuando se ejecuta Nginx con un solo hilo de trabajo, se terminan ejecutando dos instancias, una es el maestro y la otra es el trabajador. Luego sumamos los dos valores. Cuando se ejecuta un nodo.js cluster de 2 habrá 3 procesos, uno siendo el maestro y los otros dos siendo los trabajadores. La columna de memoria aproximada de la siguiente tabla es una suma total de cada Nginx y Nodo.proceso js para la prueba dada.
Aquí están los resultados de los benchmark:
En el node-cluster
benchmark se usan 2 trabajadores. Esto significa que hay 3 Nodos.procesos js en ejecución: 1 maestro y 2 trabajadores. En el punto de referencia nginx-cluster-node
tenemos 2 nodos.procesos js en ejecución. Cada prueba de Nginx tiene un único maestro de Nginx y un único proceso de trabajador de Nginx. Los puntos de referencia implican leer un archivo desde el disco, y ni Nginx ni Node.js se configuraron para almacenar el archivo en caché en la memoria.
Usar Nginx para realizar la terminación SSL para el nodo.js resulta en un aumento de rendimiento de ~16% (749 a 865 rpm). El uso de Nginx para realizar compresión gzip da como resultado un aumento de rendimiento de ~50% (5,047 rps a 7,590 rps). El uso de Nginx para administrar un clúster de procesos resultó en una penalización de rendimiento de ~-1% (8,006 rps a 7,908 rps), probablemente debido a la sobrecarga de pasar una solicitud adicional a través del dispositivo de red de bucle invertido.
Esencialmente el uso de memoria de un solo Nodo.el proceso js es de ~600 MB, mientras que el uso de memoria de un proceso Nginx es de alrededor de ~50 MB. Estos pueden fluctuar un poco dependiendo de las características que se estén utilizando, por ejemplo, Nodo.js usa ~13 MB adicionales cuando realiza la terminación SSL, y Nginx usa ~4 MB adicionales cuando se usa como verso de proxy inverso que sirve contenido estático del sistema de archivos. Una cosa interesante a tener en cuenta es que Nginx utiliza una cantidad constante de memoria a lo largo de su vida útil. Sin embargo, Nodo.js fluctúa constantemente debido a la naturaleza de recolección de basura de JavaScript.
Aquí están las versiones del software utilizado al realizar este benchmark:
- Nginx:
1.14.2
- Nodo.js:
10.15.3
- Asedio:
3.0.8
Las pruebas se realizaron en una máquina con 16 gb de memoria, un i7-7500U CPU 4x2.70GHz
, y el kernel de Linux 4.19.10
. Todos los archivos necesarios para recrear los puntos de referencia anteriores están disponibles aquí:
Intrínsecamente Labs / nodejs-proxy-inverso-puntos de referencia.
Código de aplicación simplificado
Los puntos de referencia son agradables y todo, pero en mi opinión los mayores beneficios de descargar el trabajo de un nodo.la aplicación js a un proxy inverso es la simplicidad del código. Podemos reducir el número de líneas de código de aplicación imperativo potencialmente defectuoso y cambiarlo por configuración declarativa. Un sentimiento común entre los desarrolladores es que tienen más confianza en el código escrito por un equipo externo de ingenieros, como Nginx, que en el código escrito por ellos mismos.
En lugar de instalar y administrar middleware de compresión gzip y mantenerlo actualizado en varios nodos.en su lugar, podemos configurarlo en una sola ubicación. En lugar de enviar o descargar certificados SSL y volver a adquirirlos o reiniciar los procesos de aplicación, podemos usar las herramientas de administración de certificados existentes. En lugar de agregar condicionales a nuestra aplicación para comprobar si un proceso es un maestro o un trabajador, podemos descargarlo a otra herramienta.
Un proxy inverso permite que nuestra aplicación se centre en la lógica de negocio y se olvide de los protocolos y la gestión de procesos.