nginx завантажувати проблему client_max_body_size


117

У мене запущено nginx / ruby-on-rails, і у мене є проста багатостороння форма для завантаження файлів. Все працює добре, поки я не вирішу обмежити максимальний розмір файлів, які я хочу завантажити. Для цього я встановив nginx client_max_body_sizeв (1 МБ) і очікую статусу HTTP 413 (Request Entity Too Large) у відповідь, коли це правило порушується.

Проблема полягає в тому, що коли я завантажую файл 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**

Навколишнє середовище / UA: Windows XP / Firefox 3.6.13

Відповіді:


128

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 опублікував патч, щоб виправити це у списку розсилки: nginx.2469901.n2.nabble.com/… Немає жодного слова, чи буде додано його до стабільної гілки 1.2.x.
Джо Шоу

Дякую, що насправді багато що пояснює. Звичайно, схоже, Expectце шлях для великих запитів.
крукід

Я оновив свою відповідь, щоб зазначити, що патч, про який я згадував раніше, був скоєний і включений у версію 1.2.7.
Джо Шоу

Тільки для того, щоб заощадити час на приємний синтаксис (як я провів): request.setHeader(HttpHeaders.EXPECT, CONTINUE);з import org.apache.http.HttpHeaders;таimport static org.jboss.netty.handler.codec.http.HttpHeaders.Values.CONTINUE;
Ерез Коен

48

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

Цей cleanпараметр звільняє межі пам’яті та споживання, доручаючи nginx зберігати вхідний буфер у файл, а потім очищати цей файл пізніше з диска, видаляючи його.

Набір body_in_file_onlyдля cleanі настройки буферів для client_max_body_size. У початковому конфігурації питання вже було включено файл Sendfile, також збільшуйте час очікування. Я використовую наведені нижче налаштування, щоб виправити це, що підходить для локальних конфігурацій, сервера та http.

client_body_in_file_only clean;
client_body_buffer_size 32K;

client_max_body_size 300M;

sendfile on;
send_timeout 300s;

Навіть якщо це призведе до того, що nginx поверне належний HTTP 413, UA все одно в кінцевому підсумку надішле цілий орган запиту, чи не так? У цьому випадку я думаю, що варто спробувати підхід @ joe-shaw запропонував.
крукід

@krukid, коли здається, у нас завершено завантаження на 99% до того, як NGINX "провалиться швидко", я згоден з вами. У цьому випадку всі ознаки є позитивними навколо об'єкта запиту, тобто діагноз полягає в тому, що логіка внутрішнього застосування сервера нормальна - що б не стояло за Nginx. Тож, хоча це, ймовірно, запит добре сформований, наша потреба полягає в тому, щоб розглянути, чому NGINX задавлюється у відповідь. client_max_body_size повинен бути першим параметром конфігурації, який ми розглядаємо, а потім розглянемо буфери, оскільки при достатній великій кількості завантаження правильне рішення залежить від того, скільки пам’яті може працювати і наш сервер.
Бент Кардан

@Bent Cardan. Цей підхід здався кращим, і я його спробував. Але я все одно отримую помилку 413 приблизно через 20 секунд для файлу 4mb. Моя швидкість не може керувати 4 Мб за 20 секунд, тому це відбувається після того, як дані протікають зовсім небагато. Думки?
Ієронім

Я додав зміни у файл nginx.conf _client_max_body_size 300M; sendfile on; send_timeout 300s; _ Це для мене прекрасно працює Спасибі
Рамеш Чанд

Рішення для мене працює openshift php7 nginx.
marlo

7

З документації :

Потрібно пам’ятати, що браузери не знають, як правильно показати цю помилку.

Я підозрюю, що це відбувається, якщо ви оглянете HTTP сюди-сюди за допомогою таких інструментів, як Firebug або Live HTTP заголовки (обидва розширення Firefox), ви зможете побачити, що відбувається насправді.


1
Я також натрапив на це і тут: forum.nginx.org/read.php?2,2620 Де автор nginx каже, що люди можуть спробувати змінити lingering_time / lingering_timeout - і те й інше не вплинуло в моєму випадку. Крім того, я просто не бачу, як може виникнути стійка проблема таймауту, коли я завантажую файл 1,2 Мб з обмеженням 1 Мб, легко маючи стійке з'єднання 5 Мбіт / с. Я обнюхав відповідь, і вона надсилає сторінку 413 із заголовком "З'єднання: закрити", але з'єднання, здається, не закривається.
крукід

Я думаю, що мені просто важко повірити, що, хоча існує абсолютно дійсний HTTP-статус 413, він не працює в браузерах. Я гуглив багато місць, де люди не можуть позбутися цієї сторінки, і я її навіть не бачив.
крукід

Якщо ви відключите пасажира, чи закриє це з'єднання?
Марк Роуз

Ну, я порівняв відповіді з пасажиром і без нього. Коли все працює нормально, і я завантажую файл у кілька разів більший (~ 14 МБ), ніж моє обмеження на 1 МБ, я отримую 413 відповідей кілька разів (тому що клієнт продовжує надсилати шматки), і остаточне "Скидання з’єднання" виглядає як таймаут. Без пасажира я отримую одну миттєву відповідь 413 і весь прогрес припиняється, але я все одно бачу сторінку "Зновлення з’єднання", а не мою статичну 413.html або щось, що означає "Занадто великий об'єкт"
krukid
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.