Independientemente de la plataforma que utilices, el registro de eventos suele ser un requisito fundamental para el procesamiento de macrodatos, las estadísticas, las auditorías, los informes para clientes y las transacciones, así como para depurar la comunicación entre cliente y servidor y los posibles problemas.
En este blog, abordamos el papel del registro de eventos en la depuración, donde constituye la herramienta definitiva para localizar los diversos problemas tan habituales en las comunicaciones por Internet.

El registro de la comunicación entre el cliente y el servidor web resulta de gran ayuda para depurar posibles problemas relacionados con la versión del navegador, la red del cliente y los archivos a los que se accede. Sin embargo, esto no acaba aquí. Las posibilidades sobre qué registrar son infinitas y dependen por completo de su plataforma y sus requisitos.
Arquitectura de registro de NGINX
Cuando utilizas un proxy inverso, un equilibrador de carga o una red de distribución de contenidos (CDN), añades otro nodo al flujo de comunicación entre el cliente y el servidor. Un servidor intermediario que manipula datos, como un proxy inverso, suele provocar problemas inesperados.
Como proxy inverso, NGINX convierte la conexión entre el cliente y el servidor web (u otro servidor de aplicaciones) en dos conexiones independientes: finaliza la conexión del cliente y crea una nueva con el servidor. Esta «división» en dos conexiones también genera dos contextos de registro independientes, y NGINX gestiona el registro de cada uno de forma ligeramente distinta.
- Para el tráfico entre el cliente y el proxy inverso, NGINX proporciona tanto un registro de errores como un registro de acceso, que registra los eventos de procesamiento y las acciones que no son errores. El registro de errores se habilita con la directiva
error_log, y se puede establecer el nivel de gravedad de los errores que se registrarán. El registro de acceso se habilita con la directivaaccess_log. La directiva asociadalog_formatpermite personalizar el tipo de información incluida en los registros y el formato de las entradas. Los registros se pueden escribir en un archivo, enviar a syslog o ambas cosas. - Para el tráfico entre el proxy inverso y el servidor web o de aplicaciones (al que NGINX denomina servidor ascendente), NGINX admite el registro de errores. Sin embargo, no admite el registro de accesos para este tráfico. La única forma de ver eventos que no sean errores entre el servidor proxy y un servidor ascendente es establecer el nivel de gravedad del registro de errores en
debug. El inconveniente de esta configuración es que se registran enormes cantidades de datos. Esto ralentiza el procesamiento de las solicitudes y crea archivos muy grandes que pueden agotar rápidamente el espacio de almacenamiento. (Tenga en cuenta que también debe volver a compilar NGINX con el argumento--with-debugen el comandoconfigure, ya que la compatibilidad con la depuración no está habilitada de forma predeterminada).
Nuestra solución de registro para servidores upstream
Como proveedor de CDN, a menudo nos encontramos con servidores de origen que no se comunican correctamente con nuestros servidores proxy inversos y clientes. Los mensajes de nivel debug del registro de errores no siempre proporcionan la información que necesitamos para solucionar un problema con el servidor de origen.
La solución pronto resultó bastante evidente: generar un registro de acceso del servidor de origen añadiendo una función que recopile únicamente la información esencial de la comunicación entre el proxy inverso y los servidores de origen.

