Kemungkinan penyebab kode kesalahan NGINX 499

116

Saya mendapatkan banyak kode kesalahan 499 NGINX. Saya melihat bahwa ini adalah masalah sisi klien. Ini bukan masalah dengan NGINX atau tumpukan uWSGI saya. Saya mencatat korelasi dalam log uWSGI saat mendapatkan 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

Saya mencari penjelasan yang lebih mendalam dan berharap tidak ada yang salah dengan konfigurasi NGINX saya untuk uwsgi. Saya menerimanya begitu saja. Sepertinya masalah klien.

Tampa
sumber
Apakah Anda pernah menemukan solusi untuk ini? Saya melihat masalah yang sama persis dengan uWSGI dan nginx.
Raj
1
Saya mendapatkannya ketika saya membatalkan permintaan ajax jQuery.
mpen
1
Saya tahu ini adalah pertanyaan yang sangat lama tetapi jumlah pertanyaan yang salah tempat pada SO sangat mengejutkan. Ini jelas milik SF.
Sosukodo

Jawaban:

164

HTTP 499 di Nginx berarti klien menutup koneksi sebelum server menjawab permintaan. Dalam pengalaman saya biasanya disebabkan oleh waktu tunggu sisi klien . Seperti yang saya tahu itu adalah kode kesalahan khusus Nginx.

mrbo
sumber
1
Sebagai kasus khusus, saya perhatikan itu kadang-kadang terjadi ketika pengguna akhir mengklik dua kali tombol pengiriman formulir. Formulir dikirim dua kali, tetapi hanya satu tanggapan yang diharapkan oleh klien. Ini dapat diatasi dengan menonaktifkan (setidaknya untuk beberapa detik) tombol di JS saat pertama kali diklik.
Antoine Pinsard
14
Penting untuk diperhatikan bahwa "klien" mungkin sebenarnya adalah proxy. Misalnya, jika Anda menggunakan penyeimbang beban, ini mungkin membatalkan permintaan ke server nginx karena waktu tunggu.
Brad Koch
Ini terjadi di APP Angular saya jika pengguna menutup tab dan permintaan API saya tidak diselesaikan.
Vivek Saurabh
Penting untuk dicatat bahwa ini juga bisa disebabkan oleh server ; jika server terlalu lama untuk merespons, klien menyerah.
ijoseph
78

Dalam kasus saya, saya tidak sabar dan akhirnya salah menafsirkan log.

Faktanya, masalah sebenarnya adalah komunikasi antara nginx dan uwsgi, dan bukan antara browser dan nginx. Jika saya telah memuat situs di browser saya dan telah menunggu cukup lama, saya akan mendapatkan "504 - Bad Gateway". Tapi butuh waktu lama, saya terus mencoba berbagai hal, dan kemudian menyegarkan di browser. Jadi saya tidak pernah menunggu cukup lama untuk melihat error 504. Saat menyegarkan di browser, saat itulah permintaan sebelumnya ditutup, dan Nginx menulisnya di log sebagai 499.

Elaborasi

Di sini saya akan berasumsi bahwa pembaca tahu sedikit seperti yang saya lakukan ketika saya mulai bermain-main.

Setup saya adalah reverse proxy, server nginx, dan server aplikasi, server uWSGI di belakangnya. Semua permintaan dari klien akan masuk ke server nginx, kemudian diteruskan ke server uWSGI, dan kemudian tanggapan dikirim kembali dengan cara yang sama. Saya pikir ini adalah cara setiap orang menggunakan nginx / uwsgi dan seharusnya menggunakannya.

Nginx saya berfungsi sebagaimana mestinya, tetapi ada yang salah dengan server uwsgi. Ada dua cara (mungkin lebih) di mana server uwsgi dapat gagal merespons ke server nginx.

1) uWSGI berkata, "Saya sedang memproses, tunggu saja dan Anda akan segera mendapatkan tanggapan". nginx memiliki jangka waktu tertentu, yaitu mau menunggu, fx 20 detik. Setelah itu, ini akan merespons klien, dengan kesalahan 504.

