Можлива причина кодів помилок NGINX 499


116

Я отримую багато 499 кодів помилок NGINX. Я бачу, що це питання клієнта. Це не проблема з NGINX або моїм стеком uWSGI. Я зазначу кореляцію в журналах uWSGI, коли get 499.

address space usage: 383692800 bytes/365MB} {rss usage: 167038976
bytes/159MB} [pid: 16614|app: 0|req: 74184/222373] 74.125.191.16 ()
{36 vars in 481 bytes} [Fri Oct 19 10:07:07 2012] POST /bidder/ =>
generated 0 bytes in 8 msecs (HTTP/1.1 200) 1 headers in 59 bytes (1
switches on core 1760)
SIGPIPE: writing to a closed pipe/socket/fd (probably the client
disconnected) on request /bidder/ (ip 74.125.xxx.xxx) !!!
Fri Oct 19 10:07:07 2012 - write(): Broken pipe [proto/uwsgi.c line
143] during POST /bidder/ (74.125.xxx.xxx)
IOError: write error

Я шукаю більш глибоке пояснення і сподіваюся, що це нічого поганого в моєму конфігурації NGINX для uwsgi. Я приймаю це за номінал. Здається, це проблема клієнта.


Ви коли-небудь знаходили рішення для цього? Я бачу точно таку ж проблему і з uWSGI, і з nginx.
Радж

1
Я отримую це, коли я перериваю запит на jQuery ajax.
mpen

1
Я знаю, що це дуже давнє запитання, але кількість неправильно поставлених запитань на SO надзвичайна. Це явно належить до SF.
Sosukodo

Відповіді:


163

HTTP 499 в Nginx означає, що клієнт закрив з'єднання до того, як сервер відповів на запит. На мій досвід, як правило, викликано очікування клієнта на стороні . Як я знаю, це специфічний код помилки Nginx.


1
Як особливий випадок, я помітив, що це іноді трапляється, коли кінцевий користувач двічі клацає кнопку подання форми. Форма надсилається двічі, але клієнт очікує лише одну відповідь. Це можна вирішити, відключивши (принаймні на кілька секунд) кнопки в JS під час першого натискання.
Антуан Пінсар

14
Важливо зазначити, що "клієнт" насправді може бути проксі-сервером. Наприклад, якщо ви використовуєте балансир завантаження, він може скасувати запит на сервер nginx через час очікування.
Бред Кох

Це відбувається в моєму кутовому додатку, якщо користувач закриває вкладку, а мої запити API не завершуються.
Vivek Saurabh

Важливо зазначити, що це також може бути викликано сервером ; якщо сервер займає занадто багато часу для відповіді, клієнт здається.
ijoseph

78

У моєму випадку я був нетерплячим і закінчився неправильним тлумаченням журналу.

Насправді справжньою проблемою було спілкування між nginx та uwsgi, а не між браузером та nginx. Якби я завантажив сайт у своєму браузері і зачекав досить довго, я отримав би "504 - Bad Gateway". Але це зайняло так багато часу, що я продовжував пробувати речі, а потім оновлювався в браузері. Тому я ніколи не чекав досить довго, щоб побачити помилку 504. При оновленні в браузері, тобто коли попередній запит закритий, і Nginx пише, що в журналі як 499.

Розробка

Тут я припускаю, що читач знає так само мало, як я, коли я почав грати.

У моїй установці був зворотний проксі, сервер nginx та сервер додатків, сервер uWSGI за ним. Усі запити від клієнта переходитимуть до сервера nginx, потім пересилаються на сервер uWSGI, а потім відповідь надсилається тим же шляхом назад. Я думаю, саме так усі використовують nginx / uwsgi і повинні використовувати його.

Мій nginx працював як слід, але з сервером uwsgi щось не було. Є два способи (можливо більше), коли сервер uwsgi не може відповісти на nginx-сервер.

