NGINX 499 hata kodlarının olası nedeni


117

Çok sayıda 499 NGINX hata kodu alıyorum. Bunun müşteri tarafı sorunu olduğunu görüyorum. NGINX veya benim uWSGI yığınımla ilgili bir sorun değil. Bir 499 aldığında uWSGI günlüklerindeki korelasyonu not ediyorum.

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

Daha derinlemesine bir açıklama arıyorum ve uwsgi için NGINX yapılandırmamda yanlış bir şey olmadığını umuyorum. Görünüşe göre alıyorum. Bir müşteri sorunu gibi görünüyor.


buna hiç bir çözüm bulabildin mi? Hem uWSGI hem de nginx ile aynı sorunu görüyorum.
Raj

1
Bir jQuery ajax isteğini iptal ettiğimde bunu anlıyorum.
mpen

1
Bunun çok eski bir soru olduğunu biliyorum, ancak SO ile ilgili yanlış yerleştirilen soruların miktarı şaşırtıcı. Bu açıkça SF'ye ait.
Sosukodo

Yanıtlar:


165

Nginx'teki HTTP 499, istemcinin , sunucu isteği yanıtlamadan önce bağlantıyı kapattığı anlamına gelir . Benim deneyimime göre genellikle istemci tarafı zaman aşımından kaynaklanıyor . Bildiğim gibi, Nginx'e özgü bir hata kodu.


1
Özel bir durum olarak, bazen son kullanıcı bir form gönderme düğmesini çift tıkladığında bunun gerçekleştiğini fark ettim. Form iki kez gönderilir, ancak müşteri tarafından yalnızca bir yanıt beklenir. Bu, JS'deki düğmeler ilk tıklandıklarında devre dışı bırakılarak (en azından birkaç saniye için) çözülebilir.
Antoine Pinsard

14
"İstemci" nin aslında bir proxy olabileceğini unutmamak önemlidir. Örneğin, bir yük dengeleyici kullanıyorsanız, zaman aşımı nedeniyle nginx sunucusuna yapılan isteği iptal edebilir.
Brad Koch

Kullanıcı sekmeyi kapatırsa ve API isteklerim tamamlanmazsa bu, Angular uygulamamda gerçekleşir.
Vivek Saurabh

Bunun sunucudan da kaynaklanabileceğini unutmamak gerekir ; sunucunun yanıt vermesi çok uzun sürerse, istemci pes eder.
ijoseph

78

Benim durumumda sabırsızdım ve kütüğü yanlış yorumladım.

Aslında asıl sorun nginx ve uwsgi arasındaki iletişimdi ve tarayıcı ile nginx arasındaki iletişim değildi. Siteyi tarayıcıma yükleseydim ve yeterince bekleseydim "504 - Bozuk Ağ Geçidi" almış olurdum. Ama o kadar uzun sürdü ki bir şeyler denemeye devam ettim ve ardından tarayıcıyı yeniledim. Bu yüzden 504 hatasını görecek kadar uzun süre beklemedim. Tarayıcıda yenilenirken, yani önceki istek kapatıldığında ve Nginx bunu günlüğe 499 olarak yazar.

ayrıntı

Burada okuyucunun ben etrafta oynamaya başladığım zamanki kadar az şey bildiğini varsayacağım.

Kurulumum bir ters proxy, nginx sunucusu ve bir uygulama sunucusu, arkasındaki uWSGI sunucusuydu. İstemciden gelen tüm istekler nginx sunucusuna gider, ardından uWSGI sunucusuna iletilir ve ardından yanıt aynı şekilde geri gönderilir. Bence bu, herkesin nginx / uwsgi'yi nasıl kullandığının ve onu kullanması gerektiğini düşünüyorum.

Nginx'im olması gerektiği gibi çalıştı, ancak uwsgi sunucusunda bir sorun vardı. Uwsgi sunucusunun nginx sunucusuna yanıt verememesinin iki yolu (belki daha fazlası) vardır.