2) uWSGI mati, atau uWSGi mati saat nginx menunggunya. nginx langsung melihatnya dan dalam hal ini, ia mengembalikan kesalahan 499.

Saya menguji penyiapan saya dengan membuat permintaan di klien (browser). Di browser tidak ada yang terjadi, itu terus menggantung. Setelah mungkin 10 detik (kurang dari batas waktu) saya menyimpulkan bahwa ada sesuatu yang tidak benar (yang benar), dan menutup server uWSGI dari baris perintah. Kemudian saya akan pergi ke pengaturan uWSGI, mencoba sesuatu yang baru, dan kemudian restart server uWSGI. Saat saya menutup server uWSGI, server nginx akan mengembalikan kesalahan 499.

Jadi saya terus debugging dengan 499 erroe, yang berarti googling untuk error 499. Tetapi jika saya menunggu cukup lama, saya akan mendapatkan error 504. Jika saya mendapatkan kesalahan 504, saya akan dapat memahami masalah dengan lebih baik, dan kemudian dapat melakukan debug.

Jadi kesimpulannya adalah, bahwa masalahnya adalah uWGSI yang terus menggantung ("Tunggu sebentar lagi, sebentar lagi, saya akan punya jawaban untuk Anda ...").

Bagaimana saya tetap bahwa masalah, saya tidak ingat. Saya rasa itu bisa disebabkan oleh banyak hal.

Mads Skjern
sumber
1
Bagaimana Anda akhirnya menyelesaikan ini? Saya mengalami masalah yang sama dan belum dapat mengetahui penyebabnya.
Colin Nichols
1
Saya menambahkan elaborasi, sayangnya, saya tidak berpikir itu akan menyelesaikan masalah Anda.
Mads Skjern
1
Hanya ingin mengucapkan terima kasih! Saya memiliki situasi yang persis sama dan ini menempatkan saya di jalur yang benar.
Aaron
3
@ Shafiul: Penjelasan saya tidak menjelaskan apa yang menyebabkan masalah dengan uWSGI, ini hanya menjelaskan bahwa uWSGI adalah penyebabnya (dan bukan nginx). Penjelasannya menjelaskan gejala dan bagaimana saya salah menafsirkannya. Saya memahami kekecewaan Anda, tetapi Anda telah salah memahami inti dari jawaban saya. Hormat kami.
Mads Skjern
2
Jawaban yang sangat berguna, jangan pernah hapus! Konsep ini harus disempurnakan dalam dokumentasi di suatu tempat, Anda melakukan layanan hebat dengan menjelaskan bagaimana perilakunya berbeda dari yang disiratkan oleh dokumen!
jerclarke
21

Klien menutup koneksi bukan berarti itu masalah browser !? Tidak semuanya!

Anda dapat menemukan 499 kesalahan dalam file log jika Anda memiliki LB (penyeimbang beban) di depan server web Anda (nginx) baik AWS atau haproxy (khusus). Yang mengatakan LB akan bertindak sebagai klien untuk nginx.

Jika Anda menjalankan nilai default haproxy untuk:

    timeout client  60000
    timeout server  60000

Itu berarti LB akan habis setelah 60000ms jika tidak ada respon dari nginx. Waktu tunggu mungkin terjadi untuk situs web atau skrip sibuk yang membutuhkan lebih banyak waktu untuk eksekusi. Anda harus menemukan waktu tunggu yang sesuai untuk Anda. Misalnya memperluasnya ke:

    timeout client  180s
    timeout server  180s

Dan Anda mungkin sudah siap.

Bergantung pada pengaturan Anda, Anda mungkin melihat kesalahan batas waktu gateway 504 di browser Anda yang menunjukkan bahwa ada yang salah dengan php-fpm tetapi tidak demikian halnya dengan kesalahan 499 di file log Anda.

mrki
sumber
12

