Volver al blog

Algoritmos de selección de bloques de servidor y ubicación de Nginx: Descripción general

Algoritmos de selección de bloques de servidor y ubicación de Nginx: Descripción general

Introducción

Nginx es una de las opciones de servidor web más populares del mundo. Es capaz de gestionar con éxito una multitud de conexiones simultáneas de clientes. Al mismo tiempo, funciona como un servidor de correo, web o proxy inverso.

Esta guía tiene como objetivo describir los métodos entre bastidores que dirigen cómo Nginx procesa las solicitudes de los clientes. Desmitificaremos el diseño de bloques de server y location, así como explicar cómo reducir mejor la aparente imprevisibilidad del manejo de solicitudes.

En primer lugar, aquí hay un tutorial completo sobre cómo instalar Nginx en su servidor Ubuntu. ¡Ahora, comencemos!

Configuración de bloques con Nginx

El enfoque lógico de Nginx implica clasificar las configuraciones destinadas a diferentes propósitos en bloques de contenido separados y más lógicos. Estos residirán en una estructura jerárquica. Cuando un cliente realiza una solicitud, Nginx inicia un proceso mediante el cual determina cuál de estos bloques de configuración es el más aplicable para atender esta solicitud. Nos centraremos en este proceso de decisión.

Los bloques principales que discutiremos serán los bloques server y los bloques location . Los bloques server son un subconjunto de las configuraciones que establece Nginx que definen qué servidor virtual será responsable de manejar un tipo de solicitud definido. Por lo general, se basan en la dirección IP, el nombre de dominio o el puerto de la solicitud entrante. Los administradores configuran múltiples bloques server. Luego, deben decidir cuál de las conexiones debe manejar la solicitud.

Los bloques location residen dentro de los bloques server. Estos son los encargados de tomar decisiones sobre cómo y qué recursos puede aprovechar para manejar las solicitudes entrantes a su servidor principal particular. Este modelo es altamente flexible. El espacio URI se puede configurar para usar estos bloques de la manera que el administrador considere mejor.

Decidir qué bloque manejará qué solicitud con Nginx

Nginx permite la definición de múltiples bloques server. Todos ellos funcionan como diferentes servidores web virtuales. Por lo tanto, debe haber un método que delimite qué servidor atenderá las solicitudes entrantes particulares. Esto se hace buscando la mejor opción para el rendimiento de la solicitud a través de un sistema de comprobaciones definidas.

Nginx se ocupa principalmente de dos directivas principales de bloques server: listen y server_name.

Buscar posibles coincidencias con la directiva 'Listen'

Lo primero que evalúa Nginx es el puerto y la dirección IP de la solicitud. Luego, lo compara con la directiva listen de cada servidor. Este análisis de la lista de servidores ayuda a aislar solo aquellos bloques server que pueden resolver la solicitud en cuestión.

Normalmente, la directiva listen definirá el puerto y la dirección IP de los que será responsable de responder un bloque server en particular. Un bloque server que no presenta una directiva listen recibe los parámetros de escucha de 0.0.0.0:80 por defecto. Si Nginx es ejecutado por un usuario normal, no raíz, el parámetro listen se define como 0.0.0.0:8080. Eso significa que, sea cual sea la interfaz, si los bloques provienen del puerto 80, los bloques definidos de esa manera responderán a ellos. Sin embargo, este valor predeterminado no tiene un gran peso en el proceso de selección de un servidor.

Puede configurar la directiva listen para:

  • Una sola dirección IP que escucha solicitudes en el puerto predeterminado (80).
  • Un solo puerto que escucha en cualquier interfaz en ese puerto.
  • Una combinación de puerto y dirección IP.
  • Una ruta de socket Unix establecida (esta opción solo tiene implicaciones cuando las solicitudes pasan a través de diferentes servidores).

Nginx implementará un conjunto de reglas al decidir a qué bloque server se enviará una solicitud. Las reglas dependen de la configuración particular de la directiva listen. Son las siguientes:

  • Si una directiva listen está incompleta, las partes que faltan obtienen sus valores predeterminados. Esto significa que la dirección IP y el puerto se completarán obligatoriamente con valores predeterminados para procesar la solicitud.
    • En este caso, un bloque que no contenga ninguna directiva listen utilizará el valor predeterminado de 0.0.0.0:80.
    • Un bloque al que le falta un puerto y tiene una dirección IP de 111.111.111.111 se convertirá en 111.111.111.111:80.
    • Cuando no hay dirección IP, un bloque con el puerto 8888 adquirirá la dirección IP predeterminada para añadirla y crear 0.0.0.0:8888.
  • Una vez determinadas la dirección IP y el puerto, Nginx buscará bloques de servidor que coincidan con ese puerto.
  • Si encuentra solo una coincidencia específica, este será el bloque de servidor. Si hay múltiples bloques que califican, Nginx recurrirá a la directiva server_name para profundizar más hasta encontrar el bloque de servidor exacto en cuestión.

