La lista de verificación de producción definitiva de Node.js

¿Estás haciendo esto de Node bien en producción? Veamos algunos errores comunes que cometen las personas al ejecutar Node en producción (que provienen directamente de mis propios proyectos, como codedamn) y cómo se pueden mitigar.

Puede usar esto como su lista de verificación en producción cuando esté implementando aplicaciones de Node. Dado que este es un artículo de prácticas listas para producción , muchos de ellos no se aplicarán cuando desarrolle aplicaciones en su sistema local.

Ejecute el nodo en modo de clúster / procesos de nodo separados

Recuerde que Node es de un solo subproceso. Puede delegar muchas cosas (como solicitudes HTTP y lectura / escritura del sistema de archivos) al sistema operativo que lo maneja en un entorno multiproceso. Pero aún así, el código que usted escribe, la lógica de la aplicación, siempre se ejecuta en un solo hilo.

Al ejecutarse en un solo hilo, su proceso de nodo siempre está limitado a un solo núcleo en su máquina. Entonces, si tiene un servidor con varios núcleos, está desperdiciando energía de cálculo ejecutando Node solo una vez en su servidor.

¿Qué significa "ejecutar Node solo una vez"? Verá, los sistemas operativos tienen un programador integrado que es responsable de cómo se distribuye la ejecución de los procesos en las CPU de la máquina. Cuando ejecuta solo 2 procesos en una máquina de 2 núcleos, el sistema operativo determina que es mejor ejecutar ambos procesos en núcleos separados para obtener el máximo rendimiento.

Es necesario hacer algo similar con Node. Tienes dos opciones en este punto:

  1. Ejecutar Node en modo de clúster: el modo de clúster es una arquitectura que se integra en el propio Nodo. En palabras simples, Node bifurca más procesos propios y distribuye la carga a través de un único proceso maestro.
  2. Ejecutar procesos de nodo de forma independiente: esta opción es ligeramente diferente de la anterior en el sentido de que ahora no tiene un proceso maestro que controle los procesos de nodo secundarios. Esto significa que cuando genera diferentes procesos de nodo, se ejecutarán de forma completamente independiente entre sí. Sin memoria compartida, sin IPC, sin comunicación, nada.

Según una respuesta de stackoverflow, el último (punto 2) funciona mucho mejor que el primero (punto 1) pero es un poco más complicado de configurar.

¿Por qué? Porque en una aplicación de nodo, no solo existe una lógica de aplicación, sino que casi siempre cuando configura servidores en código de nodo, necesita vincular puertos. Y una sola base de código de aplicación no puede vincular el mismo puerto dos veces en el mismo sistema operativo.

Sin embargo, este problema se puede solucionar fácilmente. Las variables de entorno, los contenedores de Docker, el proxy frontend de NGiNX, etc., son algunas de las soluciones para esto.

Tasa que limita sus puntos finales

Seamos sinceros. No todo el mundo tiene las mejores intenciones para tu arquitectura. Claro, los ataques como DDoS son simplemente muy complicados de mitigar, e incluso gigantes como GitHub caen cuando sucede algo así.

Pero lo mínimo que puede hacer es evitar que un script-kiddie elimine su servidor solo porque tiene un costoso punto final de API expuesto desde su servidor sin ninguna limitación de velocidad.

Si usa Express con Node, hay 2 hermosos paquetes que funcionan a la perfección para limitar el tráfico en la Capa 7:

  1. Límite de tarifa exprés - //www.npmjs.com/package/express-rate-limit
  2. Express Slow Down - //www.npmjs.com/package/express-slow-down

Express Slow Down en realidad agrega un retraso incremental a sus solicitudes en lugar de eliminarlas. De esta manera, los usuarios legítimos, si hacen DDoS por accidente (súper actividad de hacer clic en los botones aquí y allá), simplemente se ralentizan y no tienen una tasa limitada.

Por otro lado, si hay un script-kiddie ejecutando scripts para desactivar el servidor, el limitador de velocidad Express supervisa y limita la velocidad a ese usuario en particular, según la IP del usuario, la cuenta de usuario o cualquier otra cosa que desee.

La limitación de velocidad también podría (¡debería!) Aplicarse en la Capa 4 (La Capa 4 significa bloquear el tráfico antes de descubrir su contenido, HTTP) a través de la dirección IP. Si lo desea, puede configurar una regla NGiNX que bloquea el tráfico en la capa 4 y rechaza la avalancha de tráfico proveniente de una sola IP, lo que evita que los procesos de su servidor sean abrumadores.