Saat Anda mengarahkan 499aborsi koneksi yang dicatat oleh nginx. Tetapi biasanya ini dihasilkan ketika server backend Anda terlalu lambat , dan waktu tunggu proxy lain lebih dulu atau perangkat lunak pengguna membatalkan koneksi. Jadi periksa apakah uWSGI menjawab dengan cepat atau tidak apakah ada beban pada server uWSGI / Database.

Dalam banyak kasus, ada beberapa proxy lain antara pengguna dan nginx. Beberapa dapat berada di infrastruktur Anda seperti mungkin CDN, Load Balacer, cache Varnish, dll. Lainnya dapat berada di sisi pengguna seperti proxy caching, dll.

Jika ada proxy di sisi Anda seperti LoadBalancer / CDN ... Anda harus mengatur batas waktu ke waktu tunggu terlebih dahulu di backend Anda dan selanjutnya proxy lainnya kepada pengguna.

Jika Anda memiliki:

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

Saya akan merekomendasikan Anda untuk mengatur:

  • n detik hingga batas waktu uWSGI
  • n+1 detik hingga batas waktu nginx
  • n+2 detik ke waktu tunggu untuk Load Balancer
  • n+3 detik batas waktu ke CDN.

Jika Anda tidak dapat menyetel beberapa waktu tunggu (seperti CDN), temukan apa itu batas waktunya dan sesuaikan yang lain sesuai dengan itu ( n, n-1...).

Ini memberikan rangkaian waktu tunggu yang benar. dan Anda benar-benar akan menemukan siapa yang memberikan waktu tunggu dan mengembalikan kode respons yang benar kepada pengguna.

bartomeu
sumber
8

Dalam kasus saya, saya mendapat 499 ketika API klien menutup koneksi sebelum mendapat respons apa pun. Secara harfiah mengirim POST dan segera menutup koneksi. Ini diselesaikan dengan opsi:

proxy_ignore_client_abort aktif

Dok Nginx

DerSkythe
sumber
3
Saya tidak mengerti bagaimana ini membantu
Vladimir Starkov
Mungkin itu bukan kasusmu? Klien mengirimkan data dan tidak tertarik dengan apa yang akan terjadi pada mereka dan apa jawabannya. Tetapi aplikasi saya harus memproses datanya. Tanpa opsi ini, data tidak punya waktu untuk mencapai aplikasi saya.
DerSkythe
Terima kasih. Gejala yang tepat dan perbaikan sempurna.
TTimo
Wah! Itu hampir persis apa yang saya butuhkan. Satu-satunya hal yang saya tambahkan - akan mengirim 200 tanggapan ke sumber webhook sedikit sebelum menutup koneksi itu sendiri. Jika tidak, mereka cenderung menonaktifkan webhook dan tidak mengirimnya lagi… Dapatkah saya melakukannya untuk URL yang dipilih?
pilat
1
Ini tidak menyelesaikan masalah klien Anda tidak mendapatkan tanggapan. Ini hanya menghilangkan 499 kesalahan dalam log Anda dan menggantinya dengan kode status 200. Ide buruk untuk melakukan ini. Solusi sebenarnya adalah memberi tahu klien Anda untuk meningkatkan pengaturan batas waktu mereka ...
marcinx
7

Ternyata 499 benar-benar berarti "koneksi terputus klien."

Saya memiliki klien membaca batas waktu 60-an (dan nginx juga memiliki proxy_read_timeout default 60-an). Jadi yang terjadi dalam kasus saya adalah bahwa nginx akan error.log upstream timed out (110: Connection timed out) while reading upstreamdan kemudian nginx mencoba lagi "server proxy berikutnya di grup server backend yang Anda konfigurasikan." Itu jika Anda memiliki lebih dari satu.

Kemudian mencoba yang berikutnya dan berikutnya hingga (secara default ) itu telah menghabiskan semuanya. Karena masing-masing waktu habis, tindakan ini juga menghapusnya dari daftar server backend "langsung". Setelah semua habis, ia mengembalikan a504 gateway timeout.

