NGINX 499 오류 코드의 가능한 이유


116

499 NGINX 오류 코드가 많이 나타납니다. 이것이 클라이언트 측 문제라는 것을 알았습니다. NGINX 또는 내 uWSGI 스택의 문제가 아닙니다. 나는 499를 얻을 때 uWSGI 로그의 상관 관계에 주목합니다.

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

더 자세한 설명을 찾고 있으며 uwsgi에 대한 NGINX 구성에 문제가 없기를 바랍니다. 나는 그것을 액면 그대로 받아들이고있다. 클라이언트 문제인 것 같습니다.


이것에 대한 해결책을 찾았습니까? uWSGI와 nginx에서 똑같은 문제가 발생합니다.
Raj

1
jQuery ajax 요청을 중단하면 나타납니다.
mpen 2014-04-02

1
나는 이것이 매우 오래된 질문이라는 것을 알고 있지만 SO에 대한 잘못된 질문의 양은 엄청납니다. 이것은 분명히 SF에 속합니다.
Sosukodo

답변:


163

Nginx의 HTTP 499 는 서버가 요청에 응답하기 전에 클라이언트가 연결을 닫았 음을 의미합니다 . 내 경험상 일반적으로 클라이언트 측 시간 초과로 인해 발생합니다 . 내가 알고 있듯이 그것은 Nginx 특정 오류 코드입니다.


1
특별한 경우로 최종 사용자가 양식 제출 버튼을 두 번 클릭 할 때 가끔 발생한다는 것을 알았습니다. 양식은 두 번 전송되지만 클라이언트는 하나의 응답 만 예상합니다. JS에서 버튼을 처음 클릭 할 때 (적어도 몇 초 동안) 비활성화하여 해결할 수 있습니다.
Antoine Pinsard

14
"클라이언트"가 실제로 프록시 일 수 있다는 점에 유의하는 것이 중요합니다. 예를 들어로드 밸런서를 사용하는 경우 시간 초과로 인해 nginx 서버에 대한 요청을 취소 할 수 있습니다.
Brad Koch

사용자가 탭을 닫고 API 요청이 완료되지 않으면 Angular 앱에서 발생합니다.
Vivek Saurabh

이것은 서버 에 의해서도 발생할 수 있다는 점에 유의하십시오 . 서버가 응답하는 데 너무 오래 걸리면 클라이언트는 포기합니다.
ijoseph

78

제 경우에는 참을성이 없어서 로그를 잘못 해석했습니다.

실제로 실제 문제는 브라우저와 nginx 간의 통신이 아니라 nginx와 uwsgi 간의 통신이었습니다. 내 브라우저에 사이트를로드하고 충분히 기다렸다면 "504-Bad Gateway"를 얻었을 것입니다. 하지만 시간이 너무 오래 걸려서 계속 시도하고 브라우저에서 새로 고침했습니다. 그래서 504 오류를 볼 때까지 기다린 적이 없습니다. 브라우저에서 새로 고침하면 이전 요청이 닫히고 Nginx는이를 로그에 499로 기록합니다.

동화

여기에서는 내가 놀기 시작했을 때와 마찬가지로 독자가 아는 것이 거의 없다고 가정합니다.

내 설정은 역방향 프록시, nginx 서버 및 응용 프로그램 서버, 그 뒤에있는 uWSGI 서버였습니다. 클라이언트의 모든 요청은 nginx 서버로 이동 한 다음 uWSGI 서버로 전달 된 다음 동일한 방식으로 응답이 전송됩니다. 나는 이것이 모든 사람들이 nginx / uwsgi를 사용하고 그것을 사용하는 방법이라고 생각합니다.

내 nginx가 제대로 작동했지만 uwsgi 서버에 문제가 있습니다. uwsgi 서버가 nginx 서버에 응답하지 못하는 두 가지 방법이 있습니다.

1) uWSGI가 "처리 중입니다. 잠시만 기다려주십시오. 곧 응답을 받으실 것입니다." nginx는 기다릴 수있는 일정 시간 (fx 20 초)을 가지고 있습니다. 그 후 504 오류로 클라이언트에 응답합니다.