Nginx solo recurrirá a evaluar la directiva server_name si no encontró el bloque de servidor con el nivel de especificidad exacto de la directiva listen. Si example.com está en el puerto 80, con una IP de 192.168.1.10, el primer bloque de este ejemplo siempre será el que atienda la solicitud. Esto es así independientemente de lo que diga la directiva server_name:

Nginx Server

Si hay más de un bloque de servicio calificado con una coincidencia de especificidad, entonces se tendrá en cuenta la directiva server_name.

Encontrar posibles coincidencias con la directiva ‘Server_Name’

Si las directivas listen son igualmente específicas, Nginx comprobará el encabezado ‘Host’ de la solicitud. Este es un valor que tendrá la IP del dominio al que el cliente intentaba acceder inicialmente. Nginx utilizará la directiva server_name dentro de cada candidato de bloque de servidor que aún califique. Realiza estas evaluaciones basándose en una fórmula. Es la siguiente:

  • El primer intento de Nginx será identificar un bloque con un server_name que coincida exactamente con el valor del encabezado ‘Host’ en la solicitud. Si lo encuentra, el bloque que contiene la coincidencia exacta será el que atienda la solicitud. En caso de que encuentre múltiples bloques, elegirá el primero de la lista.
  • Si no hay coincidencias exactas, Nginx intentará usar server_name para encontrar el bloque de servidor que coincida mediante el uso de *, un comodín al principio del nombre del bloque de servidor en la configuración. Encontrar uno con este método significa que el bloque de servidor ha sido determinado. Si encuentra más de una coincidencia, la coincidencia más larga será la que cumpla con la solicitud.
  • Sin un comodín coincidente, Nginx intentará encontrar un bloque de servidor con un comodín final coincidente. En otras palabras, este será un nombre de servidor con un * en la configuración. Si se encuentra uno, se utiliza para la solicitud. Mientras que, si se encuentran varios, Nginx utilizará una vez más la coincidencia más larga.
  • En caso de que sigan sin haber coincidencias después de ambos intentos con comodines, Nginx evaluará aquellos bloques de servidor que definen el server_name utilizando expresiones regulares (designadas por un ~ antes del nombre). La primera instancia de server_name con una expresión que coincida con la del encabezado ‘Host’ se considerará como el bloque de servidor para el manejo de la solicitud.
  • Si en este punto todavía no hay coincidencias, Nginx utilizará el bloque de servidor predeterminado para esa combinación de puerto y dirección IP.

Cada combinación de puerto/dirección IP tendrá un bloque de servidor designado. Se utilizará si las reglas para determinar el bloque de servidor adecuado para el manejo de la solicitud no dan resultado. Este será el primer bloque en la configuración que contenga una opción default_server en la directiva listen (anularía el algoritmo encontrado inicialmente). Cada combinación de dirección IP/puerto solo puede tener, como máximo, una configuración default_server.

Ejemplos de selección de bloques de servidor

Si el server_name definido coincide exactamente con el valor del encabezado ‘Host’, será el bloque de servidor seleccionado para el procesamiento de la solicitud. El siguiente ejemplo muestra un encabezado ‘Host’ de la solicitud designado como “host1.example.com”. En este caso, seleccionará el segundo servidor:

Nginx Server

Sin una coincidencia exacta, Nginx comprobará si existe el server_name con un comodín. Si no, se seleccionará la coincidencia más larga que comience con un comodín. En lo siguiente, “www.example.org” está en el encabezado “Host”. Eso significa que elegirá el segundo bloque:

server screenshot

Sin una coincidencia que comience con el comodín, Nginx pasa a una comprobación de comodín final. Se seleccionará la coincidencia más larga que termine con el comodín para el procesamiento de la solicitud. En este caso, la cabecera “Host” es “www.example.com”, por lo que elegirá el tercer bloque de servidor:

Nginx Server

Si aún no hay coincidencias, Nginx intentará hacer coincidir las directivas server_name utilizando expresiones estándar. La primera de esas expresiones se selecciona para el procesamiento de la solicitud. Si el “Host” es “www.example.com,” el segundo bloque de servidor será la opción para atender la solicitud:

