2011-02-09 2 views
99

Я запускаю nginx/ruby-on-rails, и у меня есть простая многочастная форма для загрузки файлов. Все работает нормально, пока я не решит ограничить максимальный размер файлов, которые я хочу загрузить. Для этого я установил nginx client_max_body_size на 1m (1MB) и ожидает, что статус HTTP 413 (Request Entity Too Large) будет откликаться, когда это правило ломается.nginx upload client_max_body_size issue

Проблема заключается в том, что при загрузке файла размером 1,2 МБ вместо отображения страницы ошибки HTTP 413 браузер немного зависает и затем умирает с сообщением «Соединение было сброшено во время загрузки страницы».

Я пробовал практически каждый вариант, что предлагает nginx, ничего не работает. У кого-нибудь есть идеи об этом?

Вот мой 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;  
    }  
} 

Спасибо.


**Edit**

Environment/UA: Windows XP/Firefox 3.6.13

ответ

109

nginx «не работает быстро», когда клиент сообщает ему, что он отправит тело, большее, чем client_max_body_size, отправив ответ 413 и закрыв соединение.

Большинство клиентов не читают ответы до тех пор, пока не будет отправлен весь запрос. Поскольку nginx закрывает соединение, клиент отправляет данные в закрытый сокет, вызывая TCP RST.

Если ваш HTTP-клиент поддерживает его, лучшим способом справиться с этим является отправка заголовка Expect: 100-Continue. Nginx поддерживает это правильно с 1.2.7 и ответит с ответом 413 Request Entity Too Large, а не 100 Continue, если Content-Length превышает максимальный размер тела.

+1

О, я должен указать, что в этом ответе предполагается, что клиент отправляет 'Content-Length', а не выполняет' Transfer-Encoding: chunked'. –

+2

Автор nginx опубликовал патч, чтобы исправить это в списке рассылки: http://nginx.2469901.n2.nabble.com/client-max-body-size-and-100-Continue-413-Request-Entity-Too -Large-tp7582547p7582554.html Нет слов о том, будет ли оно добавлено к ветви 1.2.x. –

+0

Спасибо, это на самом деле многое объясняет. Конечно, выглядит так: «Ожидание» - это способ поиска больших запросов. – krukid

7

От the documentation:

Необходимо иметь в виду, что браузеры не знаю, как правильно показать эту ошибку.

Я подозреваю, что это то, что происходит, если вы проверить HTTP туда и сюда с использованием таких инструментов, как Firebug или Live HTTP Headers (оба расширения Firefox), вы будете в состоянии видеть, что происходит на самом деле.

+1

Я сталкивался, что здесь, тоже: http://forum.nginx.org/read.php?2,2620 Где Nginx автор говорит, что люди могли бы попытаться изменить lingering_time/lingering_timeout - оба из которых были никакого эффекта в моем случае. Кроме того, я просто не вижу, как может возникнуть проблема с постоянным таймаутом, когда я загружаю файл размером 1,2 МБ с пределом 1 МБ, который легко может иметь устойчивое соединение 5 Мбит/с. Я понюхал ответ, и он отправляет страницу 413 с заголовком «Соединение: закрыть», но соединение, похоже, не закрывается. – krukid

+0

Наверное, мне просто трудно поверить, что даже если существует абсолютно достоверный статус HTTP 413, он не запускается в браузерах. Я искал множество мест, где люди не могут избавиться от этой страницы, и я даже не видел ее. – krukid

+0

Если вы отключите пассажир, закрывает ли соединение? –

41

Сохраняется ли ваша загрузка в самом конце? 99% перед сбоем? Тело клиента и буферы являются ключевыми, поскольку nginx должен буферизовать входящие данные. Конфигурации тела (данные тела запроса) определяют, как nginx обрабатывает объемный поток двоичных данных от клиентов с несколькими частями в логику вашего приложения.

Настройка clean освобождает пределы памяти и потребления, инструктируя nginx хранить входящий буфер в файле, а затем очищать этот файл позже с диска, удалив его.

Установите body_in_file_only на номер clean и настройте буферы для client_max_body_size.В конфигурацию исходного вопроса уже был включен файл sendfile, также увеличиваются таймауты. Я использую приведенные ниже настройки, чтобы исправить это, соответствующий вашему локальному config, server, & http контекстам.

client_body_in_file_only clean; 
client_body_buffer_size 32K; 

client_max_body_size 300M; 

sendfile on; 
send_timeout 300s; 
+0

Даже если это приведет к тому, что nginx вернет правильный HTTP 413, UA все равно пошлет целую часть тела запроса, не так ли? В этом случае я думаю, что стоит попробовать подход @ joe-shaw. – krukid

+0

@krukid, когда он выглядит, мы получили 99% -ую загрузку до того, как NGINX «не быстро», я согласен с вами. В этом случае все знаки положительно окружают объект запроса, то есть диагноз заключается в том, что логика внутреннего сервера приложений - все, что работает за Nginx. Поэтому, хотя, скорее всего, запрос был хорошо сформирован, нам необходимо подумать о том, почему NGINX задыхается от ответа. client_max_body_size должен быть первым вариантом конфигурации, на который мы смотрим, а затем рассмотрим буферы, потому что при достаточно большой загрузке правильное решение зависит от того, сколько памяти может обрабатывать и наш сервер. –

+0

@Bent Кардан. Этот подход казался лучшим, и я попробовал. Но я все еще получаю ошибку 413 примерно через 20 секунд для файла размером 4 МБ. Моя скорость не может управлять 4 МБ за 20 секунд, так что это происходит после того, как данные текут совсем немного. Мысли? – Jerome

Смежные вопросы