Nginx限流简介和使用案例
1.Nginx限流简介
Nginx官方版本限制IP的连接和并发分别有两个模块:
- limit_req_zone 现在单位时间内的请求数
- limit_req_conn 限制同一时间内的并发连接数
2.ngx_http_limit_req_module 模块
ngx_http_limit_req_module模块,作用是限制定义key的请求处理速率,特别是来自单个IP地址的请求的处理速率。该限制是使用“漏桶”方法完成的。
下面这里列举一个简单的nginx限速配置:
limit_req_zone
定义了一个限速zone,名称为one;基于的key为binary_remote_addr,限制的请求速率是每秒限制10个请求。
- binary_remote_addr:定义限流key,表示对客户端IP来做限流,binary_remote_add比remote_addr更节省内存空间。
- zone:定义了一个限速的共享内存区域名称为one, 内存大小为10M。
- rate : 设置最大访问速率,rate=10r/s 表示每秒处理请求数为10个。
limit_req
使用limit_req指令来将其限制应用于特定location或server块使限制生效
- limit_req zone=one burst=5 nodelay;zone=one 设置使用哪个zone域来做限制,与上面limit_req_zone 里的name对应。
- burst=5,设置请求的最大突发大小。如果请求速率超过为区域配置的速率,则会放到缓冲区内排队,这个配置了最大突发请求是5。
- nodelay,如果不希望在请求受到限制时延迟过多的请求,则应使用该参数,超出的请求会返回503
3. 使用案例
基于URL限制单位时间请求数
有些特定场景下,如某些重要接口限制每秒请求数,单纯的基于ip的限制无法保障该接口的请求数的限制,应该采取基于uri的配置
与基于客户端ip类似的限制配置类似
limit_req_zone $uri zone=app1000:256m rate=1000r/s;
server {
location /app/login {
limit_req zone=app1000 burst=200 nodelay;
}
}
- $uri,记录的是执行一系列内部重定向操作后最终传递到后端服务器的URL
多URL共享限流zone
有些场景下多个接口是同一组后端服务,这种情况下如果这组后端服务有请求数上的一个限制,就需要这几个url共享一个限流zone
可以使用map指令定义zone
map $uri $app1000uri {
default "";
/foo 1;
/bar 1;
}
limit_req_zone $app1000uri zone=app1000:256m rate=1000r/s;
server {
location /foo {
limit_req zone=app1000 burst=200 nodelay;
}
location /bar {
limit_req zone=app1000 burst=200 nodelay;
}
}
- /foo /bar共享1000r/s的限制速率,当url为/foo或/bar时$app1000uri的数值为1,limit_req_zone指令生效;为其他请求url时$app1000uri为"",limit_req_zone指令不生效。
触发限流时返回特定status code
用途,与客户端约定特殊状态码做特殊处理
以下列举的配置
limit_req_zone $uri zone=app1000:256m rate=1000r/s;
server {
location /app/login {
limit_req zone=app1000 burst=200 nodelay;
limit_req_status 520;
}
}
- limit_req_status,设置要返回的状态码以响应被拒绝的请求,默认statuscode为503
基于ip白名单限流
日常使用中nginx不仅会承接线上流量,也会承接内网流量,如果需求当请求是外网ip时触发限流,当请求是内外ip是不触发限流,那么应该如何配置?
请看下面的案例
map $remote_addr $limitwhite {
default $binary_remote_addr;
~*^10\. "";
}
limit_req_zone $limitwhite zone=ipwhitelist:20m rate=100r/s;
server {
location /app/login {
limit_req_zone $limitwhite zone=ipwhitelist:20m rate=100r/s;
}
}
- ip限流白名单,remote_addr为10.开头时,$limitwhite为空,限流不生效