nginx-proxy超时参数解释

先说明下nginx版本是:
nginx version: nginx/1.17.10 (Ubuntu)

配置说明

send_timeout time;

发送数据至客户端超时, 默认60s, 如果连续的60s内客户端没有收到1个字节, 连接关闭
Default: send_timeout 60s;
Context: http, server, location
Sets a timeout for transmitting a response to the client. The timeout is set only between two successive write operations,not for the transmission of the whole response. If the client does not receive anything within this time, the connection is closed.

proxy_connect_timeout time;

nginx与upstream server的连接超时时间
Default: proxy_connect_timeout 60s;
Context: http, server, location
Defines a timeout for establishing a connection with a proxied server. It should be noted that this timeout cannot usually exceed 75 seconds.

proxy_read_timeout time;

nginx接收upstream server数据超时, 默认60s, 如果连续的60s内没有收到1个字节, 连接关闭
Default: proxy_read_timeout 60s;
Context: http, server, location
Defines a timeout for reading a response from the proxied server. The timeout is set only between two successive read operations,not for the transmission of the whole response. If the proxied server does not transmit anything within this time, the connection is closed.

proxy_send_timeout time;

nginx发送数据至upstream server超时, 默认60s, 如果连续的60s内没有发送1个字节, 连接关闭
Default: proxy_send_timeout 60s;
Context: http, server, location
Sets a timeout for transmitting a request to the proxied server. The timeout is set only between two successive write operations,not for the transmission of the whole request. If the proxied server does not receive anything within this time, the connection is closed.

proxy_next_upstream_timeout

nginx请求next upstream的超时时间,默认为0,当为0的时候就是关闭限制,也就是没有超时时间,那这个时候会一直等下去吗? 还是又回到上面的read_timeout,send_timeout这些标准呢?

即在proxy_next_upstream_timeout时间内允许proxy_next_upstream_tries次重试。如果超过了其中一个设置,则Nginx也会结束重试并返回客户端响应。
但是我们知道proxy_next_uptream_tries默认也是0,表示没有限制。那这么看来最后是遵循proxy_send_timeout来的,你proxy_next_uptream再多,最后都是要满足上面的要求。那个时间是有默认值的60秒的。

因此这个参数没看源码,没有测试就是猜测出来是这个结果。后面我们自己测试下看看。

Default: proxy_next_upstream_timeout 0;
Context: http, server, location
Limits the time during which a request can be passed to the next server. The 0 value turns off this limitation.

试验

那就我们来做个试验吧。

后面81和82都只是用nc来监听的。

proxy_send_timeout时间远大于proxy_next_upstream timeout

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name _;

proxy_connect_timeout 1s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
proxy_next_upstream timeout http_502 http_504;
proxy_next_upstream_timeout 15s;
proxy_next_upstream_tries 10;

location / {
proxy_pass http://test;
}

}
1
2
3
4
5
6
7
8
9
10
11
HTTP/1.1 504 Gateway Time-out


time_namelookup: 0.000053
time_connect: 0.000287
time_appconnect: 0.000000
time_pretransfer: 0.000340
time_redirect: 0.000000
time_starttransfer: 60.002161
----------
time_total: 60.006748

很奇怪吧,为什么是60秒啊。好像跟proxy_next_upstream_timeout完全没关系。
而且看到现象是82端口压根就没有请求,只请求了81端口。

下面附上日志

1
127.0.0.1 127.0.0.1 - [2020-06-30T22:28:36+08:00] "GET / HTTP/1.1" 504 177 "-" "curl/7.68.0" "-" 60.000|60.000|test|127.0.0.1:82|-|504

proxy_read_timeout小于proxy_next_upstream timeout

好了,我们改下配置,把send_timeout和read_timeout都改为6秒,next部分不变

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
upstream test {
server 127.0.0.1:81 max_fails=3 fail_timeout=2s;
server 127.0.0.1:82 max_fails=3 fail_timeout=2s;
}


server {
listen 80 default_server;
listen [::]:80 default_server;


root /var/www/html;

index index.html index.htm index.nginx-debian.html;

server_name _;
proxy_connect_timeout 1s;
proxy_send_timeout 6s;
proxy_read_timeout 6s;

proxy_next_upstream error timeout http_502 http_504;
proxy_next_upstream_timeout 15s;
proxy_next_upstream_tries 2;

location / {
proxy_pass http://test;
}

}

