Nginx proxy_read_timeout与proxy_connect_timeout

我已经开始使用Nginx作为提供某种服务的一组服务器的反向代理

这个服务有时可能相当慢(它运行在Java上,而且JVM有时会陷入“完全垃圾回收”中,可能需要几秒钟),所以我把proxy_connect_timeout设置为2秒,这将给Nginx足够的时间弄清楚服务停留在GC上,不会及时响应,而且应该将请求传递给另一台服务器。

我还设置了proxy_read_timeout来防止反向代理被阻塞,如果服务本身需要太多时间来计算响应 – 再次,它应该将请求移动到另一个服务器,该服务器应该有足够的空间来返回一个及时的响应。

我已经运行了一些基准,我可以清楚地看到, proxy_connect_timeout正常工作,因为一些请求正好在连接超时指定的时间返回,因为服务被卡住,不接受传入的连接(服务使用Jetty作为embedded式servlet容器)。 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; 

然后我设置两个testing服务器。 一个只会在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 } 

然后我发送了一个testing连接:

 [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" 

然后access.log有预期的30s超时(10 + 20):

 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会由于读取超时而中止。

连接超时意味着握手时的TCP延迟(例如,没有SYN_ACK)。 TCP将重新尝试发送SYN,但你只给了2秒。 到Nginx去使用另一台服务器,所以根本没有时间重新发送SYN。

UPD。 :无法在文档中find,但tcpdump显示,有3秒。 第一次发送SYN和第二次尝试发送SYN之间的延迟。