Gus*_*uss 23 nginx proxy timeout
我已经开始使用 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 没有从上游服务器读取任何内容,则成功。
pol*_*ial 26
我实际上无法在以下内容上重现此内容:
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
Run Code Online (Sandbox Code Playgroud)
我在我的 nginx.conf 中进行了设置:
proxy_connect_timeout 10;
proxy_send_timeout 15;
proxy_read_timeout 20;
Run Code Online (Sandbox Code Playgroud)
然后我设置了两个测试服务器。一种只会在 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
}
Run Code Online (Sandbox Code Playgroud)
然后我发送了一个测试连接:
[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
Run Code Online (Sandbox Code Playgroud)
然后看 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"
Run Code Online (Sandbox Code Playgroud)
然后:
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"
Run Code Online (Sandbox Code Playgroud)
然后是预期 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 -
Run Code Online (Sandbox Code Playgroud)
这是我正在使用的日志格式,其中包括各个上游超时:
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';
Run Code Online (Sandbox Code Playgroud)
问题是,如果服务卡住并且在 Nginx 尝试访问它时不接受连接,但在 Nginx 可以超时之前,我本希望看到一些请求在 proxy_read_timeout + proxy_connect_timeout 之后超时,或者几乎是那个时间长度 -它被释放并开始处理,但速度太慢,Nginx 会因为读取超时而中止。
连接超时意味着握手时 TCP 停止(例如,没有 SYN_ACK)。TCP 会重新尝试发送 SYN,但您只给了 2 秒。到 Nginx 去使用另一个服务器,所以它根本没有时间重新发送 SYN。
更新。: 在文档中找不到,但 tcpdump 显示有3秒。第一次发送 SYN 和第二次尝试发送 SYN 之间的延迟。
| 归档时间: |
|
| 查看次数: |
115412 次 |
| 最近记录: |