Lý do có thể cho mã lỗi NGINX 499


116

Tôi nhận được rất nhiều mã lỗi NGINX 499. Tôi thấy rằng đây là một vấn đề từ phía khách hàng. Đó không phải là vấn đề với NGINX hoặc ngăn xếp uWSGI của tôi. Tôi lưu ý mối tương quan trong nhật ký uWSGI khi nhận được 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

Tôi đang tìm kiếm lời giải thích chuyên sâu hơn và hy vọng rằng không có gì sai với cấu hình NGINX của tôi cho uwsgi. Tôi đang coi nó trên mệnh giá. Nó có vẻ như là một vấn đề của khách hàng.


Bạn đã bao giờ tìm thấy một giải pháp cho điều này? Tôi thấy cùng một vấn đề với cả uWSGI và nginx.
Raj

1
Tôi nhận được nó khi tôi hủy bỏ một yêu cầu ajax jQuery.
mpen

1
Tôi biết đây là một câu hỏi rất cũ nhưng số lượng câu hỏi đặt sai vị trí trên SO thật đáng kinh ngạc. Điều này rõ ràng thuộc về SF.
Sosukodo

Câu trả lời:


163

HTTP 499 trong Nginx có nghĩa là máy khách đã đóng kết nối trước khi máy chủ trả lời yêu cầu. Theo kinh nghiệm của tôi thường là do thời gian chờ phía khách hàng . Như tôi biết đó là mã lỗi cụ thể của Nginx.


1
Là một trường hợp đặc biệt, tôi nhận thấy nó đôi khi xảy ra khi người dùng cuối nhấp đúp vào nút gửi biểu mẫu. Biểu mẫu được gửi hai lần, nhưng khách hàng chỉ mong đợi một phản hồi. Điều này có thể được giải quyết bằng cách tắt (ít nhất trong vài giây) các nút trong JS lần đầu tiên chúng được nhấp.
Antoine Pinsard

14
Điều quan trọng cần lưu ý là "máy khách" thực sự có thể là một proxy. Ví dụ: nếu bạn đang sử dụng bộ cân bằng tải, nó có thể hủy yêu cầu đến máy chủ nginx do hết thời gian.
Brad Koch

Nó xảy ra trên Angular APP của tôi nếu người dùng đóng tab và các yêu cầu API của tôi không được hoàn thành.
Vivek Saurabh

Điều quan trọng cần lưu ý rằng điều này cũng có thể do máy chủ ; nếu máy chủ mất quá nhiều thời gian để phản hồi, máy khách sẽ bỏ cuộc.
ijoseph

78

Trong trường hợp của tôi, tôi đã thiếu kiên nhẫn và cuối cùng đã hiểu sai bản ghi.

Trên thực tế, vấn đề thực sự là giao tiếp giữa nginx và uwsgi, chứ không phải giữa trình duyệt và nginx. Nếu tôi đã tải trang web trong trình duyệt của mình và đợi đủ lâu, tôi sẽ nhận được "504 - Cổng xấu". Nhưng mất quá nhiều thời gian, tôi tiếp tục thử mọi thứ, và sau đó làm mới trong trình duyệt. Vì vậy, tôi không bao giờ đợi đủ lâu để thấy lỗi 504. Khi làm mới trong trình duyệt, đó là khi yêu cầu trước đó bị đóng và Nginx ghi điều đó vào nhật ký là 499.

Công phu

Ở đây tôi sẽ giả định rằng người đọc biết ít như tôi đã làm khi tôi bắt đầu chơi xung quanh.

Thiết lập của tôi là một proxy ngược, máy chủ nginx và máy chủ ứng dụng, máy chủ uWSGI đằng sau nó. Tất cả các yêu cầu từ máy khách sẽ chuyển đến máy chủ nginx, sau đó được chuyển tiếp đến máy chủ uWSGI và sau đó phản hồi được gửi lại theo cùng một cách. Tôi nghĩ đây là cách mọi người sử dụng nginx / uwsgi và phải sử dụng nó.

Nginx của tôi hoạt động như bình thường, nhưng đã xảy ra sự cố với máy chủ uwsgi. Có hai cách (có thể nhiều hơn) mà máy chủ uwsgi có thể không phản hồi với máy chủ nginx.

1) uWSGI nói, "Tôi đang xử lý, chỉ cần đợi và bạn sẽ sớm nhận được phản hồi". nginx có một khoảng thời gian nhất định, rằng nó sẵn sàng đợi, fx 20 giây. Sau đó, nó sẽ phản hồi lại máy khách, với lỗi 504.

