Nginx를 일종의 서비스를 제공하는 서버 세트의 리버스 프록시로 사용하기 시작했습니다.
서비스는 때때로 느려질 수 있습니다 (Java에서 실행되고 JVM은 때때로 “전체 가비지 수집”에 몇 초가 걸릴 수 있음). 따라서 proxy_connect_timeout
2 초로 설정하면 Nginx가 알아낼 시간이 충분합니다. 서비스가 GC에 멈춰 있고 시간 내에 응답하지 않으며 요청을 다른 서버로 전달해야합니다.
또한 proxy_read_timeout
서비스 자체가 응답을 계산하는 데 너무 많은 시간이 걸리면 리버스 프록시가 멈추지 않도록 설정 했습니다. 다시 요청을 적시에 응답을 반환 할 수있는 다른 서버로 이동해야합니다.
일부 벤치 마크를 실행 proxy_connect_timeout
했으며 서비스가 멈추고 들어오는 연결을 수락하지 않기 때문에 일부 요청이 연결 시간 초과에 지정된 시간에 정확하게 반환되므로 제대로 작동 한다는 것을 분명히 알 수 있습니다 (서비스는 Jetty를 내장 된 것으로 사용합니다) 서블릿 컨테이너). 는 proxy_read_timeout
내가 타임 아웃 후 반환이를 지정한 요청을 볼 수도 작동합니다.
문제는 proxy_read_timeout + proxy_connect_timeout
서비스가 멈추고 Nginx가 액세스하려고 시도 할 때 연결을 수락하지 않으면 Nginx가 시간 초과하기 전에 요청이 시간 초과 또는 거의 그 시간이 걸리는 것으로 예상 한다는 것입니다. 처리를 시작하지만 너무 느리고 읽기 시간 초과로 인해 Nginx가 중단됩니다. 서비스에 그러한 사례가 있다고 생각하지만 몇 가지 벤치 마크를 실행하여 총 수백만 건의 요청을 처리 한 결과 위의 항목 proxy_read_timeout
(더 큰 시간 초과)으로 반환되는 단일 요청을 보지 못했습니다 .
이 문제에 대한 의견을 보내 주시면 Nginx의 버그 때문일 수 있습니다 (아직 코드를 보지 않았으므로 가정 사항입니다). 연결 후 시간 초과 카운터가 재설정되지 않습니다. Nginx가 업스트림 서버에서 아무것도 읽지 않으면 성공합니다.
답변
실제로 이것을 재현 할 수 없었습니다.
2011/08/20 20:08:43 [notice] 8925#0: nginx/0.8.53
2011/08/20 20:08:43 [notice] 8925#0: built by gcc 4.1.2 20080704 (Red Hat 4.1.2-48)
2011/08/20 20:08:43 [notice] 8925#0: OS: Linux 2.6.39.1-x86_64-linode19
내 nginx.conf에서 이것을 설정했습니다.
proxy_connect_timeout 10;
proxy_send_timeout 15;
proxy_read_timeout 20;
그런 다음 두 개의 테스트 서버를 설정했습니다. 하나는 SYN에서 시간 초과되고 연결을 허용하지만 응답하지 않는 것입니다.
upstream dev_edge {
server 127.0.0.1:2280 max_fails=0 fail_timeout=0s; # SYN timeout
server 10.4.1.1:22 max_fails=0 fail_timeout=0s; # accept but never responds
}
그런 다음 하나의 테스트 연결을 보냈습니다.
[m4@ben conf]$ telnet localhost 2480
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
GET / HTTP/1.1
Host: localhost
HTTP/1.1 504 Gateway Time-out
Server: nginx
Date: Sun, 21 Aug 2011 03:12:03 GMT
Content-Type: text/html
Content-Length: 176
Connection: keep-alive
그런 다음 error_log를보고이를 보여줍니다.
2011/08/20 20:11:43 [error] 8927#0: *1 upstream timed out (110: Connection timed out) while connecting to upstream, client: 127.0.0.1, server: ben.dev.b0.lt, request: "GET / HTTP/1.1", upstream: "http://10.4.1.1:22/", host: "localhost"
그때:
2011/08/20 20:12:03 [error] 8927#0: *1 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 127.0.0.1, server: ben.dev.b0.lt, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:2280/", host: "localhost"
그런 다음 30 초의 타임 아웃 (10 + 20)이있는 access.log :
504:32.931:10.003, 20.008:.:176 1 127.0.0.1 localrhost - [20/Aug/2011:20:12:03 -0700] "GET / HTTP/1.1" "-" "-" "-" dev_edge 10.4.1.1:22, 127.0.0.1:2280 -
다음은 개별 업스트림 시간 초과를 포함하는 로그 형식입니다.
log_format edge '$status:$request_time:$upstream_response_time:$pipe:$body_bytes_sent $connection $remote_addr $host $remote_user [$time_local] "$request" "$http_referer" "$http_user_agent" "$http_x_forwarded_for" $edge $upstream_addr $upstream_cache_status';
답변
문제는 proxy_read_timeout + proxy_connect_timeout 이후에 시간 초과되거나 Nginx가 액세스하려고 시도 할 때 서비스가 중단되어 연결을 수락하지 않으면 Nginx가 시간 초과되기 전에 시간이 초과되는 요청을 볼 수 있다는 것입니다. 해제되어 처리를 시작하지만 너무 느리고 읽기 시간 초과로 인해 Nginx가 중단됩니다.
연결 시간 초과는 핸드 셰이 킹시 (예 : SYN_ACK가 없음) TCP 정지를 의미합니다. TCP는 SYN 전송을 재 시도하지만 2 초만 제공했습니다. 다른 서버를 사용하기 위해 Nginx로 이동하므로 SYN을 다시 보낼 시간이 없습니다.
UPD. : 문서에서 찾을 수 없지만 tcpdump에 3 초가 있음이 표시 됩니다. 첫 번째 SYN 전송과 두 번째 SYN 전송 시도 사이의 지연.