La idea general es hacer que NGINX llame a nuestra función cada vez que se realice una solicitud a un servidor upstream. Esto nos permite programar en la propia función toda la lógica relacionada con el registro de actividad del servidor upstream.
El módulo estándar ngx_http_upstream_module gestiona las solicitudes a servidores upstream, y necesitamos que llame a la función por nosotros. Actualmente, el módulo no admite esta funcionalidad, por lo que lo hemos parcheado para habilitar la llamada de retorno cuando sea necesario.
El registro propiamente dicho se gestiona en un módulo independiente que hemos desarrollado y que utiliza la función de devolución de llamada de registro que añadimos al módulo upstream parcheado. El nuevo módulo define una nueva directiva upstream_log para configurar la funcionalidad de registro. Esta directiva utiliza el mismo analizador que la directiva access_log, por lo que los datos pueden escribirse en un archivo o enviarse a un servidor syslog mediante un socket.
Cuando NGINX lee la directiva upstream_log en nginx.conf durante el inicio, se invocan dos funciones:
ngx_http_upstream_log_set_log, que analiza la directiva y prepara la propia estructura del registro (ngx_log_t) mediantengx_log_set_loginternamentengx_http_upstream_log_init(en un paso posterior a la configuración), que registra nuestra función principal de registro con el módulo upstream
De este modo, cuando es necesario reenviar una solicitud a un servidor upstream mediante proxy, todo está preparado. El módulo upstream establece una conexión con el servidor upstream, y nuestro parche garantiza que se invoque la función de registro para guardar los detalles de la solicitud.
El formato de registro está integrado directamente en el módulo upstream. Aún tenemos la opción de añadir compatibilidad para configurarlo mediante la directiva log_format, pero no es necesario para nuestro caso de uso.
Valores registrados del servidor upstream
La función de registro se invoca justo después de que se cierre la conexión con el servidor ascendente. Su argumento es un puntero a una solicitud que se está procesando en ese momento (la estructura ngx_http_ request_t), lo que permite a la función acceder a todos los datos de la estructura y registrarlos. El campo upstream (un puntero a ngx_http_upstream_t) resulta especialmente interesante, ya que contiene datos sobre la solicitud al servidor ascendente. Nos interesan especialmente:
- El código de estado de la respuesta del servidor de origen
- La duración de la solicitud
- El valor de una cabecera HTTP en la respuesta o de la cabecera Host
El acceso a toda la estructura de la solicitud es lo que aporta flexibilidad al módulo, ya que permite registrar una gran variedad de información.
Problemas que encontramos
Inicialmente implementamos la funcionalidad en ngx_http_core_module. Esto era suficiente para un prototipo, pero no era una solución muy limpia, ya que podía complicar futuras actualizaciones y modificaciones. Finalmente, separamos la función de registro de upstream en un módulo independiente, tal y como se describe en Nuestra solución de registro de upstream.
Por supuesto, hubo algunos problemas de implementación. En particular, en algunos puntos gestionamos incorrectamente las cadenas ngx_str_t, por ejemplo, al usar la función de la biblioteca de C sprintf en lugar de ngx_snprintf. Esto puede provocar que se escriban datos indefinidos en el registro del servidor de origen o incluso un fallo de segmentación en el hilo de trabajo. Estos problemas se resolvieron tras un exhaustivo proceso de depuración y pruebas con herramientas como Valgrind y AddressSanitizer.
Funciones de NGINX utilizadas en CDN77
La principal razón por la que CDN77 utiliza NGINX es su capacidad de almacenamiento en caché. El servidor CDN es un nodo situado entre el cliente y el servidor web (servidor de origen), que transmite las solicitudes del cliente y solicita los archivos correspondientes al servidor de origen. Una vez que el archivo se almacena en caché, se entrega a otros usuarios que soliciten el mismo archivo desde la misma ubicación.
«Archivos servidos localmente» es una de las funciones que utilizamos para que NGINX proporcione un archivo desde el disco del servidor cuando recibe una solicitud.
Para almacenar contenido en caché de forma segura, se necesitan algunas funciones y configuraciones adicionales. Utilizamos SSL (TLS 1.3 con 0‑RTT) o tokens seguros que pueden generarse para una dirección IP específica a fin de proteger adecuadamente el contenido.
Otras funciones que utilizamos incluyen páginas de error personalizadas para nuestros clientes, la implementación predeterminada de NGINX del grapado OCSP y FastCGI para PHP, con el fin de reducir el número de procesos PHP necesarios.
Conclusión
El registro de los servidores upstream no solo nos ha ayudado, y sigue haciéndolo, a depurar diversos problemas, sino que también nos ha brindado una excelente oportunidad para profundizar en las funcionalidades principales de NGINX y ha simplificado muchos otros proyectos que hemos emprendido.
Acerca de CDN77
CDN77 mejora y facilita la distribución de contenidos en todo el mundo. Con más de 30 centros de datos, podemos almacenar en caché y distribuir contenidos de forma eficaz por todo el planeta. Esto incluye el contenido estático de su sitio web, la distribución de software, el vídeo bajo demanda (VoD) y la transmisión en directo mediante diversos protocolos, como HLS o MPEG‑DASH, utilizando un motor de streaming dedicado.
Empezar a usar CDN77 es muy fácil, rápido y sencillo. Regístrese para disfrutar de una prueba gratuita, cree un recurso de CDN y utilice la URL de CDN generada o un registro CNAME personalizado para integrarlo con su sitio web o solución de streaming. Todas las funciones, opciones de configuración y posibles soluciones personalizadas garantizan que CDN77 satisfaga sus necesidades.
Sobre los autores
Artículos relacionados del blog
Únete a F5 NGINX en AppWorld 2024
Descubre las numerosas razones para asistir al evento insignia de F5, que incluirá un emocionante anuncio sobre la cartera de productos NGINX.
Rotación de certificados SSL/TLS sin reinicios en NGINX Open Source
La función de diccionario compartido permite configurar NGINX sin necesidad de reiniciarlo al renovar los certificados SSL/TLS.
Exposición de APIs en Kubernetes
La unidad 2 de Microservices March 2022 se centra en cómo exponer tus API en Kubernetes. Aquí tienes enlaces a los recursos que necesitas: la retransmisión en directo del 14 de marzo, artículos de blog y otros recursos de preparación, y el laboratorio práctico «Protege las API de Kubernetes mediante la limitación de solicitudes».
NGINX Sprint 2.0: visión clara, código renovado y nuevos compromisos con el código abierto
Hoy, en NGINX Sprint 2.0, anunciamos cómo respaldaremos nuestra visión del futuro de las aplicaciones modernas con una mayor presencia en la comunidad de código abierto, incluida la participación en el proyecto comunitario Kubernetes, nuevos proyectos de software de código abierto y la arquitectura de referencia para aplicaciones modernas.
Presentamos NGINX Plus R22
NGINX Plus R22 incorpora nuevas funcionalidades, como la compatibilidad con OCSP para verificar la revocación de certificados en TLS mutuo, el uso de varios proveedores de identidad OIDC en una configuración, el seguimiento en tiempo real de la limitación de solicitudes y conexiones en el panel de NGINX Plus y mejoras en NGINX JavaScript.
Presentamos NGINX Plus R17
NGINX Plus R17 incorpora compatibilidad con la limitación de velocidad en dos fases y con TLS 1.3, la versión más reciente del protocolo Transport Layer Security. La configuración de OpenID Connect es más sencilla y NGINX ModSecurity WAF es el doble de rápido que antes. También se ha actualizado el módulo JavaScript de NGINX.