2) uWSGI đã chết, hoặc uWSGi chết trong khi nginx đang đợi nó. nginx thấy điều đó ngay lập tức và trong trường hợp đó, nó trả về lỗi 499.

Tôi đang thử nghiệm thiết lập của mình bằng cách đưa ra các yêu cầu trong ứng dụng khách (trình duyệt). Trong trình duyệt không có gì xảy ra, nó cứ bị treo. Có thể sau 10 giây (ít hơn thời gian chờ), tôi kết luận rằng có điều gì đó không đúng (đó là sự thật) và đóng máy chủ uWSGI từ dòng lệnh. Sau đó, tôi sẽ đi đến cài đặt uWSGI, thử một cái gì đó mới và sau đó khởi động lại máy chủ uWSGI. Tại thời điểm tôi đóng máy chủ uWSGI, máy chủ nginx sẽ trả về lỗi 499.

Vì vậy, tôi tiếp tục gỡ lỗi với lỗi 499, có nghĩa là googling cho lỗi 499. Nhưng nếu tôi đã đợi đủ lâu, tôi sẽ nhận được lỗi 504. Nếu tôi gặp lỗi 504, tôi sẽ có thể hiểu vấn đề tốt hơn và sau đó có thể gỡ lỗi.

Vì vậy, kết luận là, vấn đề là với uWGSI, liên tục bị treo ("Chờ một chút nữa, chỉ một chút nữa, sau đó tôi sẽ có câu trả lời cho bạn ...").

Tôi đã khắc phục sự cố đó như thế nào , tôi không nhớ. Tôi đoán nó có thể được gây ra bởi rất nhiều thứ.


1
Làm thế nào bạn kết thúc việc này? Tôi đang gặp sự cố tương tự và không thể xác định nguyên nhân.
Colin Nichols

1
Tôi đã thêm một chi tiết, rất tiếc, tôi không nghĩ rằng nó sẽ giải quyết được vấn đề của bạn.
Mads Skjern

1
Chỉ muốn nói lời cảm ơn! Tôi đã gặp trường hợp tương tự và điều này đã đưa tôi đi đúng hướng.
Aaron

3
@Shafiul: Sự giải thích của tôi không giải thích điều gì đã gây ra sự cố với uWSGI, nó chỉ giải thích rằng uWSGI là nguyên nhân (chứ không phải nginx). Phần xây dựng mô tả các triệu chứng và cách tôi giải thích sai những điều này. Tôi hiểu sự thất vọng của bạn, nhưng bạn đã hiểu sai bản chất câu trả lời của tôi. Trân trọng.
Mads Skjern

2
Câu trả lời cực kỳ hữu ích, không bao giờ xóa! Những khái niệm này nên được bổ sung trong tài liệu ở đâu đó, bạn thực hiện một dịch vụ tuyệt vời bằng cách giải thích cách nó hoạt động khác với các tài liệu sẽ ngụ ý!
jerclarke

21

Khách hàng đóng kết nối không có nghĩa đó là sự cố trình duyệt !? Không có gì!

Bạn có thể tìm thấy 499 lỗi trong tệp nhật ký nếu bạn có LB (bộ cân bằng tải) ở phía trước máy chủ web của bạn (nginx) AWS hoặc haproxy (tùy chỉnh). Điều đó nói rằng LB sẽ hoạt động như một khách hàng của nginx.

Nếu bạn chạy các giá trị mặc định của haproxy cho:

    timeout client  60000
    timeout server  60000

Điều đó có nghĩa là LB sẽ hết thời gian chờ sau 60000ms nếu không có phản hồi từ nginx. Thời gian chờ có thể xảy ra đối với các trang web bận rộn hoặc tập lệnh cần nhiều thời gian hơn để thực thi. Bạn sẽ cần tìm thời gian chờ phù hợp với mình. Ví dụ, hãy mở rộng nó thành:

    timeout client  180s
    timeout server  180s

Và bạn có thể sẽ được thiết lập.

Tùy thuộc vào thiết lập của bạn, bạn có thể thấy lỗi thời gian chờ cổng 504 trong trình duyệt của mình, điều này cho thấy có điều gì đó không ổn với php-fpm nhưng điều đó sẽ không xảy ra với lỗi 499 trong tệp nhật ký của bạn.


12

