NGINX Plus R9 incorpora la capacidad de usar un proxy inverso y equilibrar la carga del tráfico UDP, una mejora significativa de las funciones de equilibrio de carga de capa 4 de NGINX Plus.
Esta entrada de blog analiza los retos que plantea ejecutar un servidor DNS en una infraestructura de aplicaciones moderna para mostrar cómo tanto NGINX Open Source como NGINX Plus pueden equilibrar de forma eficaz y eficiente la carga del tráfico UDP y TCP. (Las comprobaciones [activas] del estado de las aplicaciones son exclusivas de NGINX Plus, pero, por lo demás, la información de este blog se aplica igualmente a NGINX Open Source; para abreviar, en el resto de la entrada nos referiremos a NGINX Plus).
[Editor: Para obtener una visión general de todas las novedades de NGINX Plus R9, consulte «Presentamos NGINX Plus R9» en nuestro blog.]
¿Por qué equilibrar la carga del tráfico UDP?
A diferencia de TCP, UDP no garantiza por diseño la entrega de datos de extremo a extremo. Es como enviar un mensaje mediante una paloma mensajera: se sabe con certeza que el mensaje se ha enviado, pero no se puede asegurar que haya llegado. Este enfoque «sin conexión» ofrece varias ventajas, entre las que destaca una latencia inferior a la de TCP, tanto porque los mensajes individuales más pequeños de UDP consumen menos ancho de banda como porque no existe un proceso de negociación para establecer una conexión. UDP deja en manos del desarrollador de la aplicación la detección de tiempos de espera agotados y otros problemas de red. Pero ¿qué implica esto para DNS?
Al igual que otros protocolos basados en UDP, DNS utiliza un flujo de datos de solicitud y respuesta. Por ejemplo, un cliente DNS solicita la dirección IP correspondiente a un nombre de host y recibe una respuesta. Si la respuesta no llega dentro de un periodo de espera determinado, el cliente DNS envía la misma solicitud a un servidor DNS «de respaldo». Sin embargo, tener que esperar a que finalice dicho periodo antes de volver a intentar una solicitud puede convertir un proceso que normalmente es extremadamente rápido (medido en milisegundos) en uno muy lento (medido en segundos).

El uso de NGINX Plus para actuar como proxy y equilibrar la carga del tráfico DNS reduce el número de ocasiones en las que el cliente experimenta un tiempo de espera agotado. Al disponer de varios servidores DNS detrás del equilibrador de carga NGINX Plus, los clientes solo experimentan un tiempo de espera agotado cuando se produce una partición de red entre el cliente y NGINX Plus. Cuando NGINX Plus utiliza comprobaciones del estado de las aplicaciones, los problemas de los propios servidores DNS no afectan al cliente. Al supervisar la disponibilidad y el tiempo de respuesta de cada servidor, NGINX Plus evita enviar solicitudes de clientes a servidores que no funcionan correctamente.
DNS no es solo un protocolo UDP
Aunque la gran mayoría del tráfico DNS se realiza mediante UDP, hay operaciones DNS habituales que utilizan TCP. DNS utiliza UDP para mensajes pequeños (de hasta 512 bytes), pero recurre a TCP para las operaciones que requieren (o probablemente requieran) mensajes de mayor tamaño. Históricamente, TCP solo se utilizaba con DNS para transferencias de zona desde un servidor de nombres principal y autoritativo a sus servidores de nombres secundarios. Sin embargo, con la transición hacia los contenedores y la infraestructura inmutable, DNS se utiliza cada vez más como principal mecanismo de descubrimiento de servicios mediante el uso de registros SRV.
Los registros DNS SRV records se introdujeron originalmente para que los teléfonos de voz sobre IP (VoIP) que utilizan SIP pudieran detectar sus servidores, pero pueden utilizarse para cualquier tipo de servicio. Sin embargo, los registros SRV contienen mucha más información que la mayoría de los demás tipos de registros DNS. Como resultado, en una respuesta UDP estándar de 512 bytes solo caben unos 10 registros SRV, frente a unos 30 registros A. Cuando una respuesta DNS supera el límite de 512 bytes, se devuelven los primeros 512 bytes, pero la respuesta se marca como «truncada». En ese momento, un cliente DNS puede gestionar la respuesta truncada lo mejor que pueda o volver a intentar la misma solicitud mediante TCP.
Esto significa que, al equilibrar la carga de los servidores DNS en una infraestructura de red moderna, NGINX Plus puede esperar recibir una combinación de tráfico UDP y TCP.
DNS en un entorno de microservicios
La siguiente ilustración muestra una vista simplificada de un entorno de microservicios con dos balanceadores de carga. El balanceador de carga del frontend actúa como proxy de las solicitudes de los clientes públicos de la aplicación, selecciona la mejor instancia de microservicio y realiza muchas otras funciones que no abordaremos aquí. Nos centraremos en el balanceador de carga DNS, que se sitúa entre el entorno de microservicios y los servidores DNS que proporcionan información de descubrimiento de servicios a los microservicios.