Nginx Server

Si sigue sin haber coincidencias, la solicitud irá a la combinación de dirección IP y puerto que tenga configurado el servidor predeterminado correspondiente.

Coincidencia de bloques Location

Nginx también necesita establecer un algoritmo mediante el cual decidirá qué bloque location en el servidor será responsable de responder a una solicitud.

Sintaxis para bloques Location

Antes de explicar cómo decide Nginx designar el bloque location que manejará las solicitudes, revisaremos la sintaxis en las definiciones de los bloques location. Como se mencionó anteriormente, los bloques location residen en los bloques server (y en otros bloques location). Su propósito es tomar decisiones sobre cómo procesar la URI de la solicitud. La URI es la parte de la solicitud que viene después de la dirección IP y el puerto o el nombre de dominio en la solicitud.

Los bloques location suelen verse así:

Syntax for Location Blocks

Nginx comprobará la URI de la solicitud frente a location_match. La presencia o ausencia del modificador anterior dictará la forma en que Nginx intentará hacer coincidir los bloques. Dependiendo del modificador, los bloques location se interpretarán de acuerdo con las siguientes reglas:

  • Sin modificadores: Sin ningún modificador, la ubicación se interpretará como una coincidencia de prefijo. Esto significa que la ubicación proporcionada se comparará con el principio de la URI en la solicitud para determinar una coincidencia correcta.
  • =: El signo de igual significa que este bloque se considerará una coincidencia siempre que la URI de la solicitud coincida exactamente con la ubicación proporcionada.
  • ~: El modificador de tilde representa que la coincidencia del bloque location distinguirá entre mayúsculas y minúsculas.
  • ~*: La combinación de un modificador de tilde y un asterisco representa que el bloque location no distinguirá entre mayúsculas y minúsculas al buscar una coincidencia.
  • ^~: Si el modificador de tilde va precedido por un acento circunflejo, no se producirá la coincidencia de expresiones regulares siempre que este bloque sea elegido como la mejor coincidencia que no sea de expresión regular.

Ejemplos de sintaxis de bloques Location

Para presentar un ejemplo de coincidencia de prefijo, el bloque location será la selección para responder a una URI de una solicitud con la forma de /site, /site/page1/index.html o /site/index/html:

location site

Para los propósitos de esta demostración de coincidencia de URI requerida, el bloque se utilizará siempre para responder a solicitudes de URI con la forma de /page1, y no a la URI de solicitud /page1/index.html. Si este es el bloque seleccionado y cumple con la solicitud utilizando una página de índice, el manejador real de la solicitud será redirigido internamente a otra ubicación:

Nginx Server

Por ejemplo, una ubicación que debe interpretarse con una expresión que distingue entre mayúsculas y minúsculas, el siguiente bloque no podría manejar solicitudes para /FLOWER.PNG. Sin embargo, manejará solicitudes para /tortoise.jpg:

Nginx Server and Location Block Selection Algorithms: Overview

A continuación, observe un bloque que permitiría una coincidencia que no distingue entre mayúsculas y minúsculas similar a la anterior. En este caso, el bloque podría manejar tanto //tortoise.jpg y /FLOWER.PNG:

location

La variante final es aquella en la que un bloque evitaría que se produzca la coincidencia de expresiones regulares si se determina que es la coincidencia óptima que no es de expresión regular. Este puede manejar solicitudes para /costumes/ninja.html:

Nginx Server and Location Block Selection Algorithms: Overview

Para ser más precisos, los modificadores dictan la forma en que se determinan los bloques location. Esto no nos dice, sin embargo, qué utiliza Nginx como algoritmo de toma de decisiones para identificar el bloque location al que se debe enviar una solicitud. Abordemos eso a continuación.

Elegir la ubicación que manejará las solicitudes en Nginx

El método por el cual Nginx elige la ubicación que procesa una solicitud es similar a cómo se seleccionan los bloques de servidor. En otras palabras, determina la ubicación óptima para cada solicitud mediante la ejecución de un proceso. Para configurar Nginx de manera precisa y adecuada, es imperativo que comprenda este proceso.

