
En la documentación de Nginx hay directivas relativas a tres tiempos de espera de red diferentes, que se pueden configurar para servidores "backend" de la siguiente manera:
proxy_connect_timeout
Define un tiempo de espera para establecer una conexión con un servidor proxy. Cabe señalar que este tiempo de espera no suele exceder los 75 segundos.
Esto es fácil de entender: Nginx está a punto de conectarse a un servidor "backend" ascendente y si no puede conectarse dentro de un período de tiempo X, se dará por vencido y devolverá un error. El servidor es inaccesible, tiene demasiadas conexiones, etc.
proxy_read_timeout
Define un tiempo de espera para leer una respuesta del servidor proxy. El tiempo de espera se establece únicamente entre dos operaciones de lectura sucesivas, no para la transmisión de la respuesta completa. Si el servidor proxy no transmite nada dentro de este tiempo, la conexión se cierra.
Esto también tiene sentido: Nginx ya ha establecido una conexión TCP con el servidor "backend" y ahora está a punto de enviar la solicitud, pero el servidor está tardando mucho en procesar y si tarda más de X cantidad de tiempo, cierre la conexión y regresar al usuario.
De hecho, me sorprendió que Nginx cerrara la conexión. Pensé que la mantendría pero devolvería un error al usuario. Suena costoso restablecer esas conexiones TCP "backend" cada vez que algo se agota.
proxy_send_timeout
Establece un tiempo de espera para transmitir una solicitud al servidor proxy. El tiempo de espera se establece únicamente entre dos operaciones de escritura sucesivas, no para la transmisión de toda la solicitud. Si el servidor proxy no recibe nada dentro de este tiempo, la conexión se cierra.
Éste no lo entiendo del todo. Tengo una teoría pero quiero que alguien la confirme. El único valor que se me ocurre para este tiempo de espera es si la carga útil de la solicitud es enorme (por ejemplo, una solicitud POST grande con JSON o un documento que el usuario desea guardar). Transmitir la solicitud al "backend" requerirá dividir la solicitud en segmentos MTU TCP más pequeños y enviarlos como "fragmentos" de la solicitud original. Entonces, técnicamente no enviamos la solicitud hasta que transmitimos todos los fragmentos al servidor con éxito. ¿Nginx está midiendo el tiempo entre cada parte de la solicitud? ¿Es eso lo que significa "escribir" en el documento? Una vez que se envíe la solicitud, Nginx comenzará a medir el proxy_read_timeout
?
Respuesta1
TCP/IP es un protocolo de transmisión de datos llamado "streaming". Está diseñado para permitir que la parte que lea datos a través de una conexión TCP/IP no tenga que preocuparse necesariamente por el tamaño de los "segmentos" o incluso los paquetes. En la práctica, esto se traduce en una situación en la que un par que invoca alguna operación tradicional de "lectura" para obtener datos enviados por el par remoto (por ejemplo,read
con Linux), no necesariamente leerá a la vez exactamente tantos datos como los que el extremo remoto proporcionó en una sola operación de "escritura". La implementación del protocolo TCP/IP invariablemente generará paquetes IP del tamaño apropiado a partir de lo que se pasó a una operación de "escritura" a la vez, y la implementación en el otro extremo ensamblará los datos a partir de esos paquetes; pero no lo hará¡necesariamente entréguelos a alguna aplicación cliente de "lectura" con los mismos límites de datos!
Ejemplo: A tiene 50 Kb de datos para enviar por cada evento del sistema externo, por lo que no caben en la RAM todos al mismo tiempo, por lo que los envía en trozos de 16 Kb, que es el tamaño de su búfer de envío. Entonces envían primero 16Kb, luego otros 16Kb, luego otros 16Kb y finalmente 2Kb. La implementación TCP/IP podría enviar estos 50 Kb, almacenados internamente en un buffer de 128 Kb (por ejemplo, un buffer del kernel), y sólo entonces enviarlos a través de la red, que también tiene sus propias condiciones. Algunos de estos datos, fragmentados de una manera que la aplicación emisora ni siquiera es consciente, llegan primero al otro extremo (debido a las condiciones de la red) y la implementación TCP/IP los ensambla allí y los coloca en un búfer del núcleo. de nuevo. El kernel activa el proceso que quiere leer los datos, leyendo los 30 Kb. El receptor debe decidir si espera más y cómo entender cuánto más esperar: elformatodel "mensaje" o datos no es algo que le preocupe a TCP/IP.
Esto significa que Nginx no puede saber cuánto leerá la solicitud de un cliente a la vez por cada read
llamada que realizará en un sistema basado en Linux, por ejemplo.
Sin embargo, la documentación de proxy_send_timeout
insinúa ligeramente para qué sirve (el énfasis es mío):
Establece un tiempo de espera para transmitir una solicitud al servidor proxy. El tiempo de espera se establece únicamente entre dos operaciones de escritura sucesivas, no para la transmisión de toda la solicitud.Si el servidor proxy no recibe nada dentro de este tiempo, la conexión está cerrada.
La cosa es que desde Nginxapoderadosuna solicitud, lo que significa que la solicitud nooriginarcon él: espera a que el cliente "descendente" (el extremo remoto de la conexión que envió la solicitud a Nginx y que este último, en su función de "proxy", ahora espera reenviar ascendente) transmita los datos de la solicitud anterior. lo reenvía (escribe) a través de la conexión ascendente.
Según tengo entendido, si no se recibe nada desde abajo [durante el período de tiempo de espera], entonces el servidor proxy tampoco recibirá nada, y la conexión se cerrará.
Dicho de otra manera, si dicho downstream no envía nada en el plazo de tiempo indicado por proxy_send_timeout
, Nginx cerrará la conexión con el upstream.
Por ejemplo, considere un navegador web que envía una solicitud a Nginx. Nginx lee la primera pieza en el momento A. Suponiendo que enviará la solicitud a algún flujo ascendente, abre una conexión a dicho flujo ascendente y transmite (escribe) lo que ha recibido del navegador, a través del socket de conexión ascendente. Luego simplemente espera a que se lean más partes de los datos de la solicitud desde el navegador; si la siguiente parte no llega después de un tiempo de espera X relativo al tiempo A, cerrará la conexión con el flujo ascendente.
Tenga en cuenta que esto no significa necesariamente que cerrará la conexión con el navegador web; ciertamente devolverá algún código de estado de error HTTP para la solicitud, pero la vida útil de la conexión del navegador web se rige por un conjunto de condiciones diferente al de proxy_send_timeout
: Este último solo se refiere a las conexiones de Nginx con el upstream.