Configuración básica del balanceo de carga de DNS
NGINX Plus implementa el balanceo de carga de capa 4 en el módulo Stream, por lo que el balanceo de carga UDP y TCP se configura en el bloque stream, como se muestra en el siguiente fragmento.
Advertencia: No puede limitarse a añadir este fragmento de configuración como un archivo nuevo en el directorio /etc/nginx/conf.d. Se produce un error de validación («la directiva stream no está permitida aquí»), porque el archivo de configuración predeterminado de NGINX Plus, nginx.conf, incluye el contenido de los archivos del directorio conf.d en el bloque http. La solución más sencilla es incluir el bloque stream completo directamente en nginx.conf.
stream { upstream dns_servers {
server 192.168.136.130:53;
server 192.168.136.131:53;
}
server {
listen 53 udp;
listen 53; #tcp
proxy_pass dns_servers;
error_log /var/log/nginx/dns.log info;
}
}Primero definimos el grupo de servidores DNS ascendentes. Las directivas «server» especifican el número de puerto en el que escuchan nuestros servidores ascendentes: el 53 (el puerto estándar para DNS).
El bloque server{} define cómo gestiona NGINX Plus el tráfico DNS entrante. Las dos directivas listen indican a NGINX Plus que escuche en el puerto 53 el tráfico tanto UDP como TCP. TCP es el protocolo predeterminado de la capa 4 para el módulo Stream, por lo que no lo especificamos explícitamente como parámetro, a diferencia de lo que hacemos con UDP.
La directiva proxy_pass indica a NGINX Plus qué debe hacer con el tráfico que recibe. En este caso, redirigimos dicho tráfico al grupo de servidores ascendentes dns_servers. NGINX Plus utiliza automáticamente UDP al reenviar solicitudes UDP de clientes a servidores ascendentes (y TCP para las solicitudes TCP de clientes), por lo que no es necesario especificar explícitamente el protocolo de capa 4 en el grupo de servidores ascendentes.
No existe ninguna directiva access_log en el módulo Stream, ya que NGINX Plus no inspecciona la carga útil de los segmentos TCP ni de los datagramas UDP (como sí hace con los paquetes HTTP). Sin embargo, podemos usar el parámetro info en la directiva error_log para registrar el procesamiento de las conexiones y los eventos del proxy.
[Editor: El registro de accesos se habilitó en el módulo Stream después de la publicación de este blog, en NGINX Open Source 1.11.4 y NGINX Plus R11.]
Ajustes para una alta disponibilidad
Para mejorar la disponibilidad de nuestros servidores DNS, podemos añadir un par de directivas más y configurar comprobaciones de estado activas (a nivel de aplicación).
Configuración del número de respuestas del proxy y de la duración del tiempo de espera
La primera directiva adicional es proxy_responses, que indica cuántas respuestas espera NGINX Plus por cada solicitud UDP enviada mediante proxy. En nuestro caso, tras recibir una única respuesta, NGINX Plus deja de esperar inmediatamente más respuestas, lo que libera la memoria y el socket utilizados para esa sesión.
La segunda directiva adicional, proxy_timeout, determina cuánto tiempo espera NGINX Plus una respuesta del servidor (en este caso, reducimos el valor predeterminado de 10 minutos a 1 segundo). Si NGINX Plus no recibe ninguna respuesta durante este periodo, prueba con el siguiente servidor del grupo de servidores ascendentes y marca el servidor ascendente que no responde como no disponible durante un periodo determinado (10 segundos de forma predeterminada), para que ningún otro cliente sufra durante ese tiempo un retraso provocado por el tiempo de espera agotado.
server { listen 53 udp;
listen 53; #tcp
proxy_pass dns_servers;
error_log /var/log/nginx/dns.log info;
proxy_responses 1;
proxy_timeout 1s;
}También podemos cambiar el tiempo durante el cual un servidor se marca como no disponible incluyendo la opción fail_timeout en la directiva server del grupo de servidores upstream. Con la siguiente configuración, NGINX Plus marca los servidores upstream que han fallado como no disponibles durante 60 segundos:
upstream dns_servers { server 192.168.136.130:53 fail_timeout=60s;
server 192.168.136.131:53 fail_timeout=60s;
}Esto nos permite controlar el retraso que experimenta un cliente si falla uno de nuestros servidores DNS. Sin embargo, si se intenta realizar una solicitud TCP a un servidor DNS que ha fallado, la comprobación de errores inherente a TCP permite que NGINX Plus lo marque automáticamente como no disponible, de modo que se eviten las solicitudes TCP o UDP posteriores a dicho servidor.
Configuración de comprobaciones de estado activas
La función de comprobación activa del estado de NGINX Plus es una herramienta adicional de gran valor para garantizar la alta disponibilidad de cualquier servicio con equilibrio de carga, incluido DNS. En lugar de esperar a que falle una solicitud TCP real de un cliente DNS antes de marcar el servidor DNS como inactivo, hacemos que NGINX Plus intente periódicamente establecer una conexión TCP en el puerto 53 para comprobar si el servidor DNS está activo y funciona correctamente. Para ello, incluimos la directiva health_check con su parámetro port=53 en el bloque server{}. (De forma predeterminada, NGINX Plus envía las comprobaciones de estado al puerto especificado por la directiva listen, que en nuestro caso es el 53. Por tanto, aquí usamos el parámetro para configurar explícitamente el valor predeterminado, aunque podríamos especificar otro puerto si también modificáramos nuestros servidores DNS para que respondieran al tráfico en él).
Con UDP, podemos ir un paso más allá y configurar una comprobación de estado activa que realice una consulta DNS real de un registro conocido. Por ejemplo, podríamos añadir el siguiente registro CNAME al archivo de zona del mismo subdominio que se utiliza para la detección de servicios en el entorno de microservicios.
healthcheck IN CNAME healthy.svcs.example.com.Dada la naturaleza ligera de UDP, podemos observar el tráfico de red y extraer fácilmente la cadena de bytes que representa una consulta DNS. A continuación, creamos un bloque de configuración match con esa cadena como parámetro de la directiva send. La directiva expect especifica la respuesta que debe devolver el servidor para que se considere que funciona correctamente.
match dns_lookup {
send x00x01x00x00x00x01x00x00x00x00x00x00x06x68x65x61 ...;
expect ~* "healthy.svcs.example.com.";
}La ventaja de esta comprobación exhaustiva del estado a nivel de aplicación es que, aunque el servidor de nombres esté en funcionamiento, realizar una consulta DNS real para el dominio de producción permite detectar problemas de configuración y daños en los datos que, de otro modo, podrían causar problemas en fases posteriores.
El equipo de soporte de NGINX Plus puede ayudarle a preparar comprobaciones de estado UDP para consultas DNS y otros protocolos.
El siguiente fragmento destaca las directivas adicionales necesarias para las comprobaciones de estado activas.
stream { upstream dns_servers {
zone dns_mem 64k;
server 192.168.136.130:53 fail_timeout=60s;
server 192.168.136.131:53 fail_timeout=60s;
}
match dns_lookup { send x00x01x00x00x00x01x00x00x00x00x00x00x06x68x65x61 ...; expect ~* "healthy.svcs.example.com."; }
server {
listen 53 udp;
listen 53; #tcp
health_check match=dns_lookup interval=20 fails=2 passes=2 udp;
health_check interval=20 fails=1 passes=2 port=53; #tcp
proxy_pass dns_servers;
error_log /var/log/nginx/dns.log debug;
proxy_responses 1;
proxy_timeout 1s;
}
}La directiva «zone» define una zona de memoria compartida denominada «dns_mem», que pone los resultados de las comprobaciones de estado (y otra información de estado) a disposición de todos los procesos de trabajo de NGINX Plus.
La directiva «match» se explica justo arriba.
La directiva health_check tiene varios parámetros que puede ajustar a su entorno. Aquí definimos comprobaciones de estado independientes para UDP y TCP, respectivamente. Debido a las diferencias entre UDP y TCP, exigimos que se produzcan dos fallos consecutivos en la comprobación de estado UDP antes de marcar el servidor DNS como no disponible, pero solo un fallo en el caso de TCP. Para ambos protocolos, exigimos dos respuestas correctas antes de volver a marcar un servidor como disponible, a fin de evitar el envío de solicitudes a un servidor inestable que cambia constantemente de estado.
Una ventaja de definir un único grupo de servidores DNS ascendentes para el tráfico UDP y TCP es que, si falla la comprobación de estado de cualquiera de los dos protocolos, el servidor se marca como no disponible y se elimina del conjunto con balanceo de carga.
Optimización para escalar
Aunque implementar solo dos servidores backend puede ser una solución eficaz de alta disponibilidad, las capacidades de balanceo de carga de NGINX Plus permiten escalar horizontalmente los servidores backend sin que el cliente lo sepa.
Es poco probable que el entorno de microservicios de ejemplo descrito anteriormente requiera escalar los servidores DNS de backend. Sin embargo, un proveedor de servicios de Internet que ofrece servicios DNS a todos sus abonados soporta una carga constante y la posibilidad de que se produzcan grandes picos, lo que hace necesario disponer de un gran número de servidores DNS y de un proxy de frontend que distribuya la carga del tráfico entre ellos.
Todos los algoritmos de balanceo de carga de NGINX y NGINX Plus están disponibles tanto para TCP y UDP como para HTTP:
- Round Robin (opción predeterminada)
- Hash genérico y su variante consistente (algoritmo ketama)
- Hash de IP
- Menor número de conexiones
- Menor tiempo (solo NGINX Plus)
(También puede configurar ponderaciones en todos los algoritmos para aumentar aún más su eficiencia. Para obtener más información, consulte la sección sobre ponderaciones del artículo «Cómo elegir una técnica de balanceo de carga de NGINX Plus» de nuestro blog.)
Mientras que las solicitudes HTTP pueden variar enormemente en cuanto a la carga y las exigencias de procesamiento que imponen a los servidores backend, las solicitudes DNS suelen generar todas la misma carga. Por este motivo, es poco probable que los algoritmos de Menor número de conexiones y Menor tiempo ofrezcan alguna ventaja frente al de Round Robin. En concreto, el algoritmo de Menor número de conexiones incluye en su recuento cualquier solicitud UDP para la que NGINX Plus siga esperando una respuesta del servidor ascendente. Mientras no se alcancen los valores de proxy_responses y proxy_timeout, NGINX Plus seguirá contabilizando conexiones de servidores ascendentes que quizá ya hayan terminado su trabajo.
Cuando se dispone de un gran número de clientes y de un protocolo con mucho «diálogo» —es decir, con múltiples mensajes intercambiados entre el cliente y el servidor, como en el flujo de desafío-respuesta de RADIUS—, el uso de un hash de la IP de origen permite que ese diálogo tenga lugar con un único servidor backend. En otras palabras, establece persistencia de sesión, lo que significa que NGINX Plus dirige todas las solicitudes de un cliente determinado al mismo servidor. En el siguiente ejemplo se configura el algoritmo de balanceo de carga Hash para un par de servidores de autenticación RADIUS, utilizando como clave la dirección IP de origen (del cliente), capturada por la variable $remote_addr.
upstream radius_servers { hash $remote_addr; # Source-IP hash
server 192.168.136.201:1812;
server 192.168.136.202:1812;
}Más información
Para obtener más información sobre el balanceo de carga UDP y TCP, consulta los siguientes recursos:
- Equilibrado de carga TCP y UDP en la Guía de administración de NGINX Plus
- Módulo Stream de NGINX y contexto de configuración
upstreamconfiguration context - Guía de implementación para equilibrar la carga de servidores Microsoft® Exchange™, que deben gestionar tráfico basado tanto en TCP como en HTTP
- Alta disponibilidad de MySQL con NGINX Plus y Galera Cluster<.htmla> (caso de uso de balanceo de carga TCP)
Para conocer las demás fantásticas funciones de NGINX Plus R9, consulte Presentamos NGINX Plus R9 en nuestro blog y vea nuestro seminario web bajo demanda, Novedades de NGINX Plus R9.
Para probar NGINX Plus, inicie hoy mismo su prueba gratuita de 30 días o póngase en contacto con nosotros para hablar sobre sus casos de uso.
Sobre el autor

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.