2) uWSGI가 죽었거나 nginx가 기다리는 동안 uWSGi가 죽습니다. nginx는이를 즉시 확인하고이 경우 499 오류를 반환합니다.

클라이언트 (브라우저)에서 요청하여 설정을 테스트하고있었습니다. 브라우저에서는 아무 일도 일어나지 않았고 계속 중단되었습니다. 약 10 초 (시간 초과 미만) 후에 뭔가 잘못되었다는 결론 (사실)을 확인하고 명령 줄에서 uWSGI 서버를 닫았습니다. 그런 다음 uWSGI 설정으로 이동하여 새로운 것을 시도한 다음 uWSGI 서버를 다시 시작합니다. uWSGI 서버를 닫는 순간 nginx 서버는 499 오류를 반환합니다.

그래서 499 erroe로 계속 디버깅했는데, 이는 499 오류에 대한 인터넷 검색을 의미합니다. 그러나 충분히 기다렸다면 504 오류가 발생했을 것입니다. 504 오류가 발생했다면 문제를 더 잘 이해하고 디버깅 할 수 있었을 것입니다.

결론은 uWGSI에 문제가 있다는 것입니다.이 문제는 계속 매달려 있습니다 ( "조금 더 오래, 조금만 더 기다리십시오. 그러면 제가 답변 해 드리겠습니다 ...").

어떻게 문제를 고쳤는지 기억이 나지 않습니다. 많은 것들이 원인 일 수 있다고 생각합니다.


1
어떻게이 문제를 해결하게 되었습니까? 동일한 문제가 발생하여 원인을 파악할 수 없습니다.
Colin Nichols

1
나는 정교함을 추가했지만 불행히도 그것이 당신의 문제를 해결할 것이라고 생각하지 않습니다.
Mads Skjern

1
감사합니다! 나는 똑같은 상황을 겪었고 이것이 나를 올바른 길로 인도했습니다.
Aaron

3
@Shafiul : 내 정교하게 uWSGI에 문제의 원인을 설명하지 않고 uWSGI가 원인 (nginx가 아님)이라고 설명합니다. 그 정교함은 증상과 내가 이것을 어떻게 잘못 해석했는지 설명합니다. 귀하의 실망은 이해하지만 귀하는 내 대답의 본질을 오해했습니다. 진정으로.
Mads Skjern

2
매우 유용한 답변, 절대 삭제하지 마십시오! 이러한 개념은 문서 어딘가에 구체화되어야합니다. 문서가 의미하는 것과 다르게 작동하는 방식을 정교화하여 훌륭한 서비스를 수행합니다!
jerclarke

21

클라이언트가 연결을 닫았다 고해서 브라우저 문제가 아닙니다!? 전혀!

웹 서버 (nginx) 앞에 LB (로드 밸런서)가 AWS 또는 haproxy (사용자 지정) 인 경우 로그 파일에서 499 오류를 찾을 수 있습니다. 그것은 LB가 nginx의 클라이언트 역할을 할 것이라고 말했습니다.

다음에 대해 haproxy 기본값을 실행하는 경우 :

    timeout client  60000
    timeout server  60000

이는 nginx에서 응답이 없으면 LB가 60000ms 후에 시간 초과됨을 의미합니다. 실행에 더 많은 시간이 필요한 바쁜 웹 사이트 또는 스크립트의 경우 시간 초과가 발생할 수 있습니다. 자신에게 맞는 타임 아웃을 찾아야합니다. 예를 들어 다음으로 확장하십시오.

    timeout client  180s
    timeout server  180s

그리고 당신은 아마 설정 될 것입니다.

설정에 따라 php-fpm에 문제가 있음을 나타내는 504 게이트웨이 시간 초과 오류가 브라우저에 표시 될 수 있지만 로그 파일에 499 오류가있는 경우는 해당되지 않습니다.


12

499nginx가 기록한 연결 중단 을 가리 킵니다 . 그러나 일반적으로 이것은 백엔드 서버가 너무 느리고 다른 프록시가 먼저 시간 초과되거나 사용자 소프트웨어가 연결을 중단 할 때 생성됩니다 . 따라서 uWSGI가 빠르게 응답하는지 여부를 확인하고 uWSGI / 데이터베이스 서버에 부하가 있는지 확인하십시오.