1) uWSGI, "İşlem yapıyorum, sadece bekleyin ve yakında bir yanıt alacaksınız" der. nginx'in beklemeye istekli olduğu belli bir süresi vardır, fx 20 saniye. Bundan sonra müşteriye 504 hatasıyla cevap verecektir.

2) uWSGI öldü veya nginx onu beklerken uWSGi öldü. nginx bunu hemen görür ve bu durumda 499 hatası verir.

İstemcide (tarayıcıda) isteklerde bulunarak kurulumumu test ediyordum. Tarayıcıda hiçbir şey olmadı, sadece asılı kaldı. Belki 10 saniye sonra (zaman aşımından daha az) bir şeyin doğru olmadığı sonucuna vardım (bu doğru) ve uWSGI sunucusunu komut satırından kapattım. Sonra uWSGI ayarlarına gider, yeni bir şey dener ve ardından uWSGI sunucusunu yeniden başlatırdım. UWSGI sunucusunu kapattığım an, nginx sunucusu bir 499 hatası döndürecekti.

Bu yüzden 499 erroe ile hata ayıklamaya devam ettim, bu da 499 hatası için googling anlamına geliyor. Ama yeterince bekleseydim, 504 hatasını alırdım. 504 hatasını almış olsaydım, sorunu daha iyi anlayabilir ve ardından hata ayıklayabilirdim.

Yani sonuç şu ki, sorun asılı duran uWGSI ile ilgili ("Biraz daha bekleyin, biraz daha uzun, o zaman sizin için bir cevabım olacak ...").

Bu sorunu nasıl çözdüğümü hatırlamıyorum. Sanırım birçok şeyden kaynaklanıyor olabilir.


1
Bunu nasıl çözdün? Ben de aynı sorunu yaşıyorum ve nedenini tespit edemedim.
Colin Nichols

1
Bir detay ekledim, maalesef probleminizi çözeceğini düşünmüyorum.
Mads Skjern

1
Sadece size teşekkür etmek istedim! Ben de tamamen aynı durumdaydım ve bu beni doğru yola soktu.
Aaron

3
@Shafiul: Benim detaylandırmam, uWSGI ile ilgili soruna neyin neden olduğunu açıklamıyor, basitçe uWSGI'nin neden olduğunu (nginx değil) açıklıyor. Detaylandırma semptomları ve bunları nasıl yanlış yorumladığımı açıklıyor. Hayal kırıklığınızı anlıyorum, ama cevabımın özünü yanlış anladınız. İçtenlikle.
Mads Skjern

2
Son derece faydalı cevap, asla silme! Bu kavramlar, belgelerde bir yerde detaylandırılmalıdır, nasıl davrandığını, belgelerin ima ettiğinden farklı olarak detaylandırarak harika bir hizmet yaparsınız!
jerclarke

21

İstemci bağlantıyı kapattı, bunun bir tarayıcı sorunu olduğu anlamına gelmez !? Bir şey değil!

AWS veya haproxy (özel) web sunucunuzun (nginx) önünde bir LB (yük dengeleyici) varsa bir günlük dosyasında 499 hata bulabilirsiniz. Bu, LB'nin nginx'e bir müşteri olarak hareket edeceğini söyledi.

Haproxy varsayılan değerlerini çalıştırırsanız:

    timeout client  60000
    timeout server  60000

Bu, nginx'ten yanıt gelmezse LB'nin 60000 ms'den sonra zaman aşımına uğrayacağı anlamına gelir. Yürütme için daha fazla zamana ihtiyaç duyan meşgul web siteleri veya komut dosyaları için zaman aşımları olabilir. Sizin için çalışacak zaman aşımını bulmanız gerekecek. Örneğin, şuna genişletin:

    timeout client  180s
    timeout server  180s

Ve muhtemelen hazır olacaksın.

Kurulumunuza bağlı olarak, tarayıcınızda php-fpm ile ilgili bir sorun olduğunu, ancak günlük dosyalarınızdaki 499 hatayla durum böyle olmayacağını belirten bir 504 ağ geçidi zaman aşımı hatası görebilirsiniz.


12

