Nginx限流配置
限流算法常用的有2种,分别是漏桶算法和令牌桶算法。
漏桶算法类似于生产者/消费者模式。在一个固定容量的队列里,所有客户端的请求都会从该队列的头部进入到该队列中,之后Nginx会以固定的速率消费该队列里的请求(自行处理或分发到后台服务器),而当队列满了后,Nginx会拒绝之后收到的请求。漏桶算法可以限制Nginx处理请求的速度,而不至于在并发量突然增高的情况下将大量的请求立即转发给后台服务器处理,从而保护后台服务器。
使用令牌桶算法后,Nginx会以固定的速率往容器中存储令牌(如果满了则丢弃令牌),之后Nginx在处理请求前会先去容器中取一个令牌,如果取到了则处理该请求,如果没取到则拒绝该请求。令牌桶算法可以让Nginx能够处理一定量突然发生的高并发请求,但处理完一定数量的瞬间增多的请求后,Nginx处理请求的速率会立马将至最低。
1. 限制最小访问间隔
与限流功能有关的参数有limit_req_zone 和limit_req 。limit_req_zone 用于定义限流的相关参数,limit_req 用于在特定的阶段开启限流。limit_req_zone 指令有3个参数,第一个参数表示根据哪些信息来对请求进行限速,如客户端的IP地址、请求的URI等等,第二个参数表示用来保存被限流请求相关信息的共享内存空间,值的格式为名称:大小 ,第三个参数表示处理请求的最大速率。limit_req 指令用于开启限流,值为limit_req_zone 指令定义的共享内存空间。该指令可以作用在server 和location 指令内,表示对所有location 都启用限流或对某个location 启用限流。
limit_req_zone 指令的第一个参数用来划分限流的对象,如对每个IP地址进行独立的限流、对每个URI进行独立的限流等等,如果想限流所有请求,则该参数的值只需为对所有请求来说都统一的值即可,如字符串、某个固定值的变量,但最终的值不能为空字符串,否则将不会进行限流。
limit_req_zone 和limit_req 指令在同一位置可以被多次使用。
http {
# 定义限流
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
upstream backend {
server 192.168.132.129:8001;
server 192.168.132.129:8002;
server 192.168.132.129:8003;
}
server {
server_name www.test.com;
listen 80;
location /login/ {
# 开启限流
limit_req zone=mylimit;
proxy_pass http://backend;
}
location / {
proxy_pass http://backend;
}
}
}
在上面的例子中,对于某个IP地址每秒最多只允许访问/login/ 请求10次,实际上是两次请求之前的间隔最短为100毫秒,客户端在发起一次请求后,需要等待100毫秒后才能发起下一次请求,否则Nginx将会拒绝发起的请求并返回503错误(服务器暂时不可用)。
$binary_remote_addr 和$remote_addr 都可以表示客户端的IP地址,前者是二进制格式的,消耗的存储空间较小,后者是字符串格式的,消耗的存储空间较大,因为这里并不需要保存客户端的IP地址,因此才用$binary_remote_addr 变量。
2. 处理突发请求(漏桶)
Nginx在开启限流后,会拒绝在最小时间间隔内发起的请求,而在有些特殊情况下,请求数会突然增多,这时就需要将请求先保存起来,之后再逐个处理,而不是直接给客户端返回503错误,造成用户体验不好。通过给limit_req 指令添加burst=n 参数可以指定最多存储请求的个数(也就是队列的长度),当队列满后再返回503错误。
这也就是漏桶算法的实现,Nginx会以固定的速率从队列中处理请求,而当队列满了后将会拒绝请求。
http {
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
upstream backend {
server 192.168.132.129:8001;
server 192.168.132.129:8002;
server 192.168.132.129:8003;
}
server {
server_name www.test.com;
listen 80;
location /login/ {
# 漏桶算法的实现
limit_req zone=mylimit burst=20;
proxy_pass http://backend;
}
location / {
proxy_pass http://backend;
}
}
}
3. 无延迟排队(令牌桶)
在设置了等待队列后,由于Nginx是以规定速率处理请求的,所以虽然不会返回503错误,但客户端还是需要等待一段时间才能收到响应,这也会影响用户体验。在这种情况下可以给limit_req 指令添加nodelay 参数让Nginx立即处理队列中的请求,但会将队列中的请求用一个占位符来表示,之后再以之前定义的速率取出这些占位符。
这也就是令牌桶算法的实现。Nginx会以固定的速率取出占位符,让可用容量增加,也就是以固定的速率添加令牌。
http {
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
upstream backend {
server 192.168.132.129:8001;
server 192.168.132.129:8002;
server 192.168.132.129:8003;
}
server {
server_name www.test.com;
listen 80;
location /login/ {
# 令牌桶算法的实现
limit_req zone=mylimit burst=20 nodelay;
proxy_pass http://backend;
}
location / {
proxy_pass http://backend;
}
}
}
|