1) uWSGI каже: "Я обробляю, просто зачекайте, і ви незабаром отримаєте відповідь". nginx має певний проміжок часу, який він готовий чекати, fx 20 секунд. Після цього він відповість клієнтові з помилкою 504.

2) uWSGI мертвий, або uWSGi помирає, поки nginx чекає на нього. nginx бачить це відразу, і в цьому випадку він повертає помилку 499.

Я перевіряв налаштування, роблячи запити у клієнта (браузера). У браузері нічого не сталося, він просто продовжував висіти. Через 10 секунд (менше часу очікування) я зробив висновок, що щось не так (що було правдою), і закрив сервер uWSGI з командного рядка. Тоді я б перейшов до налаштувань uWSGI, спробував щось нове, а потім перезапустив сервер uWSGI. Щойно я закрив сервер uWSGI, сервер nginx поверне помилку 499.

Тому я продовжував налагоджувати помилку 499, що означає гуглінг за помилку 499. Але якби я досить довго чекала, я отримала б помилку 504. Якби я отримав помилку 504, я міг би краще зрозуміти проблему, а потім зможу налагоджувати.

Отже, висновок полягає в тому, що проблема була в uWGSI, який продовжував висіти ("Почекайте ще трохи, ще трохи довше, тоді у мене буде відповідь за вас ...").

Як я вирішив цю проблему, я не пам'ятаю. Я думаю, це може бути викликано багатьма речами.


1
Як ви закінчилися вирішувати це? У мене те саме питання, і я не зміг усунути причину.
Colin Ніколс

1
Я додав розробки, на жаль, не думаю, що це вирішить вашу проблему.
Mads Skjern

1
Просто хотів сказати спасибі! У мене була точно така ж ситуація, і це поставило мене в правильний шлях.
Аарон

3
@Shafiul: Моя розробка не пояснює, що спричинило проблему з uWSGI, вона просто пояснює, що uWSGI був причиною (а не nginx). Розробка описує симптоми та те, як я їх неправильно трактував. Я розумію ваше розчарування, але ви неправильно зрозуміли суть моєї відповіді. З повагою.
Mads Skjern

2
Надзвичайно корисна відповідь, ніколи не видаляйте! Ці поняття десь допрацьовуються в документації, ви робите чудову послугу, розробивши, як вона поводиться інакше, ніж це означало б документи!
jerclarke

21

Клієнт закрив з'єднання, це не означає, що це проблема із браузером! Зовсім не!

Ви можете знайти 499 помилок у файлі журналу, якщо перед веб-сервером (nginx) у вас є LB (балансир завантаження) або AWS, або haproxy (користувацький). Це сказало, що LB буде виступати клієнтом nginx.

Якщо ви використовуєте параметри за замовчуванням haproxy для:

    timeout client  60000
    timeout server  60000

Це означатиме, що LB вичерпається через 60000 мс, якщо не буде відповіді від nginx. Час очікування може виникнути для зайнятих веб-сайтів або сценаріїв, яким потрібно більше часу для виконання. Вам потрібно буде знайти тайм-аут, який буде працювати для вас. Наприклад, поширіть його на:

    timeout client  180s
    timeout server  180s

І вас, мабуть, встановлять.

Залежно від налаштувань, у вашому браузері може бути помічена помилка таймауту 504 шлюзу, що вказує на те, що з php-fpm щось не так, але це не так з 499 помилками у ваших файлах журналу.


12

По мірі вказування 499на аборт з'єднання, що реєструється nginx. Але зазвичай це виробляється, коли ваш сервер із заднім часом надто повільний , а інший тайм-аут проксі-сервера спочатку або користувальницьке програмне забезпечення припиняє з'єднання. Тому перевірте, чи відповідає uWSGI швидко чи ні, чи є завантаження на сервер uWSGI / База даних.

У багатьох випадках між користувачем та nginx є деякі інші проксі. Деякі можуть бути у вашій інфраструктурі, наприклад, CDN, Load Balacer, кеш лаку тощо. Інші можуть бути в користувачеві, як проксі-кешування тощо.