Khi bạn chỉ 499một kết nối phá thai được ghi lại bởi nginx. Nhưng thông thường điều này được tạo ra khi máy chủ phụ trợ của bạn quá chậm và một proxy khác hết thời gian chờ trước hoặc phần mềm người dùng hủy kết nối. Vì vậy, hãy kiểm tra xem uWSGI có trả lời nhanh hay không nếu có bất kỳ tải nào trên máy chủ uWSGI / Database.

Trong nhiều trường hợp, có một số proxy khác giữa người dùng và nginx. Một số có thể nằm trong cơ sở hạ tầng của bạn như có thể là CDN, Load Balacer, bộ nhớ cache Varnish, v.v. Những người khác có thể ở phía người dùng như proxy bộ nhớ đệm, v.v.

Nếu có các proxy bên bạn như LoadBalancer / CDN ... bạn nên đặt thời gian chờ thành thời gian chờ trước phần phụ trợ của bạn và dần dần các proxy khác cho người dùng.

Nếu bạn có:

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

Tôi khuyên bạn nên đặt:

  • n giây để uWSGI hết thời gian
  • n+1 giây để nginx hết thời gian
  • n+2 tiền thưởng đến thời gian chờ để Cân bằng tải
  • n+3 giây hết thời gian cho CDN.

Nếu bạn không thể đặt một số thời gian chờ (như CDN), hãy tìm thời gian chờ của nó là gì và điều chỉnh những thời gian khác theo nó ( n, n-1...).

Điều này cung cấp một chuỗi thời gian chờ chính xác. và bạn sẽ tìm thấy người thực sự đưa ra thời gian chờ và trả lại mã phản hồi phù hợp cho người dùng.


8

Trong trường hợp của tôi, tôi nhận được 499 khi API của khách hàng đóng kết nối trước khi nó nhận được bất kỳ phản hồi nào. Theo nghĩa đen, đã gửi một BÀI ĐĂNG và ngay lập tức đóng kết nối. Điều này được giải quyết theo tùy chọn:

proxy_ignore_client_abort đang bật

Nginx doc


3
Tôi không hiểu làm thế nào giúp đỡ này
Vladimir Starkov

Có lẽ đó không phải là trường hợp của bạn? Khách hàng gửi dữ liệu và không quan tâm đến điều gì sẽ xảy ra với họ và câu trả lời sẽ là gì. Nhưng ứng dụng của tôi sẽ xử lý dữ liệu. Nếu không có tùy chọn này, dữ liệu chỉ đơn giản là không có thời gian đến ứng dụng của tôi.
DerSkythe

Cảm ơn bạn. Các triệu chứng chính xác và cách khắc phục hoàn hảo.
TTimo

Ái chà! Đó gần như chính xác là những gì tôi cần. Điều duy nhất tôi muốn thêm - sẽ là gửi 200 phản hồi đến nguồn webhook một chút trước khi nó tự đóng kết nối. Nếu không, họ có xu hướng vô hiệu hóa webhook và không 'gửi lại… Tôi có thể làm như vậy cho các URL đã chọn không?
pilat,

1
Điều này không giải quyết được vấn đề khách hàng của bạn không nhận được phản hồi. Nó chỉ loại bỏ 499 lỗi trong nhật ký của bạn và thay thế chúng bằng mã trạng thái 200. Ý tưởng tồi để làm điều này. Giải pháp thực sự là yêu cầu khách hàng của bạn tăng cài đặt thời gian chờ của họ ...
marcinx

7

Hóa ra 499 thực sự có nghĩa là "máy khách bị gián đoạn kết nối."

Tôi đã có thời gian chờ đọc của khách hàng là 60 giây (và nginx cũng có proxy_read_timeout mặc định là 60 giây). Vì vậy, những gì đã xảy ra trong trường hợp của tôi là nginx sẽ lỗi. Ghi nhật ký upstream timed out (110: Connection timed out) while reading upstreamvà sau đó nginx thử lại "máy chủ proxy tiếp theo trong nhóm máy chủ phụ trợ mà bạn đã định cấu hình." Đó là nếu bạn có nhiều hơn một.

Sau đó, nó cố gắng tiếp theo và tiếp theo cho đến khi (theo mặc định ) nó đã cạn kiệt tất cả chúng. Khi mỗi lần xuất hiện, nó cũng xóa chúng khỏi danh sách các máy chủ phụ trợ "trực tiếp". Sau khi tất cả đều cạn kiệt, nó trả về504 gateway timeout.

