测试代码:https://github.com/MacwinWin/docker_nginx_quick_test
不知道什么时候开始,我对Nginx的limit_req印象是下面这样的:
下面的配置通过rate参数,实现每秒300次请求的处理
http {
limit_req_zone $binary_remote_addr zone=perip:2m rate=300r/s;
server {
location ~ / {
limit_req zone=perip;
}
}
}
但如果你用ab进行测试,你会发现
>>> ab -c 300 -n 300 'http://0.0.0.0:8080/'
This is ApacheBench, Version 2.3 <$Revision: 1879490 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 0.0.0.0 (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Finished 300 requests
Server Software: nginx/1.21.3
Server Hostname: 0.0.0.0
Server Port: 8080
Document Path: /
Document Length: 153 bytes
Concurrency Level: 300
Time taken for tests: 0.183 seconds
Complete requests: 300
Failed requests: 275
(Connect: 0, Receive: 0, Length: 275, Exceptions: 0)
Non-2xx responses: 300
Total transferred: 97500 bytes
HTML transferred: 50300 bytes
Requests per second: 1635.59 [#/sec] (mean)
Time per request: 183.420 [ms] (mean)
Time per request: 0.611 [ms] (mean, across all concurrent requests)
Transfer rate: 519.11 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 11 4.0 11 17
Processing: 20 106 25.2 98 160
Waiting: 3 104 27.4 98 159
Total: 21 117 22.0 108 163
Percentage of the requests served within a certain time (ms)
50% 108
66% 130
75% 131
80% 133
90% 152
95% 159
98% 162
99% 163
100% 163 (longest request)
>>> docker logs nginx_test
...
2021/09/14 01:53:50 [error] 32#32: *1180 limiting requests, excess: 0.700 by zone "five", client: 172.20.0.1, server: localhost, request: "GET / HTTP/1.0", host: "0.0.0.0:8080"
172.20.0.1 - - [14/Sep/2021:01:53:50 +0000] "GET / HTTP/1.0" 503 197 "-" "ApacheBench/2.3" "-"
2021/09/14 01:53:50 [error] 32#32: *1179 limiting requests, excess: 0.400 by zone "five", client: 172.20.0.1, server: localhost, request: "GET / HTTP/1.0", host: "0.0.0.0:8080"
2021/09/14 01:53:50 [error] 32#32: *1178 "/etc/nginx/html/index.html" is not found (2: No such file or directory), client: 172.20.0.1, server: localhost, request: "GET / HTTP/1.0", host: "0.0.0.0:8080"
172.20.0.1 - - [14/Sep/2021:01:53:50 +0000] "GET / HTTP/1.0" 404 153 "-" "ApacheBench/2.3" "-"
2021/09/14 01:53:50 [error] 32#32: *1177 limiting requests, excess: 0.700 by zone "five", client: 172.20.0.1, server: localhost, request: "GET / HTTP/1.0", host: "0.0.0.0:8080"
172.20.0.1 - - [14/Sep/2021:01:53:50 +0000] "GET / HTTP/1.0" 503 197 "-" "ApacheBench/2.3" "-"
172.20.0.1 - - [14/Sep/2021:01:53:50 +0000] "GET / HTTP/1.0" 503 197 "-" "ApacheBench/2.3" "-"
172.20.0.1 - - [14/Sep/2021:01:53:50 +0000] "GET / HTTP/1.0" 503 197 "-" "ApacheBench/2.3" "-"
2021/09/14 01:53:50 [error] 32#32: *1200 limiting requests, excess: 0.400 by zone "five", client: 172.20.0.1, server: localhost, request: "GET / HTTP/1.0", host: "0.0.0.0:8080"
2021/09/14 01:53:50 [error] 32#32: *1191 limiting requests, excess: 0.400 by zone "five", client: 172.20.0.1, server: localhost, request: "GET / HTTP/1.0", host: "0.0.0.0:8080"
2021/09/14 01:53:50 [error] 32#32: *1176 limiting requests, excess: 0.400 by zone "five", client: 172.20.0.1, server: localhost, request: "GET / HTTP/1.0", host: "0.0.0.0:8080"
172.20.0.1 - - [14/Sep/2021:01:53:50 +0000] "GET / HTTP/1.0" 503 197 "-" "ApacheBench/2.3" "-"
172.20.0.1 - - [14/Sep/2021:01:53:50 +0000] "GET / HTTP/1.0" 503 197 "-" "ApacheBench/2.3" "-"
2021/09/14 01:53:50 [error] 32#32: *1175 limiting requests, excess: 0.100 by zone "five", client: 172.20.0.1, server: localhost, request: "GET / HTTP/1.0", host: "0.0.0.0:8080"
2021/09/14 01:53:50 [error] 32#32: *1174 limiting requests, excess: 0.100 by zone "five", client: 172.20.0.1, server: localhost, request: "GET / HTTP/1.0", host: "0.0.0.0:8080"
172.20.0.1 - - [14/Sep/2021:01:53:50 +0000] "GET / HTTP/1.0" 503 197 "-" "ApacheBench/2.3" "-"
2021/09/14 01:53:50 [error] 32#32: *1190 limiting requests, excess: 0.100 by zone "five", client: 172.20.0.1, server: localhost, request: "GET / HTTP/1.0", host: "0.0.0.0:8080"
2021/09/14 01:53:50 [error] 32#32: *1161 "/etc/nginx/html/index.html" is not found (2: No such file or directory), client: 172.20.0.1, server: localhost, request: "GET / HTTP/1.0", host: "0.0.0.0:8080"
2021/09/14 01:53:50 [error] 32#32: *1160 limiting requests, excess: 0.400 by zone "five", client: 172.20.0.1, server: localhost, request: "GET / HTTP/1.0", host: "0.0.0.0:8080"
172.20.0.1 - - [14/Sep/2021:01:53:50 +0000] "GET / HTTP/1.0" 503 197 "-" "ApacheBench/2.3" "-"
172.20.0.1 - - [14/Sep/2021:01:53:50 +0000] "GET / HTTP/1.0" 404 153 "-" "ApacheBench/2.3" "-"
172.20.0.1 - - [14/Sep/2021:01:53:50 +0000] "GET / HTTP/1.0" 503 197 "-" "ApacheBench/2.3" "-"
172.20.0.1 - - [14/Sep/2021:01:53:50 +0000] "GET / HTTP/1.0" 503 197 "-" "ApacheBench/2.3" "-"
2021/09/14 01:53:50 [error] 32#32: *1155 limiting requests, excess: 0.100 by zone "five", client: 172.20.0.1, server: localhost, request: "GET / HTTP/1.0", host: "0.0.0.0:8080"
2021/09/14 01:53:50 [error] 32#32: *1201 "/etc/nginx/html/index.html" is not found (2: No such file or directory), client: 172.20.0.1, server: localhost, request: "GET / HTTP/1.0", host: "0.0.0.0:8080"
172.20.0.1 - - [14/Sep/2021:01:53:50 +0000] "GET / HTTP/1.0" 404 153 "-" "ApacheBench/2.3" "-"
172.20.0.1 - - [14/Sep/2021:01:53:50 +0000] "GET / HTTP/1.0" 503 197 "-" "ApacheBench/2.3" "-"
2021/09/14 01:53:50 [error] 32#32: *1124 limiting requests, excess: 1.000 by zone "five", client: 172.20.0.1, server: localhost, request: "GET / HTTP/1.0", host: "0.0.0.0:8080"
2021/09/14 01:53:50 [error] 32#32: *1173 "/etc/nginx/html/index.html" is not found (2: No such file or directory), client: 172.20.0.1, server: localhost, request: "GET / HTTP/1.0", host: "0.0.0.0:8080"
172.20.0.1 - - [14/Sep/2021:01:53:50 +0000] "GET / HTTP/1.0" 404 153 "-" "ApacheBench/2.3" "-"
...
可以发现有大量503响应
这是由于我对rate的理解有误导致的配置错误
正确的理解应是:burst是桶的容量,rate是水从桶中流出的速度(最开始理解rate是水流入桶的速度 )
所以应该将上面的配置改为:
http {
limit_req_zone $binary_remote_addr zone=perip:2m rate=300r/s;
server {
location ~ / {
limit_req zone=perip burst=300;
}
}
}
...
Concurrency Level: 300
Time taken for tests: 1.041 seconds
Complete requests: 300
Failed requests: 0
Non-2xx responses: 300
Total transferred: 90900 bytes
HTML transferred: 45900 bytes
Requests per second: 288.31 [#/sec] (mean)
Time per request: 1040.545 [ms] (mean)
Time per request: 3.468 [ms] (mean, across all concurrent requests)
Transfer rate: 85.31 [Kbytes/sec] received
...
强烈建议细读这篇官方博客https://www.nginx.com/blog/rate-limiting-nginx/
Rate – Sets the maximum request rate. In the example, the rate cannot exceed 10 requests per second. NGINX actually tracks requests at millisecond granularity, so this limit corresponds to 1 request every 100 milliseconds (ms). Because we are not allowing for bursts (see the next section), this means that a request is rejected if it arrives less than 100ms after the previous permitted one.