Якщо на вашій стороні є проксі-сервери, як LoadBalancer / CDN ... вам слід встановити тайм-аути, щоб вимкнути спочатку свій бекенд і поступово інші проксі-сервера для користувача.

Якщо у вас є:

user >>> CDN >>> Load Balancer >>> Nginx >>> uWSGI

Я рекомендую вам встановити:

  • n секунд до uWSGI таймауту
  • n+1 секунд до часу очікування nginx
  • n+2 секунд до таймауту для завантаження балансира
  • n+3 секунд таймауту до CDN.

Якщо ви не можете встановити деякі тайм-аути (наприклад, CDN), знайти те, що є його таймаутом, і відрегулювати інші відповідно до нього ( n, n-1...).

Це забезпечує правильний ланцюг тайм-аутів. і ви дійсно знайдете, чиє надання таймауту та поверне правильний код відповіді користувачеві.


8

У моєму випадку я отримав 499, коли API клієнта закрив з'єднання, перш ніж він отримав будь-яку відповідь. Буквально надіслано POST та негайно закрити з'єднання. Це вирішується варіантом:

proxy_ignore_client_abort увімкнено

Nginx doc


3
Я не розумію, як це допомагає
Володимир Старков

Можливо, це не ваш випадок? Клієнт надсилає дані і не цікавиться, що з ними станеться і що буде відповідь. Але моя програма повинна обробляти дані. Без цього варіанту дані просто не встигають дійти до моєї програми.
DerSkythe

Дякую. Точні симптоми і ідеальне виправлення.
TTimo

Ого! Це майже саме те, що мені потрібно. Єдине, що я хотів би додати, - це надіслати 200 відповідей до джерела webhook трохи раніше, ніж воно закриє з'єднання. В іншому випадку вони, як правило, вимикають веб-камери і не надсилають їх знову ... Чи можна це зробити для вибраних URL-адрес?
пілат

1
Це не вирішує проблему, коли ваш клієнт не отримує відповіді. Він усуває лише 499 помилок у ваших журналах і замінює їх кодом статусу 200. Погана ідея для цього. Справжнє рішення - сказати вашому клієнту збільшити їх час очікування ...
marcinx

7

Виявляється, 499-і дійсно означають "клієнт перервав зв’язок".

У мене був час очікування читання клієнта 60-х років (а також у nginx є proxy_read_timeout 60-х років). Тому в моєму випадку відбувається те, що nginx буде помилятися, upstream timed out (110: Connection timed out) while reading upstreamа потім nginx повторює "наступний проксі-сервер групи, яку ви налаштували." Це якщо у вас є більше одного.

Потім він намагається наступне і наступне, поки (за замовчуванням ) вони не вичерпали всіх. Як і кожен раз, він також видаляє їх із списку "живих" резервних серверів. Зрештою вичерпані, він повертає a504 gateway timeout.

Тож у моєму випадку nginx позначив сервер як "недоступний", повторно спробував його на наступному сервері, тоді відбувся 60sтайм-аут мого клієнта (негайно), тож я побачив upstream timed out (110: Connection timed out) while reading upstreamжурнал, одразу після нього - 499 журналу. Але це був просто збіг часу.

Пов'язані:

Якщо всі сервери в групі позначені як недоступні, він також повертає значення 502 Bad Gateway.протягом 10 секунд. Дивіться тут max_fails і fail_timeout. Запишіть журнали, це буде говоритиno live upstreams while connecting to upstream.

Якщо у вашій групі серверів є лише один проксі-сервер проксі-сервера, він просто спробує це один сервер, і повертає a 504 Gateway Time-outі не видаляє єдиний сервер зі списку "живих" серверів, якщо proxy_read_timeoutйого перевершено. Дивіться тут "Якщо в групі є лише один сервер, параметри max_fails, параметри fail_timeout та slow_start ігноруються, і такий сервер ніколи не вважатиметься недоступним."