Vì vậy, trong trường hợp của tôi, nginx đã đánh dấu máy chủ là "không khả dụng", hãy thử lại trên máy chủ tiếp theo, sau đó 60sthời gian chờ của khách hàng của tôi (ngay lập tức) xảy ra, vì vậy tôi sẽ thấy upstream timed out (110: Connection timed out) while reading upstreamnhật ký, ngay sau đó là nhật ký 499. Nhưng đó chỉ là sự trùng hợp về thời gian.

Có liên quan:

Nếu tất cả các máy chủ trong nhóm được đánh dấu là hiện không khả dụng, thì nó cũng trả về giá 502 Bad Gateway.trị trong 10 giây. Xem tại đây max_fails và fail_timeout. Ghi vào nhật ký nó sẽ nóino live upstreams while connecting to upstream.

Nếu bạn chỉ có một phụ trợ proxy trong nhóm máy chủ của mình, nó chỉ thử là một máy chủ và trả về một 504 Gateway Time-outmáy chủ duy nhất và không xóa máy chủ duy nhất khỏi danh sách máy chủ "trực tiếp", nếu proxy_read_timeoutbị vượt qua. Xem tại đây "Nếu chỉ có một máy chủ duy nhất trong một nhóm, các tham số max_fails, fail_timeout và slow_start bị bỏ qua và một máy chủ như vậy sẽ không bao giờ được coi là không khả dụng."

Một phần thực sự khó khăn là nếu bạn chỉ định proxy_pass cho "localhost" và hộp của bạn cũng có "phiên bản vị trí" ipv6 và ipv4 trên đó cùng lúc (hầu hết các hộp làm theo mặc định), nó sẽ được tính như thể bạn có "danh sách" nhiều máy chủ trong nhóm máy chủ của bạn, có nghĩa là bạn có thể gặp trường hợp ở trên khi nó trả về "502 trong 10 giây" mặc dù bạn chỉ liệt kê một máy chủ . Xem tại đây "Nếu một tên miền phân giải thành nhiều địa chỉ, tất cả chúng sẽ được sử dụng theo kiểu vòng tròn." Một cách giải quyết là khai báo nó là proxy_pass http://127.0.0.1:5001;(địa chỉ ipv4 của nó) để tránh nó là cả ipv6 và ipv4. Sau đó, nó được tính là hành vi "chỉ một máy chủ duy nhất".

Có một số cài đặt khác nhau mà bạn có thể điều chỉnh để giảm bớt sự cố này. Như tăng thời gian chờ hoặc làm cho nó không đánh dấu máy chủ là "bị vô hiệu hóa" khi chúng hết thời gian chờ ... hoặc sửa danh sách để nó chỉ có kích thước 1, xem ở trên :)

Xem thêm: https://serverfault.com/a/783624/27813


3

Lỗi này khá dễ tái tạo bằng cách sử dụng cấu hình nginx tiêu chuẩn với php-fpm.

Giữ nút F5 xuống trên một trang sẽ tạo ra hàng chục yêu cầu làm mới đến máy chủ. Mỗi yêu cầu trước đó sẽ bị trình duyệt hủy bỏ khi làm mới. Trong trường hợp của tôi, tôi tìm thấy hàng tá 499 trong tệp nhật ký cửa hàng trực tuyến của khách hàng của tôi. Theo quan điểm nginx: Nếu phản hồi chưa được gửi đến máy khách trước khi yêu cầu làm mới tiếp theo, nginx sẽ ghi lại lỗi 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)

Tất nhiên, nếu quá trình xử lý php-fpm lâu hơn (như một trang WP nặng), nó có thể gây ra sự cố. Ví dụ, tôi đã nghe nói về sự cố php-fpm, nhưng tôi tin rằng chúng có thể được ngăn chặn khi định cấu hình các dịch vụ đúng cách như xử lý các cuộc gọi đến xmlrpc.php.


2

... đến đây từ một tìm kiếm trên google

Tôi đã tìm thấy câu trả lời ở nơi khác tại đây -> https://stackoverflow.com/a/15621223/1093174

đó là để tăng thời gian chờ kết nối không hoạt động của bộ cân bằng tải đàn hồi AWS của tôi!

(Tôi đã thiết lập một trang Django với proxy ngược nginx / apache và một công việc / chế độ phụ trợ đăng nhập thực sự thực sự thực sự đã hết thời gian chờ)


