Nginx限流设置
nginx 提供两种不同的限流方式,分别为ngx_http_limit_req_module
, ngx_http_limit_conn_module
,两个模块可以搭配使用,其中 ngx_http_limit_req_module
用来限制请求次数,ngx_http_limit_conn_module
限制并发连接数,一般都是以IP为key做限制,ngx_http_limit_req_module
更常用
ngx_http_limit_req_module
使用方法为limit_req_zone
在http
中定义规则,limit_req
在http
、server
、location
中使用规则
limit_req_zone 定义规则
http {
# 语法
limit_req_zone key zone=name:size rate=rate [sync];
# demo
limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;
}
- key 一般使用 $binary_remote_addr,在内存中分配一块区域,以key为id记录请求相关
- zone 定义规则名,在 limit_req 中使用
- :size 指定空间大小, 1M在64位操作系统中可以存放1.6w个ip地址
- rate 请求速率 最终会被转化为 平均多少ms一个请求
demo 中的规则解析: 以 $binary_remote_addr 为key 定义一个one规则,其中分配10M空间存储信息,每秒钟允许通过两次请求,每100ms通过一个请求
limit_req 应用规则
server {
location /login/ {
# 语法
limit_req zone=name [burst=number] [nodelay | delay=number];
# demo
limit_req zone=one burst=20 delay=4;
}
}
- name
limit_req_zone
中定义的zone - burst 允许缓存多少个请求; 此处,burst=20 ,若同时有21个请求到达,Nginx 会处理第一个请求,剩余20个请求将放入队列,然后每隔100ms从队列中获取一个请求进行处理。若请求数大于21,将拒绝处理多余的请求,直接返回503.
- 不过,单独使用 burst 参数并不实用。假设 burst=50 ,rate依然为10r/s,排队中的50个请求虽然每100ms会处理一个,但第50个请求却需要等待 50 * 100ms即 5s,这么长的处理时间自然难以接受。因此,burst 往往结合 nodelay 一起使用。
- nodelay|delay=number nodelay 针对的是 burst 参数,
burst=20 nodelay
表示这20个请求立马处理,不能延迟,相当于特事特办。不过,即使这20个突发请求立马处理结束,后续来了请求也不会立马处理。burst=20 相当于缓存队列中占了20个坑,即使请求被处理了,这20个位置这只能按 100ms一个来释放。而设置 delay=10 则相当于前10个请求瞬间响应,第11个请求开始延迟响应
完整实例
http {
limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;
limit_req_status 503; # 设置拒绝响应时的状态码
server {
location / {
limit_req zone=one burst=20 nodelay;
proxy_pass http://my_upstream;
}
}
}
ngx_http_limit_conn_module
限制单个ip并发连接数,域名并发连接数
官方demo
http {
limit_conn_zone $binary_remote_addr zone=perip:10m;
limit_conn_zone $server_name zone=perserver:10m;
server {
limit_conn perip 10;
limit_conn perserver 100;
}
}
limit_conn perip 10
作用的key 是 $binary_remote_addr
,表示限制单个IP同时最多能持有10个连接。
limit_conn perserver 100
作用的key是 $server_name
,表示虚拟主机(server) 同时能处理并发连接的总数。
需要注意的是:只有当 request header 被后端server处理后,这个连接才进行计数。
白名单不限流
设置白名单
限流主要针对外部访问,内网访问相对安全,可以不做限流,通过设置白名单即可。利用 Nginx ngx_http_geo_module
和 ngx_http_map_module
两个工具模块即可搞定。
在 nginx.conf 的 http 部分中配置白名单:
geo $limit {
default 1;
10.0.0.0/8 0;
192.168.0.0/24 0;
172.20.0.35 0;
}
map $limit $limit_key {
0 "";
1 $binary_remote_addr;
}
limit_req_zone $limit_key zone=myRateLimit:10m rate=10r/s;
geo 对于白名单(子网或IP都可以) 将返回0,其他IP将返回1。
map 将 $limit
转换为 $limit_key
,如果是 $limit
是0(白名单),则返回空字符串;如果是1,则返回客户端实际IP。
limit_req_zone
限流的key不再使用 $binary_remote_addr
,而是 $limit_key
来动态获取值。如果是白名单,limit_req_zone
的限流key则为空字符串,将不会限流;若不是白名单,将会对客户端真实IP进行限流。
下载限流
ngx_http_core_module
还提供了限制数据传输速度的能力(即常说的下载速度)。
例如:
location /flv/ {
flv;
limit_rate_after 20m;
limit_rate 100k;
}
这个限制是针对每个请求的,表示客户端下载前20M时不限速,后续限制100kb/s。