Дійсно хитра частина полягає в тому, що якщо ви вказали proxy_pass для "localhost", і у вашому полі також одночасно є ipv6 та ipv4 "версії розташування" (більшість скриньок за замовчуванням), це вважатиметься так, ніби ви "список" декількох серверів у вашій групі серверів, а це означає, що ви можете потрапити в ситуацію вище, щоб повернути його "502 за 10 секунд", навіть якщо ви перераховуєте лише один сервер . Дивіться тут "Якщо доменне ім'я має декілька адрес, усі вони будуть використовуватися в круговій формі". Одне вирішення - оголосити його як proxy_pass http://127.0.0.1:5001;(його ipv4 адресу), щоб уникнути його як ipv6, так і ipv4. Тоді це вважається поведінкою "лише одного сервера".

Існує декілька різних налаштувань, які можна змінити, щоб зробити це "менше" проблеми. Як збільшити час або зробити його таким чином, щоб він не позначав сервери "відключеними", коли вони таймаут ... або виправлення списку, щоб він був розміром лише 1, див. Вище :)

Дивіться також: https://serverfault.com/a/783624/27813


3

Ця помилка досить легко відтворити, використовуючи стандартну конфігурацію nginx з php-fpm.

Якщо натиснути кнопку F5 на сторінці, ви створите десятки запитів на оновлення до сервера. Кожен попередній запит скасовується браузером при новому оновленні. У моєму випадку я знайшов десятки 499 у файлі журналу мого клієнта. З точки зору nginx: Якщо відповідь не була доставлена ​​клієнтові до наступного запиту на оновлення, nginx записує помилку 499.

mydomain.com.log:84.240.77.112 - - [19/Jun/2018:09:07:32 +0200] "GET /(path) HTTP/2.0" 499 0 "-" (user-agent-string)
mydomain.com.log:84.240.77.112 - - [19/Jun/2018:09:07:33 +0200] "GET /(path) HTTP/2.0" 499 0 "-" (user-agent-string)
mydomain.com.log:84.240.77.112 - - [19/Jun/2018:09:07:33 +0200] "GET /(path) HTTP/2.0" 499 0 "-" (user-agent-string)
mydomain.com.log:84.240.77.112 - - [19/Jun/2018:09:07:33 +0200] "GET /(path) HTTP/2.0" 499 0 "-" (user-agent-string)
mydomain.com.log:84.240.77.112 - - [19/Jun/2018:09:07:33 +0200] "GET /(path) HTTP/2.0" 499 0 "-" (user-agent-string)
mydomain.com.log:84.240.77.112 - - [19/Jun/2018:09:07:34 +0200] "GET /(path) HTTP/2.0" 499 0 "-" (user-agent-string)
mydomain.com.log:84.240.77.112 - - [19/Jun/2018:09:07:34 +0200] "GET /(path) HTTP/2.0" 499 0 "-" (user-agent-string)
mydomain.com.log:84.240.77.112 - - [19/Jun/2018:09:07:34 +0200] "GET /(path) HTTP/2.0" 499 0 "-" (user-agent-string)
mydomain.com.log:84.240.77.112 - - [19/Jun/2018:09:07:34 +0200] "GET /(path) HTTP/2.0" 499 0 "-" (user-agent-string)
mydomain.com.log:84.240.77.112 - - [19/Jun/2018:09:07:35 +0200] "GET /(path) HTTP/2.0" 499 0 "-" (user-agent-string)
mydomain.com.log:84.240.77.112 - - [19/Jun/2018:09:07:35 +0200] "GET /(path) HTTP/2.0" 499 0 "-" (user-agent-string)

Якщо обробка php-fpm займає більше часу (як важка сторінка WP), звичайно, це може спричинити проблеми. Наприклад, я чув про збої php-fpm, але вважаю, що їм можна запобігти правильному налаштуванню служб, як обробка дзвінків на xmlrpc.php.


2

... прийшов сюди з пошуку Google