Utilice un servidor frontend para la terminación SSL

Node proporciona soporte listo para usar para protocolos de enlace SSL con el navegador utilizando el httpsmódulo de servidor combinado con los certificados SSL necesarios.

Pero seamos honestos aquí, su aplicación no debería preocuparse por SSL en primer lugar de todos modos. Esto no es algo que deba hacer la lógica de la aplicación. Su código de nodo solo debe ser responsable de lo que suceda con la solicitud, no del procesamiento previo y posterior de los datos que ingresan y salen de su servidor.

La terminación SSL se refiere a convertir el tráfico de HTTPS a HTTP. Y hay herramientas mucho mejores disponibles que Node para eso. Recomiendo NGiNX o HAProxy para ello. Ambos tienen versiones gratuitas disponibles que hacen el trabajo y descargan la terminación SSL de Node.

Utilice un servidor frontend para el servicio de archivos estáticos

Nuevamente, en lugar de usar métodos integrados como express.staticservir archivos estáticos, use servidores proxy inversos frontend como NGiNX para entregar archivos estáticos desde el disco.

Primero que nada, NGiNX puede hacer eso más rápido que Node (porque está construido desde cero para hacer solo eso). Pero también descarga el servicio de archivos de un proceso de nodo de un solo subproceso que podría usar sus ciclos de reloj en algo mejor.

No solo esto: los servidores proxy frontend como NGiNX también pueden ayudarlo a entregar contenido más rápido utilizando la compresión GZIP. También puede establecer encabezados de caducidad, datos de caché y mucho más, lo cual no es algo que deberíamos esperar que haga Node (sin embargo, Node aún puede hacerlo).

Configurar el manejo de errores

El manejo adecuado de errores puede ahorrarle horas de depuración e intentar reproducir errores difíciles. En el servidor, es especialmente fácil configurar la arquitectura para el manejo de errores porque usted es quien la ejecuta. Recomiendo herramientas como Sentry with Node, que registra, informa y le envía correos electrónicos cada vez que el servidor falla debido a un error en el código fuente.

Una vez que esté en su lugar, ahora es el momento de reiniciar el servidor cuando se bloquea para que todo el sitio no se caiga durante horas hasta que lo vuelva a activar manualmente.

Para ello, puede utilizar un administrador de procesos como PM2. O incluso mejor, use un entorno de contenedor acoplado con políticas como restart: alwayscon la configuración adecuada de límites de memoria y disco.

La configuración de Docker garantiza que, incluso si su contenedor se ejecuta en OME, el proceso vuelve a girar (lo que podría no suceder en un entorno PM2, ya que el sistema operativo podría matar a PM2 si hay una pérdida de memoria en algún lugar de un proceso en ejecución).

Configure los registros correctamente

Todas las respuestas se encuentran en registros. Hacks del servidor, fallos del servidor, comportamiento sospechoso del usuario, etc. Para eso, debe asegurarse de que:

  1. Todos y cada uno de los intentos de solicitud se registran con la dirección IP / método de solicitud / ruta a la que se accede, básicamente toda la información que pueda registrar (excepto información privada como contraseñas e información de tarjeta de crédito, por supuesto)
  2. Esto se puede lograr a través del paquete morgan
  3. Configure los registros de flujo de archivos en producción en lugar de la salida de la consola. Esto es más rápido, más fácil de ver y le permite exportar registros a servicios de visualización de registros en línea.
  4. No todos los mensajes de registro tienen el mismo peso. Algunos registros están ahí para depurarlos, mientras que si algunos están presentes, pueden indicar una situación de pantalones en llamas (como un hackeo del servidor o un acceso no autorizado). Utilice winston-logger para registrar diferentes niveles de registros.
  5. Configure la rotación de registros para que no obtenga un tamaño de registro en GB después de aproximadamente un mes, cuando vea el servidor.
  6. GZIP sus archivos de registro después de la rotación. El texto es barato, altamente comprimible y fácil de almacenar. Nunca debería tener problemas con los registros de texto siempre que estén comprimidos y esté ejecutando un servidor con un espacio de disco decente (25 GB +).

Conclusión

Es fácil tomar nota de algunas prácticas en producción que podrían ahorrarle lágrimas y horas de depuración más adelante. Asegúrese de seguir estas mejores prácticas y hágame saber lo que piensa diciendo Hola en mi cuenta de Twitter.

Si te gustó este artículo, encontrémonos en las redes sociales. Aquí está mi Instagram y Twitter. ¡Soy súper activo y me encantaría charlar! Vamos a conectarnos.

¡Paz!

Mehul