499Nginx tarafından kaydedilen bir bağlantı iptalini işaret ederken. Ancak bu genellikle arka uç sunucunuz çok yavaş olduğunda üretilir olduğunda ve önce başka bir proxy zaman aşımına veya kullanıcı yazılımı bağlantıyı kestiğinde . Bu nedenle, uWSGI'nin hızlı yanıt verip vermediğini veya uWSGI / Veritabanı sunucusunda herhangi bir yük olup olmadığını kontrol edin.

Çoğu durumda, kullanıcı ile nginx arasında başka proxy'ler vardır. Bazıları altyapınızda CDN, Load Balacer, Varnish cache vb. Olabilir. Diğerleri bir caching proxy'si gibi kullanıcı tarafında olabilir.

Yanınızda LoadBalancer / CDN gibi proxy'ler varsa ... zaman aşımlarını önce arka ucunuzda ve aşamalı olarak kullanıcıya diğer proxy'lerde zaman aşımına uğratacak şekilde ayarlamalısınız.

Eğer varsa:

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

Şunları ayarlamanızı tavsiye edeceğim:

  • n uWSGI zaman aşımına saniye
  • n+1 nginx zaman aşımına saniye
  • n+2 Yük Dengeleyiciye zaman aşımına geçecek saniye
  • n+3 CDN için saniye zaman aşımı.

Bazı zaman aşımlarını (CDN gibi) ayarlayamazsanız, zaman aşımının ne olduğunu bulun ve diğerlerini buna göre ayarlayın ( n, n-1...).

Bu, doğru bir zaman aşımı zinciri sağlar. ve gerçekten kimin zaman aşımına uğradığını ve kullanıcıya doğru yanıt kodunu verdiğini göreceksiniz.


8

Benim durumumda, istemcinin API'si herhangi bir yanıt almadan önce bağlantıyı kapattığında 499 aldım. Kelimenin tam anlamıyla bir POST gönderdi ve bağlantıyı hemen kapatın. Bu, seçenekle çözülür:

proxy_ignore_client_abort on

Nginx belgesi


3
Bunun nasıl yardımcı olduğunu anlamıyorum
Vladimir Starkov

Belki senin davan değil? Müşteri verileri gönderir ve onlara ne olacağı ve cevabın ne olacağı ile ilgilenmez. Ancak başvurum verileri işlemeli. Bu seçenek olmadan, verilerin başvuruma ulaşması için zaman kalmaz.
DerSkythe

Teşekkür ederim. Kesin semptomlar ve mükemmel düzeltme.
TTimo

Oha! Budur neredeyse tam olarak ne ihtiyacım. Ekleyeceğim tek şey , bağlantının kendisini kapatmadan biraz önce webhook kaynağına 200 yanıtı göndermek olacaktır . Aksi takdirde, web kancalarını devre dışı bırakma eğilimindedirler ve 'onları tekrar göndermezler ... Bunu seçilen URL'ler için yapabilir miyim?
pilat

1
Bu, müşterinizin yanıt alamaması sorununu çözmez. Yalnızca günlüklerinizdeki 499 hatayı ortadan kaldırır ve bunları durum kodu 200 ile değiştirir. Bunu yapmak kötü bir fikir. Gerçek çözüm, müşterinize zaman aşımı ayarını artırmasını söylemektir ...
marcinx

7

Görünüşe göre 499'un gerçekten "müşteri bağlantısı kesildi" anlamına geliyor.

60 saniyelik bir istemci okuma zaman aşımına sahiptim (ve nginx ayrıca 60 saniyelik bir varsayılan proxy_read_timeout değerine sahip). Öyleyse benim durumumda olan şey nginx'in hata yapmasıdır. Log anupstream timed out (110: Connection timed out) while reading upstream ve sonra nginx'in "yapılandırdığınız arka uç sunucu grubundaki bir sonraki proxy sunucusunu" tekrar denemesi. Bu, birden fazla varsa.