Відповідь я знайшов деінде тут -> https://stackoverflow.com/a/15621223/1093174

який повинен був підняти час очікування з'єднання мого еластичного балансира навантаження AWS!

(У мене було налаштування сайту Django з реверсійним проксі-сервером nginx / apache, і справді дійсно дуже зручна робота / перегляд роботи журналу закінчувалася)


0

Як тільки я отримав 499 "Запит заборонено антивірусом" як відповідь AJAX http (хибний позитив Kaspersky Internet Security з легким евристичним аналізом, глибокий евристичний аналіз правильно знав, що немає нічого поганого).


0

Я зіткнувся з цією проблемою, і причина була пов’язана з плагіном Kaspersky Protection у браузері. Якщо ви зіткнулися з цим, спробуйте вимкнути свої плагіни та перевірте, чи це вирішує вашу проблему.


0

Однією з причин такої поведінки може бути ви використовуєте httpдля uwsgiзамість socket. Використовуйте команду нижче, якщо ви використовуєте uwsgiбезпосередньо.

uwsgi --socket :8080 --module app-name.wsgi

Ця ж команда у файлі .ini є

chdir = /path/to/app/folder
socket = :8080
module = app-name.wsgi

0

Це не відповідає на питання ОП, але оскільки я опинився тут, люто шукаючи відповідь, я хотів поділитися тим, що ми виявили.

У нашому випадку, виявляється, цих 499 років очікують. Наприклад, коли користувачі використовують функцію випередження типу в деяких вікнах пошуку, наприклад, у журналах ми бачимо щось подібне.

GET /api/search?q=h [Status 499] 
GET /api/search?q=he [Status 499]
GET /api/search?q=hel [Status 499]
GET /api/search?q=hell [Status 499]
GET /api/search?q=hello [Status 200]

Тож у нашому випадку я думаю, що це безпечно у використанні, proxy_ignore_client_abort onщо було запропоновано у попередній відповіді. Дякую за це!



0

У моєму випадку я маю налаштування

AWS ELB >> ECS(nginx) >> ECS(php-fpm).

Я налаштував неправильну групу безпеки AWS для служби ECS (php-fpm), тому Nginx не зміг дістатися до контейнера завдань php-fpm. Ось чому я отримував помилки в журналі завдань nginx

499 0 - elb-healthchecker/2.0

Перевірка стану здоров'я налаштована так, щоб перевірити сервіс php-fpm та підтвердити, що вона працює, і дати відповідь.


0

Я знаю, що це стара тема, але вона точно відповідає тому, що зі мною нещодавно трапилося, і я подумав, що тут це задокументуватимуть. Установка (у Докера) така:

  • nginx_proxy
  • nginx
  • php_fpm запускає власне додаток.

Симптом був "час очікування шлюзу 502" у запиті на вхід у програму. Експертиза знайдених журналів:

  • кнопка працює через HTTP, POSTщоб /login... і так ...
  • nginx-proxy отримав /loginзапит, і врешті повідомив про час очікування.
  • nginx повернув 499відповідь, що, звичайно, означає "господар помер".
  • /loginзапит не з'являвся на всіх (!) в журналах МПФ сервера!
  • в FPM не було жодних відстежень чи повідомлень про помилки ... nada, zero, zippo, none.

Виявилося, що проблема полягала в тому, що не вдалося підключитися до бази даних для перевірки входу. Але як зрозуміти це виявилося чистими здогадами.

Повна відсутність журналів простеження додатків ... або навіть запис про те, що FPM отримав запит ... була для мене цілковитою (і, руйнівною ...) несподіванкою. Так, програма повинна реєструвати збої, але в цьому випадку схоже, що процес працівника FPM загинув з помилкою виконання, що призводить до 499відповіді від nginx. Тепер це очевидно є проблемою в нашому додатку ... десь. Але я хотів записати деталі того, що сталося на користь наступних людей, які стикаються з чимось подібним.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.