0

Khi tôi nhận được 499 "Yêu cầu đã bị phần mềm chống vi-rút cấm" dưới dạng phản hồi http AJAX (dương tính giả bởi Kaspersky Internet Security với phân tích kinh nghiệm nhẹ, phân tích kinh nghiệm sâu biết chính xác không có gì sai).


0

Tôi gặp phải sự cố này và nguyên nhân là do plugin Kaspersky Protection trên trình duyệt. Nếu bạn đang gặp phải vấn đề này, hãy thử tắt plugin của bạn và xem liệu điều đó có khắc phục được sự cố của bạn hay không.


0

Một trong những lý do cho hành vi này có thể là bạn đang sử dụng httpfor uwsgithay vì socket. Sử dụng lệnh dưới đây nếu bạn đang sử dụng uwsgitrực tiếp.

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

Lệnh tương tự trong tệp .ini là

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

0

Điều này không trả lời câu hỏi OPs, nhưng vì tôi đã kết thúc ở đây sau khi điên cuồng tìm kiếm câu trả lời, tôi muốn chia sẻ những gì chúng tôi đã khám phá.

Trong trường hợp của chúng tôi, hóa ra những con số 499 này được mong đợi. Ví dụ: khi người dùng sử dụng tính năng gõ trước trong một số hộp tìm kiếm, chúng tôi thấy một cái gì đó như thế này trong nhật ký.

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]

Vì vậy, trong trường hợp của chúng tôi, tôi nghĩ rằng nó an toàn để sử dụng proxy_ignore_client_abort onđã được đề xuất trong câu trả lời trước. Cảm ơn vì điều đó!


0

Về phần mình, tôi đã kích hoạt ufwnhưng tôi quên để lộ các cổng ngược dòng của mình ._.


0

Trong trường hợp của tôi, tôi đã thiết lập như

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

Tôi đã định cấu hình sai nhóm bảo mật AWS cho dịch vụ ECS (php-fpm), vì vậy Nginx không thể tiếp cận với vùng chứa tác vụ php-fpm. Đó là lý do tại sao tôi gặp lỗi trong nhật ký tác vụ nginx

499 0 - elb-healthchecker/2.0

Kiểm tra tình trạng đã được định cấu hình để kiểm tra dịch vụ php-fpm và xác nhận nó hoạt động và đưa ra phản hồi.


0

Tôi biết đây là một chủ đề cũ, nhưng nó hoàn toàn khớp với những gì gần đây đã xảy ra với tôi và tôi nghĩ tôi sẽ ghi lại nó ở đây. Thiết lập (trong Docker) như sau:

  • nginx_proxy
  • nginx
  • php_fpm đang chạy ứng dụng thực tế.

Dấu hiệu là "502 Gateway Timeout" trên lời nhắc đăng nhập ứng dụng. Kiểm tra các bản ghi được tìm thấy:

  • nút hoạt động thông qua HTTP POSTđể /login... và vì vậy ...
  • nginx-proxy có /login yêu cầu và cuối cùng đã báo cáo hết thời gian chờ.
  • nginx đã trả lại một 499phản hồi, tất nhiên có nghĩa là "máy chủ đã chết."
  • các /loginyêu cầu đã không xuất hiện ở tất cả (!) trong nhật ký máy chủ của FPM!
  • không có dấu vết hoặc thông báo lỗi trong FPM ... nada, zero, zippo, không có.

Hóa ra vấn đề là do không kết nối được với cơ sở dữ liệu để xác minh đăng nhập. Nhưng làm thế nào để tìm ra điều đó hóa ra là phỏng đoán đơn thuần.

Sự vắng mặt hoàn toàn của các bản ghi theo dõi ứng dụng ... hoặc thậm chí một bản ghi mà yêu cầu đã được FPM nhận được ... là một sự ngạc nhiên hoàn toàn (và, khủng khiếp ...) đối với tôi. Có, ứng dụng được cho là ghi các lỗi, nhưng trong trường hợp này, có vẻ như quy trình FPM worker đã chết do lỗi thời gian chạy, dẫn đến 499phản hồi từ nginx. Bây giờ, đây rõ ràng là một vấn đề trong ứng dụng của chúng tôi ... ở đâu đó. Nhưng tôi muốn ghi lại những chi tiết cụ thể về những gì đã xảy ra vì lợi ích của những người tiếp theo phải đối mặt với điều gì đó như thế này.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.