Sonra sonraki ve sonrakine kadar çalışır ( varsayılan olarak ) hepsini tüketene kadar. Her biri zaman aşımına uğradığında, onları "canlı" arka uç sunucuları listesinden de kaldırır. Her şey bittikten sonra, bir504 gateway timeout.

Bu yüzden benim durumumda nginx sunucuyu "kullanılamıyor" olarak işaretledi, bir sonraki sunucuda yeniden denedi, sonra istemcimin 60szaman aşımı (hemen) gerçekleşti, bu yüzden bir upstream timed out (110: Connection timed out) while reading upstreamgünlük ve hemen ardından bir 499 günlüğü görüyorum . Ama sadece zamanlama tesadüfüydü.

İlişkili:

Gruptaki tüm sunucular şu anda kullanılamıyor olarak işaretlenmişse, 502 Bad Gateway.10s için de bir döndürür . Buraya bakın max_failsve fail_timeout. Söyleyeceği günlükleri içindeno live upstreams while connecting to upstream.

Sunucu grubunuzda yalnızca bir proxy arka ucunuz varsa, yalnızca tek sunucuyu dener ve a döndürür 504 Gateway Time-outve aşılırsa, tek sunucuyu "canlı" sunucular listesinden kaldırmaz proxy_read_timeout. Buraya bakın "Bir grupta yalnızca tek bir sunucu varsa, max_fails, fail_timeout ve slow_start parametreleri göz ardı edilir ve böyle bir sunucu asla kullanılamaz olarak değerlendirilmez."

İşin zor yanı, proxy_pass öğesini "localhost" olarak belirtirseniz ve kutunuzda aynı anda ipv6 ve ipv4 "konum sürümleri" varsa (çoğu kutu varsayılan olarak yapar), sanki sizde Sunucu grubunuzdaki birden çok sunucunun bir "listesi", yani yalnızca bir sunucu listeleseniz bile, "10 saniye için 502" döndürme durumuna girebileceğiniz anlamına gelir . Buraya bakın "Bir alan adı birkaç adrese çözümlenirse, bunların tümü sıralı bir şekilde kullanılacaktır." Bir geçici çözüm, hem ipv6 hem de ipv4 olmasını önlemek için onu proxy_pass http://127.0.0.1:5001;(ipv4 adresi) olarak bildirmektir . Daha sonra "tek bir sunucu" davranışı olarak sayılır.

Bu sorunu "daha az" hale getirmek için ince ayar yapabileceğiniz birkaç farklı ayar var. Zaman aşımlarını artırmak veya zaman aşımına uğradıklarında sunucuları "devre dışı" olarak işaretlememesi için yapmak gibi ... veya listeyi yalnızca boyut 1 olacak şekilde düzeltmek, yukarıya bakın :)

Ayrıca bkz .: https://serverfault.com/a/783624/27813


3

Bu hatayı php-fpm ile standart nginx yapılandırması kullanarak yeniden oluşturmak oldukça kolaydır.

Bir sayfada F5 düğmesini basılı tutmak, sunucuya düzinelerce yenileme isteği oluşturacaktır. Önceki her istek, yeni yenilemede tarayıcı tarafından iptal edilir. Benim durumumda, müşterimin çevrimiçi mağaza günlük dosyasında düzinelerce 499 buldum. Bir nginx açısından: Yanıt istemciye sonraki yenileme isteğinden önce teslim edilmediyse nginx, 499 hatasını günlüğe kaydeder.

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 işlemi daha uzun sürerse (yoğun bir WP sayfası gibi), elbette sorunlara neden olabilir. Örneğin php-fpm çökmelerini duydum, ancak xmlrpc.php'ye yapılan çağrıları işlemek gibi hizmetleri düzgün bir şekilde yapılandırmanın önlenebileceğine inanıyorum.


2

... buraya bir google aramasından geldi

Cevabı burada başka bir yerde buldum -> https://stackoverflow.com/a/15621223/1093174

bu da AWS elastik yük dengeleyicimin bağlantı boşta kalma zaman aşımını yükseltmekti!

