限流
春运,一项全人类历史上最大规模的迁移活动,抢火车票一直是每年跨年以后的热点话题。
系统设计时一般会预估负载,当系统暴露在公网中时,恶意攻击或正常突发流量等都可能导致系统被压垮,而限流就是保护措施之一。
Nginx 的两种限流设置:
控制速率。
控制并发连接数。
限流算法
漏桶算法
漏桶算法思路很简单,水(请求)先进入到漏桶里,漏桶以一定的速度出水,当水流入速度过大会直接溢出,可以看出漏桶算法能强行限制数据的传输速率。
令牌桶算法
令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。
漏桶 vs 令牌桶的区别
漏桶的天然特性决定了它不会发生突发流量,就算每秒 1000 个请求到来,那么它对后台服务输出的访问速率永远恒定。而令牌桶则不同,其特性可以“预存”一定量的令牌,因此在应对突发流量的时候可以在短时间消耗所有令牌,其突发流量处理效率会比漏桶高,但是导向后台系统的压力也会相应增多。
实现限流
Nginx 限速配置指令
根据 nginx 官网提供的说法,有两种算法,一种是漏桶算法,一种是令牌桶算法
- limit_req_zone 用来限制单位时间内的请求数目,以及速度限制。
- imit_req_conn 用来限制同一时间连接数,即并发限制。
http {
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=1r/s;
server {
limit_req zone=mylimit burst=1 nodelay;
}
}
limit_req_zone 参数解析
第一个参数:$binary_remote_addr 限制同一客户端 ip 地址。
第二个参数:zone=mylimit:10m 用来存储访问的频次信息。
第三个参数:rate=1r/s 表示允许相同标识的客户端的访问频次,这里限制的是每秒 1 次,还可以有比如 30r/m 的
server{}内 limit_req 参数解析
第一个参数:zone=one 设置使用哪个配置区域来做限制,与上面 limit_req_zone 里的 name 对应。
第二个参数:burst=5,重点说明一下这个配置,burst 爆发的意思,这个配置的意思是设置一个大小为 5 的缓冲区当有大量请求(爆发)过来时,超过了访问频次限制的请求可以先放到这个缓冲区内。
第三个参数:nodelay,如果设置,超过访问频次而且缓冲区也满了的时候就会直接返回 503,如果没有设置,则所有请求会等待排队。
Nginx 并发限制配置指令
ngx_http_limit_conn_module
提供了限制连接数的能力,利用 limit_conn_zone
和 limit_conn
两个指令即可
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) 同时能处理并发连接的总数。