Nginx proxy_read_timeout与proxy_connect_timeout


15

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

该服务有时可能很慢(它在Java上运行,并且JVM有时会陷入“完全垃圾收集”,可能需要几秒钟的时间),因此我将其设置proxy_connect_timeout为2秒,这将使Nginx有足够的时间来确定知道该服务停留在GC上并且不会及时响应,因此应将请求传递给其他服务器。

proxy_read_timeout如果服务本身花费太多时间来计算响应,我还设置了防止反向代理卡住的方法-再次,它应将请求移至另一台服务器,该服务器应有足够的空闲时间以返回及时的响应。

我已经运行了一些基准测试,并且可以清楚地看到proxy_connect_timeout,由于服务被卡住并且不接受传入连接(该服务使用Jetty作为嵌入式),一些请求恰好在连接超时指定的时间返回,因此工作正常servlet容器)。这proxy_read_timeout也有效,因为我可以看到在此处指定的超时后返回的请求。

问题是proxy_read_timeout + proxy_connect_timeout,如果服务被卡住,并且当Nginx尝试访问它时,但在Nginx可以超时之前-它被释放,我本来希望看到一些请求在超时后或差不多该时间长度内超时。并开始处理,但速度太慢,由于读取超时,Nginx将中止。我认为该服务有这种情况,但是在运行多个基准测试后,总共发出了数百万个请求-我看不到单个请求返回的任何值都超过上述值proxy_read_timeout(这是较大的超时)。

我很乐意对此问题发表任何评论,尽管我认为这可能是由于Nginx中的错误(我尚未查看代码,所以这只是一个假设),连接后超时计数器不会重置如果Nginx没有从上游服务器读取任何内容,则表示成功。


1
什么版本的NGINX?我想我记得较旧的版本(可能约为0.6 / 7)中有类似的东西,但是在较新的版本中已得到修复(最新的稳定版本为1.0.5),但这可能是错误的。仍然知道您的版本会有所帮助
涂抹

请注意,文档说proxy_read_timeout的不是“全局超时”,而是两次读取操作之间的时间。
2011年

@Sam:我正在使用Nginx 1.0.0。@poige-是的,我知道这一点,这就是为什么我希望总超时为proxy_read_timeout + proxy_connect_timeout
摊铺

1
附带说明,您可能应该研究一些针对JVM的并发垃圾回收调整:en.wikipedia.org/wiki/…–
多项式

@polynomial:我们确实做到了,但是根据我们的基准,并发垃圾收集功能导致整体CPU损失的CPU时间要比“停止世界” GC多,因此,我们更愿意投资Nginx调整:-)
Guss

Answers:


18

我实际上无法在以下位置重现此内容:

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';

1
在您的情况下,我的上述问题更像是这样:假设一个测试服务器在0到20秒之间的随机时间之后接受连接,然后在19到21秒之间的随机时间之后回答。然后针对它运行一个简单的基准。我希望看到10%的超时结果中约有50%的请求结果,20〜30秒的超时中有25%的结果,而25%的请求将收到成功的响应。在这种情况下,有多少成功的请求将花费20秒钟以上的时间才能完成?在我的基准测试中,它们都不是-麻烦我。
摊铺

我通过在SYN上设置随机丢失,然后让CGI缓慢吐出线路大约50秒来进行测试。我能够看到请求花费的时间远远超过两个超时的总和,但仍然成功:box.access.log 200:69.814:67.100:。:1579 33 127.0.0.1 test.host-[21 / Aug / 2011:20: 30:52 -0700]“ GET / huugs HTTP / 1.1”“-”“-”“-” dev_edge 127.0.0.1:2280-–
多项式

好吧,那在一个完全不同的层面上很奇怪:-)。一种可能的解释是,Nginx需要花费一些时间来编写请求(proxy_send_timeout),并且如您将其设置为更高的请求proxy_connection_timeout,实际上可以解决20秒内的任何延迟proxy_read_timeout。当您说“慢慢地画线”时,您是什么意思?
摊铺

在响应正文中的HTML打印行之间休眠1。仅公开两次读取之间的proxy_read_timeout情况,而不是整个读取。
多项式

1
知道了 好吧,这绝对不是我的情况,对于无法在我的OP中明确说明我很抱歉。就我而言,应用服务器在返回任何类型的响应之前先完成整个处理,然后立即返回所有内容-因此proxy_read_timeout要么完全失败请求,要么完全允许请求。这也解释了您看到的行为与我看到的行为之间的区别。
摊铺

3

问题是,我希望在proxy_read_timeout + proxy_connect_timeout之后,或者差不多是该时间长度,看到一些超时请求,如果服务被卡住,并且在Nginx尝试访问它但在Nginx可以超时之前不接受连接-它被释放并开始处理,但是速度太慢,Nginx将由于读取超时而中止。

连接超时意味着握手时TCP停顿(例如,没有SYN_ACK)。TCP会重试发送SYN,但是您只花了2秒钟。到Nginx去使用另一个服务器,因此它根本没有时间重新发送SYN。

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


我不认为这正是我要问的-问题是:如果上游卡住并在1.999秒后返回SYN_ACK,为什么nginx不会继续使用当前上游进行处理?
摊铺

好吧,如果您想确保准确的话,可以使用嗅探器。事实证明,在不到2秒的时间内根本没有ACK。
poige 2011年

我真的不能使用嗅探器,因为我希望看到这种现象发生在系统上负载很高的地方。即使在考虑数百万个请求时,即使在考虑数百万个请求之后,也永远不会在X之后出现ACK,而在2秒之前出现ACK的解释似乎是不合理的。
摊铺
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.