(Nginx / apache ters proxy ile bir Django sitesi kurdum ve gerçekten gerçekten bir arka uç işi / görünümü zaman aşımına uğradı)


1

Bunun eski bir konu olduğunu biliyorum, ancak son zamanlarda başıma gelenlerle tam olarak eşleşiyor ve burada belgeleyeceğimi düşündüm. Kurulum (Docker'da) aşağıdaki gibidir:

  • nginx_proxy
  • nginx
  • php_fpm gerçek uygulamayı çalıştırıyor.

Belirti, uygulama oturum açma isteminde "502 Ağ Geçidi Zaman Aşımı" idi. Bulunan günlüklerin incelenmesi:

  • HTTP üzerinden düğmesinin çalışma POSTiçin /login... ve bu yüzden ...
  • nginx-proxy /loginisteği aldı ve sonunda bir zaman aşımı bildirdi.
  • nginx 499, elbette "ev sahibi öldü " anlamına gelen bir yanıt verdi .
  • /loginistek bütün (!) görünmedi FPM sunucusunun günlüklerinde!
  • FPM'de hiçbir izleme hatası veya hata mesajı yoktu ... nada, zero, zippo, none.

Sorunun, girişi doğrulamak için veritabanına bağlanamama hatası olduğu ortaya çıktı. Ama bunun nasıl anlaşılacağı saf bir tahmine dayalıydı.

Uygulama izleme kayıtlarının tamamen yokluğu ... veya hatta talebin FPM tarafından alındığına dair bir kayıt ... benim için tam (ve yıkıcı ...) bir sürprizdi. Evet, uygulamanın hataları günlüğe kaydetmesi gerekiyor, ancak bu durumda FPM çalışan işlemi bir çalışma zamanı hatasıyla ölmüş gibi görünüyor ve bu da nginx'ten 499yanıt almasına neden oluyor. Şimdi, bu açıkça bizim uygulamamızdaki bir problem ... bir yerlerde. Ama bunun gibi bir şeyle karşı karşıya kalan sonraki insanların yararına olanların ayrıntılarını kaydetmek istedim.


0

AJAX http yanıtı olarak 499 "İstek antivirüs tarafından yasaklandı" mesajı aldığımda (Kaspersky Internet Security tarafından hafif sezgisel analizle yanlış pozitif, derin sezgisel analiz doğru bir şekilde yanlış bir şey olmadığını biliyordu).


0

Bu sorunla karşılaştım ve nedeni tarayıcıdaki Kaspersky Protection eklentisiydi. Bununla karşılaşıyorsanız, eklentilerinizi devre dışı bırakmayı deneyin ve bunun sorununuzu çözüp çözmediğine bakın.


0

Bu davranışın nedenlerinden biri kullandığınız olabilir httpiçin uwsgiyerine socket. uwsgiDoğrudan kullanıyorsanız aşağıdaki komutu kullanın .

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

.İni dosyasındaki aynı komut

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

0

Bu, OP'lerin sorusuna cevap vermiyor, ancak öfkeyle bir cevap aradıktan sonra buraya geldiğim için keşfettiğimiz şeyi paylaşmak istedim.

Bizim durumumuzda bu 499'ların beklendiği ortaya çıktı. Örneğin, kullanıcılar bazı arama kutularında önceden yazma özelliğini kullandıklarında, günlüklerde buna benzer bir şey görürüz.

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]

Yani bizim durumumuzda proxy_ignore_client_abort on, önceki bir cevapta önerilen kullanımının güvenli olduğunu düşünüyorum . Bunun için teşekkürler!



0

Benim durumumda, şöyle bir kurulum var

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

ECS (php-fpm) hizmeti için yanlış AWS güvenlik grubunu yapılandırmıştım, bu nedenle Nginx php-fpm görev kapsayıcısına ulaşamadı. Bu yüzden nginx görev günlüğünde hatalar alıyordum

499 0 - elb-healthchecker/2.0

Durum denetimi, php-fpm hizmetini kontrol edecek, çalıştığını doğrulayacak ve bir yanıt verecek şekilde yapılandırıldı.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.