Teniendo en cuenta las declaraciones de ubicación abordadas anteriormente, Nginx utiliza de manera similar contextos de ubicación potenciales al verificar la calificación de cada ubicación comparando con ella la URI de una solicitud dada. En esto, aplica el siguiente algoritmo:

  • Primero, Nginx verifica todos los tipos de ubicación que no incluyen una expresión regular. Lo hace buscando todas las coincidencias de prefijo basadas en la ubicación. Para hacer eso, verifica la ubicación con la URI completa de la solicitud.
  • Nginx comienza buscando una coincidencia exacta. Una vez que se identifica un bloque de ubicación que utiliza el modificador =, se compara con la solicitud URI. Si ambos coinciden exactamente, se selecciona el bloque de ubicación para manejar la solicitud en el acto.
  • Si no hay ubicaciones que coincidan exactamente con la comparación del modificador =, Nginx procede a evaluar los prefijos que no son exactos. Una vez que determina la ubicación de prefijo más larga que coincide con la URI de la solicitud, realizará las siguientes evaluaciones:
    • Si la ubicación con la coincidencia de prefijo más larga utiliza el modificador ^~, esta ubicación se elegirá de inmediato.
    • Si la ubicación con el prefijo más largo no utiliza el modificador ^~, Nginx retiene brevemente la coincidencia para permitir que cambie el enfoque de la búsqueda.
  • Una vez que se encuentra y almacena la coincidencia de ubicación de prefijo más larga, Nginx pasa a la evaluación de ubicaciones de expresiones regulares. Estas incluyen coincidencias tanto sensibles como insensibles a mayúsculas y minúsculas. Si la ubicación de prefijo coincidente más larga tiene ubicaciones regulares dentro de ella, Nginx reformará la lista para colocarlas cerca de la parte superior de la lista de ubicaciones. La primera expresión de la lista reordenada que coincida con la URI de una solicitud será la ubicación elegida para atender la solicitud.
  • Si no se encuentran expresiones regulares que satisfagan la URI de la solicitud, se elegirá la ubicación almacenada previamente para procesar la solicitud.

Nginx prioriza las coincidencias de expresiones regulares sobre las de prefijo preferente de forma predeterminada. Sin embargo, evalúa primero las ubicaciones de prefijo, de modo que la parte administradora pueda anular esta tendencia con los modificadores = y ^~.

Otra conclusión importante es que, si bien las ubicaciones de prefijo se basan típicamente en la coincidencia más específica y larga encontrada, la comprobación de expresiones regulares se detiene tan pronto como se identifica la primera coincidencia. Esto significa que la posición dentro de la configuración tiene implicaciones reales para las ubicaciones de expresiones regulares.

Un último punto a tratar es que las coincidencias de expresiones regulares dentro de la coincidencia con el prefijo más largo esencialmente se saltarán la fila durante las evaluaciones de ubicación de Nginx. Estas se colocarán en la parte superior de la lista y se evaluarán antes que otras expresiones regulares.

¿Cuándo ocurre el salto a otras ubicaciones en las evaluaciones de bloques de ubicación?

Típicamente, una vez que se evalúa una solicitud y se selecciona un bloque de ubicación para manejarla, se abordará por completo dentro de ese contexto. Esto significa que solo las directivas heredadas y las ubicaciones seleccionadas son los determinantes en el procesamiento de la solicitud, sin ninguna intervención de bloques de ubicación hermanos.

Si bien esta es una directiva general que permite el diseño predecible de bloques de ubicación, a veces ciertas directivas dentro de la ubicación también pueden activar una nueva búsqueda. En otras palabras, la regla de 'solo un bloque de ubicación' tiene algunas excepciones. Es posible que esas excepciones no se alineen con la expectativa de los bloques de ubicación. Por lo tanto, es posible que no aborden la solicitud como se esperaba.

Estas redirecciones internas pueden terminar manifestándose debido a algunas directivas que incluyen:

  • index
  • rewrite
  • error_page
  • try_files

Si utiliza la directiva index, siempre dará como resultado una redirección interna durante el manejo de la solicitud. Aunque encontrar coincidencias de location normalmente finaliza la ejecución del algoritmo para acelerar el proceso de selección, si la coincidencia de location encontrada es un directorio, es probable que la solicitud se redireccione a otra ubicación para ser procesada formalmente.

Por ejemplo, el siguiente primer location coincide con un URI de solicitud de /exact. Sin embargo, para procesar la solicitud, la directiva index que hereda el bloque location redirecciona la solicitud a un bloque secundario:

index

Para ese escenario, si la ejecución debe permanecer dentro del bloque primario, se necesitará otro esquema para procesar la solicitud al directorio. Una forma de hacerlo es configurar un index no válido para el bloque en cuestión y activar auto index en su lugar:

location exact

Aunque este método puede funcionar en algunos casos, en general no es aplicable en la práctica en la mayoría de los contextos. Una coincidencia exacta de directorio puede ser útil para situaciones en las que la solicitud necesita ser reescrita. Esto activará una búsqueda de location completamente nueva.

Otra directiva que se puede utilizar para reevaluar la ubicación de procesamiento es la directiva try_files. Le indica a Nginx que verifique específicamente si existe un conjunto específico de archivos o directorios, siendo el último criterio de búsqueda el URI al que Nginx debe redireccionar internamente.

Pensemos en la siguiente configuración:

root var

Si hay una solicitud para /blahblah, el primer location la recibirá. Al no encontrar el archivo blahblah en el directorio /var/www/main, se activará una búsqueda posterior de blahblah.html. Luego, buscará un subdirectorio llamado blahblah en el directorio /var/www/main. Si todas esas comprobaciones fallan, se redireccionará a /fallback/index.html. Esto activará otra búsqueda de location que otro bloque location recogerá. Luego, procesará el archivo /var/www/another/fallback/index.html.

Otra directiva que da como resultado una redirección a otro bloque location es la directiva rewrite. Nginx buscará un nuevo location coincidente basado en el resultado de la directiva rewrite cuando se utiliza el parámetro last. Si el último ejemplo se modifica para incluir ahora esta directiva rewrite, resulta evidente que la solicitud se puede redireccionar a otro location sin que se implemente la directiva try_files:

root var ww main

Para este ejemplo, la solicitud de /rewrite/hello será atendida inicialmente por el primer location. Después de ser reescrita a /hello, se activará una búsqueda secundaria de location. Coincidirá con el primer location. Será procesada por la directiva try_file, revirtiendo potencialmente a /fallback/index.html si no produce resultados.

Sin embargo, si se realiza una solicitud para /rewrite/fallback/hello, se encontrará una coincidencia con el primer bloque. Por lo tanto, el rewrite se procesará nuevamente, pero esta vez dará como resultado /fallback/hello. La solicitud se procesará en otro bloque location.

Situaciones similares ocurren cuando se utiliza la directiva return para enviar códigos de estado 301 o 302. La única diferencia es que se produce una nueva solicitud y se manifiesta en una redirección muy obvia. Del mismo modo, esto puede ocurrir con la directiva rewrite cuando se aplican las banderas permanent o redirect.

Otra directiva que puede conducir a redirecciones internas similares a las de try_again es la directiva error_page. Puede usarla cuando encuentre códigos de error particulares en el procesamiento. Cuando se establece una directiva try_files, es probable que la directiva error_page nunca se ejecute. Eso es porque esa directiva manejará el ciclo de vida completo de la solicitud.

Consideremos el siguiente ejemplo:

root screenshot

En este caso, cada solicitud será procesada por el primer bloque que sirve archivos desde /var/www/main. Esto no se aplica a aquellas solicitudes que comienzan con /another. Pero si no se encontrara un archivo, se iniciará una redirección interna a /another/whoops/html. Esto conducirá a otra búsqueda de location. A su vez, dirigirá la solicitud a un bloque secundario, y ese archivo se direccionará desde /var/www/another/whoops.html.

Como es evidente, la comprensión de las situaciones en las que Nginx activará una nueva búsqueda de ubicación puede ayudar a predecir mejor el comportamiento del sistema cuando se procesan las solicitudes.

Conclusión

El trabajo de los administradores se vuelve inmensamente más sencillo cuando comprenden los métodos mediante los cuales Nginx aborda las solicitudes de los clientes. Esto permite a los administradores determinar a qué bloque de servidor irá la solicitud. También pueden determinar el bloque de ubicación que se seleccionará en función de la URI de la solicitud. En general, también brinda a los administradores la capacidad de rastrear los contextos aplicados por Nginx al abordar cada solicitud.

Finalmente, puedes echar un vistazo a los otros tutoriales en nuestro blog enfocados en Nginx. Te ayudarán a beneficiarte mejor de uno de los servidores web más populares del mundo:

¡Feliz computación!

author

Manpreet Singh

Autor · CloudSigma

Preslav Dobrev es diseñador creativo en CloudSigma, centrado en una identidad empresarial coherente mediante el uso de canales de marketing tradicionales e innovadores. Es experto en fusionar la visión artística con el marketing estratégico para crear narrativas de marca impactantes.

Comentarios

Aún no hay comentarios. Sea el primero.