많은 경우 사용자와 nginx 사이에 다른 프록시가 있습니다. 일부는 CDN, Load Balacer, Varnish 캐시 등과 같은 인프라에있을 수 있습니다. 다른 일부는 캐싱 프록시 등과 같은 사용자 측에있을 수 있습니다.

LoadBalancer / CDN과 같은 프록시가있는 경우 타임 아웃을 먼저 백엔드에서 시간 초과로 설정하고 점진적으로 다른 프록시를 사용자에게로 설정해야합니다.

당신이 가지고 있다면:

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

다음을 설정하는 것이 좋습니다.

  • n uWSGI 시간 초과까지의 초
  • n+1 nginx 시간 초과까지 초
  • n+2 로드 밸런서 시간 초과에 대한 조건
  • n+3 CDN에 대한 제한 시간 (초).

일부 시간 제한 (예 : CDN)을 설정할 수없는 경우 시간 제한이 무엇인지 찾아 그에 따라 다른 항목을 조정합니다 ( n, n-1...).

이것은 올바른 타임 아웃 체인을 제공합니다. 타임 아웃을 제공 한 사람을 찾고 사용자에게 올바른 응답 코드를 반환합니다.


8

제 경우에는 클라이언트의 API가 응답을 받기 전에 연결을 닫았을 때 499를 얻었습니다. 말 그대로 POST를 보내고 즉시 연결을 닫습니다. 이것은 옵션으로 해결됩니다.

proxy_ignore_client_abort on

Nginx 문서


3
나는이 도움을 수행하는 방법을 이해 해달라고
블라디미르 Starkov

당신 사건이 아닐까요? 클라이언트는 데이터를 전송하고 그들에게 어떤 일이 일어나고 어떤 대답이 될지에 관심이 없습니다. 하지만 내 애플리케이션은 데이터를 처리해야합니다. 이 옵션이 없으면 데이터가 내 애플리케이션에 도달 할 시간이 없습니다.
DerSkythe

감사합니다. 정확한 증상과 완벽한 수정.
TTimo

우와! 그것은 거의 정확히 내가 필요한 것입니다. 내가 추가 할 유일한 것은 연결 자체를 닫기 전에 웹훅 소스에 200 개의 응답을 보내는 것입니다. 그렇지 않으면 웹훅을 비활성화하고 다시 보내지 않는 경향이 있습니다. 선택한 URL에 대해 그렇게 할 수 있습니까?
pilat

1
이것은 고객이 응답을받지 못하는 문제를 해결하지 못합니다. 로그에서 499 개의 오류 만 제거하고 상태 코드 200으로 대체합니다. 이렇게하는 것은 좋지 않습니다. 진정한 해결책은 클라이언트에게 시간 제한 설정을 늘리라고 알리는 것입니다.
marcinx

7

499는 실제로 "클라이언트가 연결을 중단했다"는 의미입니다.

클라이언트 읽기 제한 시간이 60 초였으며 nginx에는 기본 proxy_read_timeout도 60 초가 있습니다. 그래서 제 경우에 일어난 일은 nginx가 error.log an upstream timed out (110: Connection timed out) while reading upstream다음 nginx가 "구성한 백엔드 서버 그룹의 다음 프록시 서버"를 재 시도 한다는 것 입니다. 하나 이상있는 경우입니다.

그런 다음 ( 기본적으로 ) 모든 항목을 다 사용할 때까지 다음과 다음을 시도 합니다. 각각의 시간이 초과되면 "라이브"백엔드 서버 목록에서도 제거됩니다. 모두 소진 된 후에는504 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 매개 변수는 무시하고, 같은 서버를 사용할 수없는 상태로 간주되지 않습니다이 있다면."

