Py008-10-07限速

限速

  • 限速该特性可以限制某个用户在⼀个给定时间段内能够产生的HTTP请求数。请求可以简单到就是⼀一个对于主页的GET请求或者一个登陆表格的POST请求。
  • 限速也可以⽤用于安全⽬的上,⽐如暴力密码破解攻击。通过限制进来的请求速率,并且(结合⽇志)标记出⽬目标URLs来帮助防范DDoS攻击。⼀般地说,限流是用在 保护上游应⽤服务器不被在同一时刻的大量⽤户请求湮没。

经典案例 12306

并非12306的开发人员low,而是因为环境太特殊。

1
2
3
4
5
买票就是在浏览器里刷新。每刷新一次就会产生大量链接给服务器,服务器就要开很多的子进程来处理请求。
频繁的刷服务器肯定受不了。

服务器收到海量的刷新。
承受不住就挂了。

阮一峰的博客被攻击过——DDOS

1
2
比如:你在肯德基,一个肯德基店铺最多接受50来人。
但是这一地点突然来了 几千个人。堵得水泄不通。导致KFC没法工作

应用场景

  • DDOS防御
  • 下载场景保护IO (多个客户端打开迅雷下载一个文件)

nginx限速原理

漏桶原理

1
2
3
4
水(请求)从上方倒入⽔桶,从⽔桶下方流出(被处理);
来不及流出的水存在⽔桶中(缓冲),以固定速率流出;
⽔桶满后⽔溢出(丢弃)。
这个算法的核⼼是:缓存请求、匀速处理、多余的请求直接丢弃。

实现方式

1
2
3
 Nginx官⽅版本限制IP的连接和并发分别有两个模块:
limit_req_zone 用来限制单位时间内的请求数,即速率限制。
limit_req_conn ⽤来限制同一时间连接数,即并发限制
  • limit_req_zone 参数配置
  • Syntax: limit_req zone=name [burst=number] [nodelay];
  • Default: —
  • Context: http, server, location

限速案例一(请求限速)

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
#基于IP对下载速率做限制 限制每秒处理1次请求,对突发超过5个以后的请求放⼊缓存区 
http {
# 设置缓存区那个 桶
limit_req_zone $binary_remote_addr zone=hjx:10m rate=1r/s;
server {
# 对abc目录进行限速
location /abc/ {
# 使用缓存区 最大请求为5个,超过5个返回503
limit_req zone=hjx burst=5 nodelay;
}
}
}

limit_req_zone $binary_remote_addr zone=baism:10m rate=1r/s;
第⼀个参数:$binary_remote_addr 表示通过remote_addr这个标识来做限制,“binary_”的⽬的是缩写内存占⽤量,是限制同⼀一客户端ip地址。

第二个参数:zone=baism:10m表示生成⼀一个⼤⼩为10M,名字为one的内存区域,⽤来存储访问的频次信息。

第三个参数:rate=1r/s表示允许相同标识的客户端的访问频次,这里限制的是每秒1次,还可以有⽐如30r/m的。
limit_req zone=baism burst=5 nodelay;

第⼀个参数:zone=baism 设置使⽤哪个配置区域来做限制,与上面limit_req_zone 里的name对应。

第二个参数:burst=5,重点说明一下这个配置,burst爆发的意思,这个配置的意思是设置一个⼤小为5的缓冲区当有⼤大量请求(爆发)过来时,超过了访问频次限制的请求可以先放到这个缓冲区内。

第三个参数:nodelay,如果设置,超过访问频次⽽且缓冲区也满了的时候就会直接返回503,如果没有设置,则所有请求会等待排队。

限速案例二(下载限速)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#基于IP做连接限制 限制同⼀IP并发为1 下载速度为100K 
limit_conn_zone $binary_remote_addr zone=addr:10m;

server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
location /abc {
limit_conn addr 1;
limit_rate 100k;
}
}

准备一个大文件

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
# 造一个300m的文件
dd if=/dev/zero of=/usr/local/nginx/html/abc/bigfile bs=1M count=300

# 切换到临时目录下载这个文件
wget http://45.77.47.0/abc/bigfile
# 下载就很快,而且还能多台机器同时下载

# 修改配置 nginx.conf

limit_conn_zone $binary_remote_addr zone=addr:10m;
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
location /abc {
# 限制同时连接的数量
limit_conn addr 1;
# 限制下载速率
limit_rate 100k;
# 下载100M的时候限速(这个参数不太重要,因为不是按比例只能按大小)
limit_rate_after 100m;
}
}