curl下结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
HTTP/1.1 504 Gateway Time-out
Server: nginx/1.17.10 (Ubuntu)
Date: Tue, 30 Jun 2020 14:38:53 GMT
Content-Type: text/html
Content-Length: 177
Connection: keep-alive


time_namelookup: 0.000054
time_connect: 0.000290
time_appconnect: 0.000000
time_pretransfer: 0.000346
time_redirect: 0.000000
time_starttransfer: 12.002669
----------
time_total: 12.006150

出乎意料居然是12秒,我们再来看看日志

1
127.0.0.1 127.0.0.1 - [2020-06-30T22:38:53+08:00] "GET / HTTP/1.1" 504 177 "-" "curl/7.68.0" "-" 12.002|6.000, 6.001|test|127.0.0.1:81, 127.0.0.1:82|-|504, 504

proxy_read_timeout时间*2大于proxy_next_upstream_timeout

2个后端都请求了,每个都是6s。总计时间控制再15秒内。那是不是意味着如果我send_timeout和read_timeout是8秒,最后一次请求是7秒超时呢?
现实又给我们打脸了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
server {
listen 80 default_server;
listen [::]:80 default_server;


root /var/www/html;

index index.html index.htm index.nginx-debian.html;

server_name _;
proxy_connect_timeout 1s;
proxy_send_timeout 8s;
proxy_read_timeout 8s;

proxy_next_upstream error timeout http_502 http_504;
proxy_next_upstream_timeout 15;
proxy_next_upstream_tries 2;

location / {
proxy_pass http://test;
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
HTTP/1.1 504 Gateway Time-out
Server: nginx/1.17.10 (Ubuntu)
Date: Tue, 30 Jun 2020 14:43:46 GMT
Content-Type: text/html
Content-Length: 177
Connection: keep-alive


time_namelookup: 0.000054
time_connect: 0.000261
time_appconnect: 0.000000
time_pretransfer: 0.000336
time_redirect: 0.000000
time_starttransfer: 16.003110
----------
time_total: 16.006434

16秒,完全不受next_uptream_timeout的控制啊。日志里也是同样如此:

1
127.0.0.1 127.0.0.1 - [2020-06-30T22:43:46+08:00] "GET / HTTP/1.1" 504 177 "-" "curl/7.68.0" "-" 16.002|8.001, 8.001|test|127.0.0.1:82, 127.0.0.1:81|-|504, 504

proxy_read_timeout时间等于proxy_next_upstream_timeout*tries

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
server {
listen 80 default_server;
listen [::]:80 default_server;


root /var/www/html;

index index.html index.htm index.nginx-debian.html;

server_name _;
proxy_connect_timeout 1s;
proxy_send_timeout 8s;
proxy_read_timeout 8s;

proxy_next_upstream error timeout http_502 http_504;
proxy_next_upstream_timeout 4s;
proxy_next_upstream_tries 2;

location / {
proxy_pass http://test;
}

}

这次结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
HTTP/1.1 504 Gateway Time-out
Server: nginx/1.17.10 (Ubuntu)
Date: Tue, 30 Jun 2020 15:04:38 GMT
Content-Type: text/html
Content-Length: 177
Connection: keep-alive


time_namelookup: 0.000051
time_connect: 0.000261
time_appconnect: 0.000000
time_pretransfer: 0.000313
time_redirect: 0.000000
time_starttransfer: 8.002434
----------
time_total: 8.006333
1
127.0.0.1 127.0.0.1 - [2020-06-30T23:04:38+08:00] "GET / HTTP/1.1" 504 177 "-" "curl/7.68.0" "-" 8.001|8.001|test|127.0.0.1:82|-|504

总结

有上面试验可见 proxy_next_upstream_timeout和proxy_next_upstream_tries是同时使用的,先满足哪个就全部完成。
同时,单次的upstream请求是受proxy_send_timeout和proxy_read_timeout来控制的。proxy_next_upstream_timeout是一个整体的请求后端的累计时间。

proxy_send/proxy_read proxy_next_upstream_timeout proxy_next_upstream_tries 整体请求时间 upstream请求次数
8s 4s 2 8s 1
8s 15s 2 16s 2
6s 15s 2 12s 2
60s 15s 10 60s 1