Nginx 高并发限流模块 limit_conn_module limit_req_module

Posted by Sunday on 2018-10-22

limit_conn_module

limit_conn_module

1
2
3
4
5
6
7
8
9
10
11
12
http {
limit_conn_zone $binary_remote_addr zone=perip:10m;
limit_conn_zone $server_name zone=perserver:10m;
limit_conn_log_level error;
limit_conn_status 503;
...
server {
...
location /download/ {
limit_conn perip 1; # 限制每个IP只能发起1个连接
limt_rate 100k; # 限速为100kb/秒
}

limit_req_module

ngx_http_limit_req_module

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#limit_req_zone $server_name zone=perserver:10m rate=10r/s;
limit_req_zone $request_uri zone=by_uri:10m rate=30r/m;

server {
listen 80;

location /by-uri/burst0.html {
limit_req zone=by_uri;
}

location /by-uri/burst5.html {
limit_req zone=by_uri burst=5;
}

location /by-uri/burst50.html {
limit_req zone=by_uri burst=5 nodelay;
}
}

10个并发请求测试:

  • 拒绝的链接有多少?
  • 接受的链接有多少?

burst0.html

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
[root@node1 ~]# siege -b -r 1 -c 10 http://static.sundayle.com/by-uri/burst0.html
** SIEGE 4.0.2
** Preparing 10 concurrent users for battle.
The server is now under siege...
HTTP/1.1 200 0.02 secs: 14 bytes ==> GET /by-uri/burst0.html
HTTP/1.1 503 0.01 secs: 206 bytes ==> GET /by-uri/burst0.html
HTTP/1.1 503 0.02 secs: 206 bytes ==> GET /by-uri/burst0.html
HTTP/1.1 503 0.02 secs: 206 bytes ==> GET /by-uri/burst0.html
HTTP/1.1 503 0.02 secs: 206 bytes ==> GET /by-uri/burst0.html
HTTP/1.1 503 0.02 secs: 206 bytes ==> GET /by-uri/burst0.html
HTTP/1.1 503 0.01 secs: 206 bytes ==> GET /by-uri/burst0.html
HTTP/1.1 503 0.03 secs: 206 bytes ==> GET /by-uri/burst0.html
HTTP/1.1 503 0.02 secs: 206 bytes ==> GET /by-uri/burst0.html
HTTP/1.1 503 0.03 secs: 206 bytes ==> GET /by-uri/burst0.html

Transactions: 1 hits
Availability: 10.00 %
Elapsed time: 0.03 secs
Data transferred: 0.00 MB
Response time: 0.20 secs
Transaction rate: 33.33 trans/sec
Throughput: 0.06 MB/sec
Concurrency: 6.67
Successful transactions: 1
Failed transactions: 9
Longest transaction: 0.03
Shortest transaction: 0.01

30r/m表示每2秒允许一个新请求。这10个请求中有1个接受,9个被拒绝。

burst5.html

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
[root@node1 ~]# siege -b -r 1 -c 10 http://static.sundayle.com/by-uri/burst5.html
** SIEGE 4.0.2
** Preparing 10 concurrent users for battle.
The server is now under siege...
HTTP/1.1 200 0.06 secs: 14 bytes ==> GET /by-uri/burst5.html
HTTP/1.1 503 0.14 secs: 206 bytes ==> GET /by-uri/burst5.html
HTTP/1.1 503 0.14 secs: 206 bytes ==> GET /by-uri/burst5.html
HTTP/1.1 503 0.14 secs: 206 bytes ==> GET /by-uri/burst5.html
HTTP/1.1 503 0.14 secs: 206 bytes ==> GET /by-uri/burst5.html
HTTP/1.1 200 2.02 secs: 14 bytes ==> GET /by-uri/burst5.html
HTTP/1.1 200 4.02 secs: 14 bytes ==> GET /by-uri/burst5.html
HTTP/1.1 200 6.02 secs: 14 bytes ==> GET /by-uri/burst5.html
HTTP/1.1 200 8.02 secs: 14 bytes ==> GET /by-uri/burst5.html
HTTP/1.1 200 10.02 secs: 14 bytes ==> GET /by-uri/burst5.html

Transactions: 6 hits
Availability: 60.00 %
Elapsed time: 10.02 secs
Data transferred: 0.00 MB
Response time: 5.12 secs
Transaction rate: 0.60 trans/sec
Throughput: 0.00 MB/sec
Concurrency: 3.07
Successful transactions: 6
Failed transactions: 4
Longest transaction: 10.02
Shortest transaction: 0.06

接受了5个请求,从1/10到6/10成功(其余的被拒绝)。但NGINX更新其令牌并处理接受的请求的方式在这里非常明显:输出速率上限为30r / m,相当于每2秒1个请求

第一个在0.2秒后返回。计时器在2秒后计时,并处理并返回其中一个待处理请求,总往返时间为2.02秒。 2秒后,计时器再次打勾,处理另一个待处理请求,返回的总往返时间为4.02秒。等等等等…

brust50.html

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
[root@node1 ~]# siege -b -r 1 -c 10 http://static.sundayle.com/by-uri/burst50.html
** SIEGE 4.0.2
** Preparing 10 concurrent users for battle.
The server is now under siege...
HTTP/1.1 200 0.01 secs: 14 bytes ==> GET /by-uri/burst50.html
HTTP/1.1 200 0.02 secs: 14 bytes ==> GET /by-uri/burst50.html
HTTP/1.1 200 0.02 secs: 14 bytes ==> GET /by-uri/burst50.html
HTTP/1.1 200 0.02 secs: 14 bytes ==> GET /by-uri/burst50.html
HTTP/1.1 200 0.02 secs: 14 bytes ==> GET /by-uri/burst50.html
HTTP/1.1 200 0.02 secs: 14 bytes ==> GET /by-uri/burst50.html
HTTP/1.1 503 0.02 secs: 206 bytes ==> GET /by-uri/burst50.html
HTTP/1.1 503 0.02 secs: 206 bytes ==> GET /by-uri/burst50.html
HTTP/1.1 503 0.02 secs: 206 bytes ==> GET /by-uri/burst50.html
HTTP/1.1 503 0.02 secs: 206 bytes ==> GET /by-uri/burst50.html

Transactions: 6 hits
Availability: 60.00 %
Elapsed time: 0.03 secs
Data transferred: 0.00 MB
Response time: 0.03 secs
Transaction rate: 200.00 trans/sec
Throughput: 0.03 MB/sec
Concurrency: 6.33
Successful transactions: 6
Failed transactions: 4
Longest transaction: 0.02
Shortest transaction: 0.01

当爆发= 5时,我们仍然具有相同数量的状态200和503.但是现在输出速率不再严格地限制为每2秒1个请求的速率。只要有一些突发令牌可用,就会立即接受并处理任何传入请求。接受的请求不再受到任何额外的延迟。

限流白名单

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
30
31
32
33
34
http {
geo $whiteiplist {
default 1;
127.0.0.1/32 0;
192.168.1.0/24 0;
}

map $whiteiplist $limit {
1 $binary_remote_addr;
0 "";
}

limit_conn_zone $limit zone=conn_ip:10m;
limit_req_zone $limit zone=req_ip:20m rate=10r/s;



location / {
proxy_pass http://mall.sundayle.com/;
proxy_set_header Host mall.sundayle.com;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_redirect off;

# 若还有上一级代理添加
# 如 varish(192.168.10.0/24) --> proxy(mall.sundayle.com) --> 后端
set_real_ip_from 192.168.10.0/24;
real_ip_header X-Forwarded-For;
real_ip_recursive on;

limit_conn conn_ip 30;
limit_rate 100k;
limit_req zone=req_ip burst=5;
}

需要重启下nginx才生效

NGINX rate-limiting in a nutshell