Conexiones, Sesiones, Solicitudes, Registros#
Mecanismos de procesamiento de conexiones#
Angie admite varios métodos de procesamiento de conexiones. La disponibilidad de un método específico depende de la plataforma que se esté utilizando. En plataformas que admiten múltiples métodos, Angie suele seleccionar automáticamente el método más eficiente. No obstante, si es necesario, se puede elegir explícitamente un método de procesamiento de conexiones usando la directiva use.
Los siguientes métodos de procesamiento de conexiones están disponibles:
Método | Descripción |
---|---|
| Un método estándar. El módulo de soporte se crea automáticamente en plataformas que no disponen de métodos más eficientes. Las opciones de compilación |
| Un método estándar. El módulo de soporte se crea automáticamente en plataformas que no disponen de métodos más eficientes. Las opciones de compilación |
| Un método eficiente disponible en FreeBSD 4.1+, OpenBSD 2.9+, NetBSD 2.0 y macOS. |
| Un método eficiente disponible en Linux 2.6+. |
| Un método eficiente disponible en Solaris 7 11/99+, HP/UX 11.22+ (eventport), IRIX 6.5.15+, y Tru64 UNIX 5.1A+. |
| El método |
Procesamiento de solicitudes HTTP#
Una solicitud HTTP atraviesa una serie de fases, durante las cuales se realiza un tipo específico de procesamiento en cada fase.
| La fase inicial. En esta fase se invoca el módulo RealIP. |
| La fase en la que se procesan las directivas del módulo Rewrite, definidas dentro de un bloque |
| Una fase especial en la que se selecciona una location basada en la URI de la solicitud. |
| Similar a la fase |
| Una fase especial en la que la solicitud se redirige a una nueva ubicación, como en la fase |
| Durante esta fase, módulos estándar de Angie como Limit Req registran sus manejadores. |
| La fase en la que se verifica la autorización del cliente para realizar la solicitud, normalmente invocando módulos estándar de Angie como Auth Basic. |
| Una fase especial en la que se procesa la directiva satisfy any. |
| Las directivas de módulos estándar, como try_files y mirror, registran sus manejadores durante esta fase. |
| La fase en la que normalmente se genera la respuesta. Varios módulos estándar de Angie registran sus manejadores en esta etapa, incluyendo Index. Las directivas proxy_pass, fastcgi_pass, uwsgi_pass, scgi_pass y grpc_pass también se gestionan aquí. Los manejadores se invocan de forma secuencial hasta que uno de ellos genera la salida. |
| La fase final, en la que se registra la solicitud. Actualmente, solo el módulo Log registra su manejador en esta etapa para el registro de acceso. |
Procesamiento de sesiones TCP/UDP#
Una sesión TCP/UDP de un cliente atraviesa una serie de fases, durante las cuales se realiza un tipo específico de procesamiento en cada fase:
| La fase inicial tras aceptar una conexión del cliente. En esta fase se invoca el módulo RealIP. |
| Una fase preliminar para comprobar el acceso. Los módulos Set se invocan durante esta fase. |
| La fase en la que se limita el acceso del cliente antes del procesamiento real de datos. El módulo Access se invoca en esta etapa. |
| La fase en la que tiene lugar la terminación TLS/SSL. El módulo SSL se invoca durante esta fase. |
| La fase para leer los bytes iniciales de datos en el búfer de prelectura para permitir que módulos como SSL Preread analicen los datos antes del procesamiento. |
| Una fase obligatoria en la que realmente se procesan los datos, normalmente involucrando el módulo Return para enviar una respuesta al cliente. La directiva proxy_pass también se maneja aquí. |
| La fase final en la que se registra el resultado del procesamiento de la sesión del cliente. El módulo Log se invoca en esta fase. |
Procesamiento de solicitudes#
Selección de servidor virtual#
Inicialmente, se crea una conexión dentro del contexto de un servidor predeterminado. El nombre del servidor puede determinarse en las siguientes etapas del procesamiento de la solicitud, cada una de las cuales está involucrada en la selección de la configuración del servidor:
Durante el protocolo de enlace SSL, de antemano, según el SNI.
Después de procesar la línea de solicitud.
Después de procesar el campo de cabecera
Host
.
Si el nombre del servidor no se determina después de procesar la línea de solicitud o el campo de cabecera Host
, Angie utilizará un nombre vacío como nombre de servidor.
En cada una de estas etapas, se pueden aplicar diferentes configuraciones de servidor. Por lo tanto, ciertas directivas deben especificarse con precaución:
En el caso de la directiva ssl_protocols, la lista de protocolos es establecida por la biblioteca OpenSSL antes de que se aplique la configuración del servidor según el nombre solicitado a través de SNI. Como resultado, los protocolos solo deben especificarse para el servidor predeterminado.
Las directivas client_header_buffer_size y merge_slashes se aplican antes de leer la línea de solicitud. Por lo tanto, estas directivas utilizan la configuración del servidor predeterminado o la configuración del servidor elegida por SNI.
En el caso de las directivas ignore_invalid_headers, large_client_header_buffers y underscores_in_headers, que están involucradas en el procesamiento de los campos de cabecera de solicitud, la configuración del servidor depende adicionalmente de si se actualizó según la línea de solicitud o el campo de cabecera
Host
.Una respuesta de error se gestiona mediante la directiva error_page en el servidor que está procesando actualmente la solicitud.
Servidores virtuales basados en nombres#
Angie determina primero a qué servidor debe delegarse la solicitud. Considere una configuración simple donde los tres servidores virtuales escuchan en el puerto 80:
server {
listen 80;
server_name example.org www.example.org;
# ...
}
server {
listen 80;
server_name example.net www.example.net;
# ...
}
server {
listen 80;
server_name example.com www.example.com;
# ...
}
En esta configuración, Angie determina a qué servidor debe manejar la solicitud basándose únicamente en el campo de cabecera Host
. Si el valor de esta cabecera no coincide con ningún nombre de servidor o si la solicitud no contiene este campo de cabecera, Angie enviará la solicitud al servidor predeterminado para este puerto. En la configuración anterior, el servidor predeterminado es el primero, que es el comportamiento predeterminado estándar de Angie. También se puede especificar explícitamente cuál servidor debe ser el predeterminado utilizando el parámetro default_server
en la directiva listen:
server {
listen 80 default_server;
server_name example.net www.example.net;
# ...
}
Nota
Tenga en cuenta de que el servidor predeterminado es una propiedad del socket de escucha, no del nombre del servidor.
Nombres internacionalizados#
Los nombres de dominio internacionalizados (IDN) <https://en.wikipedia.org/wiki/Internationalized_domain_name>`_ deberían especificarse utilizando una representación ASCII (Punycode) en la directiva server_name (nombre del servidor):
server {
listen 80;
server_name xn--e1afmkfd.xn--80akhbyknj4f; # пример.испытание
# ...
}
Prevención de solicitudes con nombres de servidor indefinidos#
Si no se deben permitir solicitudes sin el campo de cabecera Host
, se puede definir un
servidor que descarte simplemente esas solicitudes:
server {
listen 80;
server_name "";
return 444;
}
En esta configuración, el nombre del servidor se establece como una cadena vacía, que coincide
con las solicitudes sin el campo de cabecera Host
. A continuación se devuelve un código especial no estándar 444,
que cierra la conexión.
Combinación de servidores virtuales basados en nombre y en IP#
Examinemos una configuración más compleja en la que algunos servidores virtuales escuchan en diferentes direcciones:
server {
listen 192.168.1.1:80;
server_name example.org www.example.org;
# ...
}
server {
listen 192.168.1.1:80;
server_name example.net www.example.net;
# ...
}
server {
listen 192.168.1.2:80;
server_name example.com www.example.com;
# ...
}
En esta configuración, Angie primero verifica la dirección IP y el puerto de la solicitud contra las directivas listen de los bloques server. Luego verifica el campo de cabecera Host
de la solicitud frente a las entradas server_name de los bloques server que coincidieron con la dirección IP y el puerto. Si no se encuentra el nombre del servidor, la solicitud será procesada por el servidor predeterminado. Por ejemplo, una solicitud para www.example.com
recibida en el puerto 192.168.1.1:80 será manejada por el servidor predeterminado para ese puerto — es decir, por el primer servidor — ya que www.example.com
no está definido para este puerto.
Como se mencionó anteriormente, un servidor predeterminado es una propiedad del puerto de escucha, y se pueden definir diferentes servidores predeterminados para distintos puertos:
server {
listen 192.168.1.1:80;
server_name example.org www.example.org;
# ...
}
server {
listen 192.168.1.1:80 default_server;
server_name example.net www.example.net;
# ...
}
server {
listen 192.168.1.2:80 default_server;
server_name example.com www.example.com;
# ...
}
Elección de ubicaciones#
Consideremos una configuración simple de un sitio web PHP:
server {
listen 80;
server_name example.org www.example.org;
root /data/www;
location / {
index index.html index.php;
}
location ~* \.(gif|jpg|png)$ {
expires 30d;
}
location ~ \.php$ {
fastcgi_pass localhost:9000;
fastcgi_param SCRIPT_FILENAME
$document_root$fastcgi_script_name;
include fastcgi_params;
}
}
Angie primero busca la location
de prefijo más específica dada por cadenas literales, independientemente del orden en que estén listadas. En la configuración anterior, la única ubicación de prefijo es location /
, que coincide con cualquier solicitud y se utilizará como último recurso. Luego, Angie comprueba las ubicaciones definidas por expresiones regulares en el orden en que aparecen en el archivo de configuración. La primera expresión coincidente detiene la búsqueda, y Angie utilizará esa location
. Si ninguna expresión regular coincide con una solicitud, Angie utilizará la location
de prefijo más específica encontrada anteriormente.
Nota
Las ubicaciones de todos los tipos solo prueban la parte URI de la línea de solicitud, excluyendo los argumentos. Esto se debe a que los argumentos en la cadena de consulta pueden especificarse de varias maneras, por ejemplo:
/index.php?user=john&page=1
/index.php?page=1&user=john
Además, las cadenas de consulta pueden contener cualquier número de parámetros:
/index.php?page=1&something+else&user=john
Ahora veamos cómo se procesarían las solicitudes en la configuración anterior:
La solicitud
/logo.gif
primero coincide con el prefijolocation /
y luego con la expresión regular.(gif|jpg|png)$
. Por lo tanto, es manejada por la última ubicación. Usando la directivaroot /data/www
, la solicitud se asigna al archivo/data/www/logo.gif
, y el archivo se envía al cliente.La solicitud
/index.php
también coincide inicialmente con el prefijolocation /
y luego con la expresión regular.(php)$
. En consecuencia, es manejada por esta última ubicación, y la solicitud se pasa a un servidor FastCGI que escucha enlocalhost:9000
. La directiva fastcgi_param establece el parámetro FastCGISCRIPT_FILENAME
a/data/www/index.php
, y el servidor FastCGI escribe el archivo. La variable $document_root se establece con el valor de la directivaroot
, y la variable $fastcgi_script_name se establece con el URI de la solicitud, es decir,/index.php
.La solicitud
/about.html
solo coincide con el prefijolocation /
, por lo que se maneja en esta ubicación. Usando la directivaroot /data/www
, la solicitud se asigna al archivo/data/www/about.html
, y el archivo se envía al cliente.
El manejo de la solicitud /
es más complejo. Solo coincide con el prefijo
location /
, por lo que se maneja en esta ubicación. La directiva index entonces
comprueba la existencia de archivos de índice según sus parámetros y la
root /data/www
directiva. Si el archivo /data/www/index.html
no existe pero el archivo /data/www/index.php
sí, la directiva realiza
una redirección interna a /index.php
, y Angie busca las ubicaciones nuevamente como si la solicitud hubiera sido enviada por un cliente. Como se mencionó anteriormente, la solicitud redirigida finalmente será manejada por el servidor FastCGI.
Encaminamiento y balanceo de carga#
Uno de los usos más comunes de Angie es configurarlo como servidor proxy. En este rol, Angie recibe solicitudes, las reenvía a los servidores proxied, obtiene las respuestas de esos servidores y las envía de vuelta a los clientes.
Un servidor proxy simple:
server {
location / {
proxy_pass http://backend:8080;
}
La directiva proxy_pass indica a Angie que pase las solicitudes del cliente al
backend backend:8080
(el servidor proxy). Hay muchas directivas
adicionales disponibles para configurar aún más una conexión proxy.
Encaminamiento FastCGI#
Angie puede usarse para enrutar solicitudes a servidores FastCGI que ejecutan aplicaciones desarrolladas con varios marcos y lenguajes de programación, como PHP.
La configuración más básica de Angie para trabajar con un servidor FastCGI
involucra usar la directiva fastcgi_pass en lugar de la
directiva proxy_pass, junto con directivas fastcgi_param para establecer
parámetros pasados al servidor FastCGI. Supongamos que el servidor FastCGI es
accesible en localhost:9000
. En PHP, el parámetro SCRIPT_FILENAME
se utiliza para determinar el nombre del script, y el parámetro QUERY_STRING
se utiliza para pasar los parámetros de la solicitud. La configuración resultante sería:
server {
location / {
fastcgi_pass localhost:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
}
location ~ \.(gif|jpg|png)$ {
root /data/images;
}
}
Esta configuración establece un servidor que enruta todas las solicitudes, excepto aquellas para
imágenes estáticas, al servidor proxy que opera en localhost:9000
a través del
protocolo FastCGI.
Proxy WebSocket#
Para actualizar una conexión HTTP/1.1 a WebSocket, se utiliza el mecanismo de cambio de protocolo disponible en HTTP/1.1.
Sin embargo, hay una sutileza: dado que la cabecera Upgrade
es una cabecera hop-by-hop
, no se pasa del cliente al servidor proxy. Con el proxy directo, los clientes pueden usar el método CONNECT
para evitar este problema. Este enfoque no funciona con el proxy inverso, ya que los clientes
desconocen cualquier servidor proxy, y se requiere un procesamiento especial en el servidor proxy.
Angie implementa un modo especial de operación que permite establecer un túnel
entre un cliente y un servidor proxy si el servidor proxy devuelve una respuesta
con código 101 (Switching Protocols), y el cliente solicita un cambio de protocolo
a través de la cabecera Upgrade
en la solicitud.
Como se mencionó, las cabeceras hop-by-hop, incluidas Upgrade
y
Connection
, no se pasan del cliente al servidor proxy.
Por lo tanto, para que el servidor proxy conozca la intención del cliente de
cambiar al protocolo WebSocket, estas cabeceras deben pasarse explícitamente:
location /chat/ {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
Un ejemplo más sofisticado demuestra cómo el valor del
campo de cabecera Connection
en una solicitud al servidor proxy depende de
la presencia del campo Upgrade
en la cabecera de solicitud del cliente:
http {
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
...
location /chat/ {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
}
Por defecto, la conexión se cerrará si el servidor proxy no transmite ningún dato dentro de 60 segundos. Este tiempo de espera puede aumentarse usando la directiva proxy_read_timeout. Alternativamente, el servidor proxy puede configurarse para enviar periódicamente tramas de ping WebSocket para reiniciar el tiempo de espera y comprobar si la conexión sigue activa.
Proxy de WebSocket#
Para actualizar una conexión de HTTP/1.1 a WebSocket, se utiliza el mecanismo de cambio de protocolo disponible en HTTP/1.1.
Sin embargo, hay una sutileza: dado que la cabecera Upgrade
es una cabecera hop-by-hop
, no se transmite desde el cliente al servidor al que se accede a través del proxy. Con proxying
directo, los clientes pueden utilizar el método CONNECT para sortear este problema. Este enfoque no
funciona con proxy inverso, ya que los clientes no conocen ningún servidor proxy y se requiere un
procesamiento especial en el servidor proxy.
Angie implementa un modo de operación especial que permite establecer un túnel
entre un cliente y el servidor al que se accede a través del proxy si dicho servidor remoto
devuelve una respuesta con código 101 (Switching Protocols), y el cliente solicita un cambio de protocolo
mediante la cabecera Upgrade
en la solicitud.
Como se mencionó, las cabeceras hop-by-hop, incluidas Upgrade
y
Connection
, no se transmiten desde el cliente al servidor al que se accede a través del proxy.
Por lo tanto, para que dicho servidor esté al tanto de la intención del cliente de
cambiar al protocolo WebSocket, estas cabeceras deben pasarse explícitamente:
location /chat/ {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
Un ejemplo más sofisticado demuestra cómo el valor del campo
Connection
en una solicitud al servidor al que se accede a través del proxy depende de la presencia del campo
Upgrade
en la cabecera de la solicitud del cliente:
http {
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
...
location /chat/ {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
}
Por defecto, la conexión se cerrará si el servidor al que se accede a través del proxy no transmite datos dentro de 60 segundos. Este tiempo de espera se puede aumentar utilizando la directiva proxy_read_timeout. Alternativamente, el servidor al que se accede a través del proxy puede configurarse para enviar periódicamente marcos de ping de WebSocket para restablecer el tiempo de espera y comprobar si la conexión sigue activa.
Balanceo de Carga#
El balanceo de carga entre múltiples instancias de la aplicación es una técnica ampliamente utilizada para optimizar la utilización de recursos, maximizar el rendimiento, reducir la latencia y garantizar configuraciones tolerantes a fallos.
Angie puede emplearse como un balanceador de carga HTTP altamente eficiente para distribuir el tráfico entre varios servidores de aplicaciones, mejorando así el rendimiento, la escalabilidad y la fiabilidad de las aplicaciones web.
La configuración más simple para el balanceo de carga con Angie podría verse así:
http {
upstream myapp1 {
server srv1.example.com;
server srv2.example.com;
server srv3.example.com;
}
server {
listen 80;
location / {
proxy_pass http://myapp1;
}
}
}
En el ejemplo anterior, tres instancias de la misma aplicación se ejecutan en
srv1
a srv3
. Cuando no se configura explícitamente un método de balanceo de carga,
el método predeterminado es round-robin. Otros mecanismos de balanceo de carga compatibles
incluyen: weight, least_conn, y ip_hash. Angie también admite
comprobaciones de estado del servidor en banda (o pasivas) en la implementación del proxy inverso.
Estas se configuran mediante las directivas max_fails y fail_timeout
dentro del bloque server en el contexto upstream.
Registro#
Nota
Además de las opciones enumeradas aquí, también puede habilitar el registro de depuración.
Syslog#
Las directivas error_log y access_log admiten el registro en
syslog
. Los siguientes parámetros se utilizan para configurar el registro en
syslog
:
| Especifica la dirección de un servidor |
| Establece la instalación para los mensajes de |
| Define el nivel de severidad de los mensajes de |
| Establece la etiqueta para los mensajes de |
| Desactiva la adición del campo |
Ejemplo de configuración syslog:
error_log syslog:server=192.168.1.1 debug;
access_log syslog:server=unix:/var/log/angie.sock,nohostname;
access_log syslog:server=[2001:db8::1]:12345,facility=local7,tag=angie,severity=info combined;
Nota
Las entradas de syslog se reportan no más de una vez por segundo para evitar inundaciones.