Jadi dalam kasus saya, nginx menandai server sebagai "tidak tersedia", mencobanya kembali di server berikutnya, lalu 60sbatas waktu klien saya (segera) terjadi, jadi saya akan melihat upstream timed out (110: Connection timed out) while reading upstreamlog, segera diikuti dengan log 499. Tapi itu hanya kebetulan waktu.

Terkait:

Jika semua server dalam grup ditandai sebagai tidak tersedia saat ini, maka server akan mengembalikan a 502 Bad Gateway.selama 10 detik juga. Lihat di sini max_fails dan fail_timeout. Masukkan log itu akan mengatakanno live upstreams while connecting to upstream.

Jika Anda hanya memiliki satu proksi backend di grup server Anda, itu hanya mencoba satu server, dan mengembalikan 504 Gateway Time-outdan tidak menghapus satu server dari daftar server "langsung", jika proxy_read_timeoutdilampaui. Lihat di sini "Jika hanya ada satu server dalam grup, parameter max_fails, fail_timeout dan slow_start diabaikan, dan server semacam itu tidak akan pernah dianggap tidak tersedia."

Bagian yang benar-benar rumit adalah jika Anda menentukan proxy_pass ke "localhost" dan kotak Anda kebetulan juga memiliki "versi lokasi" ipv6 dan ipv4 pada saat yang sama (kebanyakan kotak melakukannya secara default), itu akan dihitung seolah-olah Anda memiliki sebuah "daftar" dari beberapa server dalam grup server Anda, yang berarti Anda dapat masuk ke situasi di atas dengan mengembalikannya "502 untuk 10s" meskipun Anda hanya mencantumkan satu server . Lihat di sini "Jika nama domain ditetapkan ke beberapa alamat, semuanya akan digunakan dengan cara round-robin." Salah satu solusinya adalah mendeklarasikannya sebagai proxy_pass http://127.0.0.1:5001;(alamat ipv4-nya) untuk menghindarinya menjadi ipv6 dan ipv4. Kemudian ini dihitung sebagai perilaku "hanya satu server".

Ada beberapa pengaturan berbeda yang dapat Anda atur untuk membuat masalah ini "berkurang". Seperti menambah waktu tunggu atau membuatnya tidak menandai server sebagai "nonaktif" saat waktu habis ... atau memperbaiki daftar sehingga hanya berukuran 1, lihat di atas :)

Lihat juga: https://serverfault.com/a/783624/27813

rogerdpack
sumber
3

Kesalahan ini cukup mudah untuk direproduksi menggunakan konfigurasi nginx standar dengan php-fpm.

Menekan tombol F5 pada halaman akan membuat lusinan permintaan penyegaran ke server. Setiap permintaan sebelumnya dibatalkan oleh browser saat penyegaran baru. Dalam kasus saya, saya menemukan lusinan 499 di file log toko online klien saya. Dari sudut pandang nginx: Jika respons belum dikirim ke klien sebelum permintaan penyegaran berikutnya, nginx mencatat kesalahan 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)

Jika pemrosesan php-fpm membutuhkan waktu lebih lama (seperti halaman WP yang berat), tentu saja ini dapat menimbulkan masalah. Saya pernah mendengar tentang php-fpm crash, misalnya, tapi saya yakin mereka dapat dicegah mengkonfigurasi layanan dengan benar seperti menangani panggilan ke xmlrpc.php.

karvonen
sumber
2

... datang ke sini dari pencarian google

Saya menemukan jawabannya di tempat lain di sini -> https://stackoverflow.com/a/15621223/1093174

yang akan meningkatkan waktu tunggu koneksi menganggur penyeimbang beban elastis AWS saya!

(Saya telah menyiapkan situs Django dengan proksi terbalik nginx / apache, dan pekerjaan / tampilan backend yang benar-benar benar-benar masuk adalah waktu habis)

David Lam
sumber
0