정말 까다로운 부분은 "localhost"에 proxy_pass를 지정하고 상자에 ipv6 및 ipv4 "위치 버전"이 동시에있는 경우 (대부분의 상자는 기본적으로 수행됨) 서버 그룹에있는 여러 서버의 "목록"입니다. 즉, 하나의 서버 만 나열하더라도 "502 for 10s"를 반환하는 위의 상황에 들어갈 수 있습니다 . 여기를 참조 하십시오. "도메인 이름이 여러 주소로 확인되면 모두 라운드 로빈 방식으로 사용됩니다." 한 가지 해결 방법은 ipv6 및 ipv4가되는 것을 방지proxy_pass http://127.0.0.1:5001; 하기 위해 (IPv4 주소) 로 선언하는 것 입니다. 그런 다음 "단일 서버"동작으로 간주됩니다.

문제를 "줄 이도록"조정할 수있는 몇 가지 다른 설정이 있습니다. 시간 초과를 늘리거나 시간 초과시 서버를 "사용 안함"으로 표시하지 않도록 만드는 것과 같이 ... 또는 목록을 수정하여 크기가 1 만되도록합니다. 위를 참조하십시오. :)

참조 : https://serverfault.com/a/783624/27813


3

이 오류는 php-fpm에서 표준 nginx 구성을 사용하여 재현하기가 매우 쉽습니다.

페이지에서 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 Elastic Load Balancer의 연결 유휴 시간 초과를 늘리는 것이 었습니다!

(저는 nginx / apache 역방향 프록시로 Django 사이트를 설정했고 정말 정말 로그 백엔드 작업 / 뷰가 시간 초과되었습니다)


0

내가 가진 후 499 "요청이 바이러스에 의해 금지 된" AJAX를 HTTP 응답으로 (빛 휴리스틱 분석과 카스퍼 스키 인터넷 시큐리티에 의해 위양성, 깊은 휴리스틱 분석은 아무것도 잘못이 있었다 정확하게 알고 있었다).


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

이것은 OPs 질문에 대한 답은 아니지만 답을 찾기 위해 격렬하게 여기에 왔기 때문에 우리가 발견 한 것을 공유하고 싶었습니다.

우리의 경우에는이 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).

ECS (php-fpm) 서비스에 대해 잘못된 AWS 보안 그룹을 구성했기 때문에 Nginx가 php-fpm 작업 컨테이너에 연결할 수 없었습니다. 그래서 nginx 작업 로그에 오류가 발생했습니다.

499 0 - elb-healthchecker/2.0

상태 확인은 php-fpm 서비스를 확인하고 서비스가 작동하는지 확인하고 응답을 제공하도록 구성되었습니다.


0

나는 이것이 오래된 스레드라는 것을 알고 있지만 최근에 일어난 일과 정확히 일치하며 여기에 문서화 할 것이라고 생각했습니다. 설정 (Docker에서)은 다음과 같습니다.

  • nginx_proxy
  • nginx
  • 실제 앱을 실행하는 php_fpm.

증상은 응용 프로그램 로그인 프롬프트의 "502 게이트웨이 시간 초과"였습니다. 발견 된 로그 검사 :

  • 버튼은 HTTP POST를 통해 작동합니다 /login.
  • nginx-proxy가 /login요청을 받았으며 결국 시간 초과를보고했습니다.
  • nginx 499는 "호스트가 죽었다 "는 의미 의 응답을 반환 했습니다.
  • /login요청은 모든 (!)에 나타나지 않았다 FPM이 서버의 로그에!
  • FPM에는 트레이스 백이나 오류 메시지가 없었습니다 ... nada, zero, zippo, none.

문제는 로그인을 확인하기 위해 데이터베이스에 연결하지 못한 것으로 밝혀졌습니다. 그러나 그것을 알아내는 방법은 순수한 추측으로 밝혀졌습니다 .

응용 프로그램 추적 로그의 완전한 부재 ... 또는 요청이 FPM 수신되었다고도 기록 ... 완전한했다 (... 파괴 등) 나에게 놀람. 예, 응용 프로그램은 실패를 기록해야하지만이 경우에는 FPM 작업자 프로세스가 런타임 오류와 함께 종료 499되어 nginx 의 응답으로 이어집니다. 자, 이것은 분명히 우리 응용 프로그램의 문제입니다. 하지만 나는 이런 일에 직면 한 다음 사람들을 위해 무슨 일이 있었는지 기록하고 싶었습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.