problema de carga de nginx client_max_body_size

117

Estoy ejecutando nginx / ruby-on-rails y tengo un formulario simple de varias partes para cargar archivos. Todo funciona bien hasta que decido restringir el tamaño máximo de los archivos que quiero cargar. Para hacer eso, configuro el nginx client_max_body_sizeen 1 m (1 MB) y espero un estado HTTP 413 (Solicitar entidad demasiado grande) en respuesta cuando esa regla se rompa.

El problema es que cuando subo un archivo de 1,2 MB, en lugar de mostrar la página de error HTTP 413, el navegador se cuelga un poco y luego muere con el mensaje "La conexión se restableció mientras la página se cargaba".

He probado casi todas las opciones que ofrece nginx, pero nada parece funcionar. ¿Alguien tiene alguna idea acerca de esto?

Aquí está mi nginx.conf:

worker_processes  1;
timer_resolution  1000ms;
events {
    worker_connections  1024;
}

http {
    passenger_root /the_passenger_root;
    passenger_ruby /the_ruby;

    include       mime.types;
    default_type  application/octet-stream;

    sendfile           on;
    keepalive_timeout  65;

    server {
      listen 80;
      server_name www.x.com;
      client_max_body_size 1M;
      passenger_use_global_queue on;
      root /the_root;
      passenger_enabled on;

      error_page 404 /404.html;
      error_page 413 /413.html;    
    }    
}

Gracias.


**Edit**

Entorno / UA: Windows XP / Firefox 3.6.13

krukid
fuente

Respuestas:

128

nginx "falla rápidamente" cuando el cliente le informa que va a enviar un cuerpo más grande que el client_max_body_sizeenviando una respuesta 413 y cerrando la conexión.

La mayoría de los clientes no leen las respuestas hasta que se envía todo el cuerpo de la solicitud. Debido a que nginx cierra la conexión, el cliente envía datos al socket cerrado, lo que provoca un TCP RST.

Si su cliente HTTP lo admite, la mejor manera de manejar esto es enviar un Expect: 100-Continueencabezado. Nginx apoya esta correctamente como de 1.2.7, y responderá con una 413 Request Entity Too Largerespuesta más que 100 Continuesi Content-Lengthexcede el tamaño máximo cuerpo.

Joe Shaw
fuente
1
Oh, debo señalar que esta respuesta asume que el cliente está enviando en Content-Lengthlugar de hacer Transfer-Encoding: chunked.
Joe Shaw
2
El autor de nginx publicó un parche para solucionar esto en la lista de correo: nginx.2469901.n2.nabble.com/… Sin embargo, no se sabe si se agregará a la rama estable 1.2.x.
Joe Shaw
Gracias, eso realmente explica mucho. Ciertamente, parece que Expectes el camino a seguir para solicitudes grandes.
krukid
Actualicé mi respuesta para tener en cuenta que el parche que mencioné anteriormente se comprometió e incorporó en la versión 1.2.7.
Joe Shaw
Solo para ahorrar el tiempo de buscar una sintaxis agradable (como la que pasé): request.setHeader(HttpHeaders.EXPECT, CONTINUE);con import org.apache.http.HttpHeaders;yimport static org.jboss.netty.handler.codec.http.HttpHeaders.Values.CONTINUE;
Erez Cohen
48

¿Tu carga muere al final? 99% antes de estrellarse? El cuerpo del cliente y los búferes son clave porque nginx debe almacenar los datos entrantes. Las configuraciones del cuerpo (datos del cuerpo de la solicitud) especifican cómo nginx maneja el flujo masivo de datos binarios desde clientes de formularios de varias partes a la lógica de su aplicación.

La cleanconfiguración libera memoria y límites de consumo al indicarle a nginx que almacene el búfer entrante en un archivo y luego limpie este archivo del disco eliminándolo.

Establecer body_in_file_onlya cleany ajustar tampones para el client_max_body_size. La configuración de la pregunta original ya tenía el archivo de envío activado, aumente también los tiempos de espera. Utilizo la configuración a continuación para solucionar esto, apropiada en su configuración local, servidor y contextos http.

client_body_in_file_only clean;
client_body_buffer_size 32K;

client_max_body_size 300M;

sendfile on;
send_timeout 300s;
Cardan doblado
fuente
Incluso si esto da como resultado que nginx devuelva un HTTP 413 adecuado, UA terminará enviando la totalidad del cuerpo de la solicitud, ¿no es así? En ese caso, creo que vale la pena probar el enfoque que sugirió @ joe-shaw.
krukid
@krukid cuando parece que obtuvimos un 99% de carga completa antes de que NGINX "falle rápidamente", estoy de acuerdo contigo. En este caso, todos los signos son positivos en torno al objeto de la solicitud, es decir, el diagnóstico es que la lógica de la aplicación del servidor interno está bien, lo que sea que se ejecute detrás de Nginx. Entonces, si bien es probable que la solicitud haya sido bien formada, nuestra necesidad es considerar por qué NGINX se ahoga con la respuesta. client_max_body_size debería ser la primera opción de configuración que veamos, luego considerar los búferes, porque con una carga lo suficientemente grande, la solución correcta depende de cuánta memoria pueda manejar nuestro servidor también.
Cardan doblado
@Bent Cardan. Este enfoque parecía ser el mejor y lo probé. Pero sigo recibiendo un error 413 después de unos 20 segundos para un archivo de 4 MB. Mis velocidades superiores no pueden administrar 4 MB en 20 segundos, por lo que sucede después de que los datos han estado fluyendo durante bastante tiempo. Pensamientos
Jerome
He agregado los cambios en el archivo nginx.conf _client_max_body_size 300M; sendfile on; send_timeout 300s; _ Funciona perfectamente para mí Gracias
Ramesh Chand
La solución funciona para mí openshift php7 nginx.
marlo
7

De la documentación :

Es necesario tener en cuenta que los navegadores no saben cómo mostrar correctamente este error.

Sospecho que esto es lo que está sucediendo, si inspecciona el HTTP de un lado a otro usando herramientas como Firebug o Live HTTP Headers (ambas extensiones de Firefox) podrá ver lo que realmente está sucediendo.

ZoFreX
fuente
1
También me he encontrado con eso aquí: forum.nginx.org/read.php?2,2620 Donde el autor de nginx dice que la gente podría intentar cambiar lingering_time / lingering_timeout, los cuales no tuvieron ningún efecto en mi caso. Además, simplemente no veo cómo podría haber un problema de tiempo de espera persistente cuando estoy cargando un archivo de 1.2MB con un límite de 1MB fácilmente teniendo una conexión estable de 5Mbps. He olido la respuesta y envía la página 413 con el encabezado "Conexión: cerrar", pero la conexión no parece cerrarse.
krukid
Supongo que me cuesta creer que, aunque hay un estado HTTP 413 perfectamente válido, no se activa en los navegadores. Busqué en Google muchos lugares donde la gente no puede deshacerse de esa página y ni siquiera la vi.
krukid
Si inhabilita al pasajero, ¿cierra la conexión?
Mark Rose
Bueno, comparé las respuestas con y sin pasajero. Cuando todo funciona normalmente y subo un archivo varias veces más grande (~ 14 MB) que mi restricción de 1 MB, obtengo una respuesta 413 varias veces (porque el cliente sigue enviando fragmentos) y el "restablecimiento de la conexión" final parece un tiempo de espera. Sin pasajero, obtengo una respuesta instantánea 413 y todo el progreso se detiene, pero todavía veo la página "Restablecimiento de conexión", no mi 413.html estático ni nada que implique "Entidad demasiado grande"
krukid