Setelah saya mendapat 499 "Permintaan telah dilarang oleh antivirus" sebagai respons http AJAX (positif palsu oleh Kaspersky Internet Security dengan analisis heuristik ringan, analisis heuristik mendalam tahu benar tidak ada yang salah).

TeeJay
sumber
0

Saya mengalami masalah ini dan penyebabnya adalah karena plugin Perlindungan Kaspersky di browser. Jika Anda mengalami ini, coba nonaktifkan plugin Anda dan lihat apakah itu memperbaiki masalah Anda.

EGN
sumber
0

Salah satu alasan untuk perilaku ini mungkin karena Anda menggunakan httpuntuk, uwsgibukan socket. Gunakan perintah di bawah ini jika Anda menggunakan uwsgisecara langsung.

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

Perintah yang sama di file .ini adalah

chdir = /path/to/app/folder
socket = :8080
module = app-name.wsgi
Penkey Suresh
sumber
0

Ini tidak menjawab pertanyaan OP, tapi karena saya berakhir di sini setelah mati-matian mencari jawaban, saya ingin membagikan apa yang kami temukan.

Dalam kasus kami, ternyata 499 ini diharapkan. Saat pengguna menggunakan fitur ketik di depan di beberapa kotak pencarian, misalnya, kami melihat sesuatu seperti ini di log.

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]

Jadi dalam kasus kami, saya pikir ini aman untuk digunakan proxy_ignore_client_abort onyang disarankan dalam jawaban sebelumnya. Terima kasih untuk itu!

Ron DeFulio
sumber
0

Untuk bagian saya, saya telah mengaktifkan ufwtetapi saya lupa untuk mengekspos port upstream saya ._.

Alexandre Daubricourt
sumber
0

Dalam kasus saya, saya memiliki pengaturan seperti

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

Saya telah mengonfigurasi grup keamanan AWS yang salah untuk layanan ECS (php-fpm), jadi Nginx tidak dapat menjangkau penampung tugas php-fpm. Itu sebabnya saya mendapatkan kesalahan di log tugas nginx

499 0 - elb-healthchecker/2.0

Pemeriksaan kesehatan dikonfigurasikan untuk memeriksa layanan php-fpm dan mengonfirmasikannya dan memberikan tanggapan.

Piyush Sonigra
sumber
0

Saya tahu ini utas lama, tetapi sama persis dengan apa yang baru-baru ini terjadi pada saya dan saya pikir saya akan mendokumentasikannya di sini. Setup (di Docker) adalah sebagai berikut:

  • nginx_proxy
  • nginx
  • php_fpm menjalankan aplikasi sebenarnya.

Gejalanya adalah "502 Gateway Timeout" pada prompt login aplikasi. Pemeriksaan log ditemukan:

  • tombol ini bekerja melalui HTTP POSTke /login... dan ...
  • nginx-proxy mendapatkan /loginpermintaan tersebut, dan akhirnya melaporkan waktu tunggu.
  • nginx membalas 499, yang tentu saja berarti "tuan rumah mati".
  • yang /loginpermintaan tidak muncul sama sekali (!) di log FPM server!
  • tidak ada jejak balik atau pesan kesalahan di FPM ... nada, nol, zippo, tidak ada.

Ternyata masalahnya adalah kegagalan untuk terhubung ke database untuk memverifikasi login. Tapi bagaimana mengetahuinya ternyata hanya tebakan belaka.

Tidak adanya log pelacakan balik aplikasi ... atau bahkan catatan bahwa permintaan telah diterima oleh FPM ... adalah kejutan yang lengkap (dan, menghancurkan ...) bagi saya. Ya, aplikasi seharusnya mencatat kegagalan, tetapi dalam kasus ini sepertinya proses pekerja FPM mati dengan error runtime, yang mengarah ke 499respons dari nginx. Sekarang, ini jelas merupakan masalah dalam aplikasi kita ... di suatu tempat. Tetapi saya ingin mencatat hal-hal khusus tentang apa yang terjadi untuk kepentingan orang-orang berikutnya yang menghadapi hal seperti ini.

Mike Robinson
sumber