¿Cómo funciona la recarga de NGINX? ¿Por qué NGINX no está recargando en caliente?
Wei Liu
September 30, 2022
Recientemente noté una publicación en Reddit que decía "¿Por qué NGINX no soporta recarga en caliente?". Extrañamente, NGINX, el servidor web más grande del mundo, ¿no soporta recarga en caliente? ¿Significa esto que todos usamos nginx -s reload
incorrectamente? Con esta pregunta, vamos a ver cómo funciona la recarga de NGINX.
¿Qué es NGINX?
NGINX es un servidor web de código abierto multiplataforma desarrollado en lenguaje C. Según las estadísticas, entre los 1000 sitios web con mayor tráfico, más del 40% utiliza NGINX para manejar las enormes solicitudes.
¿Por qué es NGINX tan popular?
¿Qué ventajas tiene NGINX para superar a otros servidores web y mantener siempre una alta tasa de utilización?
La razón principal es que NGINX está diseñado para manejar problemas de alta concurrencia. Por lo tanto, NGINX puede proporcionar un servicio estable y eficiente mientras maneja enormes solicitudes concurrentes. Además, en comparación con competidores de la misma época, como Apache y Tomcat, NGINX tiene muchos diseños extraordinarios, como una arquitectura avanzada basada en eventos, un mecanismo completamente asíncrono para manejar E/S de red y un sistema de gestión de memoria extremadamente eficiente. Estos diseños notables ayudan a NGINX a utilizar completamente los recursos de hardware de los servidores y hacen que NGINX sea sinónimo de servidor web.
Además de lo anterior, hay otras razones como:
- Un diseño altamente modular hace que NGINX tenga una gran cantidad de módulos oficiales y de terceros ricos en características.
- La licencia BSD más libre hace que los desarrolladores contribuyan voluntariamente a NGINX.
- El soporte de recarga en caliente permite a NGINX proporcionar servicios 24/7.
Entre estas razones, la recarga en caliente es nuestro tema principal hoy.
¿Qué hace la recarga en caliente?
¿Qué esperamos de la recarga en caliente? Primero, creo que los usuarios del lado del cliente no deberían darse cuenta de que el servidor se está recargando. Segundo, los servidores o servicios upstream deberían lograr una carga dinámica y manejar todas las solicitudes de los usuarios con éxito sin tiempo de inactividad.
¿En qué circunstancias necesitamos recarga en caliente? En la era de Cloud Native, los microservicios se han vuelto tan populares que cada vez más escenarios de aplicación requieren modificaciones frecuentes en el lado del servidor. Estas modificaciones, como la activación/desactivación del proxy inverso de un dominio, cambios en las direcciones upstream y cambios en la lista de permitidos/bloqueados de IP, están relacionadas con la recarga en caliente.
Entonces, ¿cómo logra NGINX la recarga en caliente?
El principio de la recarga en caliente de NGINX
Cuando ejecutamos el comando de recarga en caliente nginx -s reload
, se envía una señal HUP al proceso maestro de NGINX. Cuando el proceso maestro recibe la señal HUP, abrirá los puertos de escucha secuencialmente y comenzará un nuevo proceso de trabajo. Por lo tanto, existirán simultáneamente dos procesos de trabajo (antiguo y nuevo). Después de que el nuevo proceso de trabajo entre, el proceso maestro enviará una señal QUIT al proceso de trabajo antiguo para cerrarlo de manera ordenada. Cuando el proceso de trabajo antiguo recibe la señal QUIT, primero cerrará el manejador de escucha. Ahora, todas las nuevas conexiones solo entrarán en el nuevo proceso de trabajo, y el servidor cerrará el proceso antiguo una vez que procese todas las conexiones restantes.
En teoría, ¿podría la recarga en caliente de NGINX cumplir perfectamente con nuestros requisitos? Desafortunadamente, la respuesta es no. Entonces, ¿qué desventajas tiene la recarga en caliente de NGINX?
La recarga de NGINX causa tiempo de inactividad
-
Una recarga en caliente demasiado frecuente haría que las conexiones fueran inestables y se perdieran datos comerciales.
Cuando NGINX ejecuta el comando de recarga, el proceso de trabajo antiguo seguirá procesando las conexiones existentes y se desconectará automáticamente una vez que procese todas las solicitudes restantes. Sin embargo, si el cliente no ha procesado todas las solicitudes, perderá para siempre los datos comerciales de las solicitudes restantes. Por supuesto, esto llamaría la atención de los usuarios del lado del cliente.
-
En algunas circunstancias, el tiempo de reciclaje del proceso de trabajo antiguo es tan largo que afecta el negocio regular.
Por ejemplo, cuando hacemos proxy del protocolo WebSocket, no podemos saber si una solicitud ha sido procesada porque NGINX no analiza el marco de la cabecera. Así que, aunque el proceso de trabajo reciba el comando de salida del proceso maestro, no puede salir hasta que estas conexiones generen excepciones, se agote el tiempo de espera o se desconecten.
Aquí hay otro ejemplo, cuando NGINX actúa como proxy inverso para TCP y UDP, no puede saber con qué frecuencia se solicita una solicitud antes de que finalmente se cierre.
Por lo tanto, el proceso de trabajo antiguo suele tardar mucho tiempo, especialmente en industrias como transmisión en vivo, medios y reconocimiento de voz. A veces, el tiempo de reciclaje del proceso de trabajo antiguo podría llegar a media hora o incluso más. Mientras tanto, si los usuarios recargan el servidor con frecuencia, se crearán muchos procesos en cierre y finalmente llevarán a NGINX a un OOM, lo que podría afectar gravemente el negocio.
# siempre existe en el proceso de trabajo antiguo:
nobody 6246 6241 0 10:51 ? 00:00:00 nginx: worker process
nobody 6247 6241 0 10:51 ? 00:00:00 nginx: worker process
nobody 6247 6241 0 10:51 ? 00:00:00 nginx: worker process
nobody 6248 6241 0 10:51 ? 00:00:00 nginx: worker process
nobody 6249 6241 0 10:51 ? 00:00:00 nginx: worker process
nobody 7995 10419 0 10:30 ? 00:20:37 nginx: worker process is shutting down <= aquí
nobody 7995 10419 0 10:30 ? 00:20:37 nginx: worker process is shutting down
nobody 7996 10419 0 10:30 ? 00:20:37 nginx: worker process is shutting down
En resumen, podríamos lograr la recarga en caliente ejecutando nginx -s reload
, lo cual era suficiente en el pasado. Sin embargo, el rápido desarrollo de los microservicios y Cloud Native hace que esta solución ya no cumpla con los requisitos de los usuarios.
Si la frecuencia de actualización de su negocio es semanal o diaria, entonces esta recarga de NGINX aún podría satisfacer sus necesidades. Sin embargo, ¿qué pasa si la frecuencia de actualización se convierte en horaria o por minuto? Por ejemplo, supongamos que tiene 100 servidores NGINX, y se recarga una vez por hora, entonces necesitaría recargar 2400 veces por día; Si el servidor se recarga por minuto, entonces necesitará recargar 8,640,000 veces por día, lo cual es inaceptable.
Necesitamos una solución sin cambio de procesos, y que también pueda lograr actualizaciones de contenido inmediatas.
Recarga en caliente que surte efecto inmediatamente en la memoria
Cuando Apache APISIX nació, fue diseñado para resolver el problema de recarga en caliente de NGINX. APISIX está desarrollado basado en las pilas tecnológicas de NGINX y Lua, y es una puerta de enlace API de microservicios nativa de la nube, de alto rendimiento y completamente dinámica que utiliza etcd como su centro de configuración principal. No es necesario reiniciar el servidor para recargar la nueva configuración del servidor, lo que significa que cualquier cambio en los servicios upstream, rutas o plugins no requerirá un reinicio del servidor. Pero, ¿cómo podría APISIX eliminar las limitaciones de NGINX para lograr una recarga en caliente perfecta basándose en el hecho de que APISIX está desarrollado sobre la pila tecnológica de NGINX?
Primero, veamos la arquitectura de software de Apache APISIX:
APISIX podría lograr la recarga en caliente perfecta ya que coloca todas las configuraciones en el núcleo de APISIX y el tiempo de ejecución de los plugins para que puedan usar asignaciones dinámicas. Por ejemplo, cuando NGINX necesita configurar parámetros dentro de los archivos de configuración, cada modificación solo surtiría efecto después de la recarga. Para configurar rutas dinámicamente, Apache APISIX solo configura un servidor específico con una sola ubicación. Tenemos que usar esta ubicación como la entrada principal para que todas las solicitudes pasen primero por ella, y luego el núcleo de APISIX asignaría dinámicamente los servicios upstream específicos para ellas. El módulo de ruta de Apache APISIX podría soportar la adición/eliminación, modificación y eliminación de rutas mientras el servidor está en ejecución. En otras palabras, podría lograr una recarga dinámica. Ninguno de estos cambios llamaría la atención de los usuarios ni afectaría el negocio regular.
Ahora, presentemos un escenario clásico; por ejemplo, si queremos agregar un proxy inverso para un nuevo dominio, solo necesitamos crear un servicio upstream en APISIX y agregar una nueva ruta. NGINX no necesita reiniciarse durante este proceso. Aquí hay otro ejemplo para el sistema de plugins: APISIX podría usar un plugin de restricción de IP para lograr la función de lista de permitidos/bloqueados de IP. Todas estas actualizaciones de características son dinámicas y no necesitan un reinicio del servidor. Gracias a etcd, la estrategia de configuración podría lograr actualizaciones instantáneas usando complementos, y todas las configuraciones podrían surtir efecto inmediatamente y proporcionar la mejor experiencia de usuario.
Conclusión
La recarga en caliente de NGINX tendría un proceso de trabajo antiguo y uno nuevo en algunas circunstancias, lo que causa un desperdicio adicional de recursos. Además, una recarga en caliente demasiado frecuente podría causar una pequeña posibilidad de pérdida total de datos comerciales. Bajo el contexto de Cloud Native y microservicios, las actualizaciones de servicios se vuelven cada vez más frecuentes, y la estrategia para gestionar API también varía, lo que lleva a nuevos requisitos para la recarga en caliente.
La recarga en caliente de NGINX ya no satisface los requisitos comerciales. Es hora de cambiar a Apache APISIX, una puerta de enlace API con una estrategia de recarga en caliente más avanzada en la era de Cloud Native. Además, después de cambiar a APISIX, los usuarios podrían tener una gestión dinámica y uniforme de los servicios API, y podría mejorar significativamente la eficiencia de gestión.