本文主要是对nginx官方limit_req
相关模块的限速原理的解释和一些个人理解,主要参考的文章为Rate Limiting with NGINX and NGINX Plus
和nginx的ngx_http_limit_req_module
的详细说明。
目前来说在nginx上面我们常见的三种限速操作分别是:限制请求数(request)、限制连接数(connection)、限制响应速度(rate),对应在nginx的模块相关指令分别是limit_req
、limit_conn
和limit_rate
三个系列。
1、前言
限速(rate limiting)是NGINX中一个非常有用但是经常被误解且误用的功能特性。我们可以用它来限制在一段时间内的HTTP请求的数量,这些请求可以是如GET
这样的简单请求又或者是用来填充登录表单的POST
请求。
限速还可以用于安全防护用途,例如限制密码撞库暴力破解等操作的频率,也可以通过把请求频率限制在一个正常范围来抵御DDoS攻击。不过更常见的使用情况是通过限制请求的数量来确保后端的upstream服务器不会在短时间内遭受到大量的流量访问从而导致服务异常。
本文会尽量覆盖nginx中限速(rate limiting)的基本概念也相关知识同时会顺带尽可能多的提一下相关的进阶配置方法。限速(rate limiting)在付费版本的nginx(Nginx Plus)中也是同样可以使用的。
NGINX Plus R16 及之后的版本支持“全局限速(global rate limiting)”,可以在一整个nginx集群中对某个用户或者连接进行限速状态的同步。原理基本上类似于openresty+redis的工作模式,将限速的状态存储到一个集群中,当需要限速操作的时候就去集群中读取相关参数,For details, see our blog and the NGINX Plus Admin Guide.
2、工作原理
nginx中限速(rate limiting)的主要算法原理就是基于在计算机网络中当带宽是有限时十分常用的漏桶算法。基本原理就是:**以漏桶为例,水从顶部倒入,从底下漏出。**这里的几个概念分别是:
- 漏桶对应我们服务器的带宽或者是处理请求的能力或者是一个队列
- 水表示客户端发送过来的请求
- 倒入的水则代表客户端发送给服务器但尚未进行处理的请求,此时请求仍在队列(在桶内)
- 漏出的水则代表从队列中出来即将发送给服务器端处理的请求,此时请求已经离开了队列(在桶外)
漏桶在一定程度上可以代表服务器的处理能力,请求根据**先进先出(FIFO)**调度算法等待处理。如果倒入水的速度小于漏水的速度,可以理解为服务器能够处理完所有的请求,此时整体服务表现正常。如果倒入水的速度大于漏水的速度,那么水桶内的水会不断增加直到最后溢出,这种情况下在水桶中的水可以理解为在队列中等待的请求,而溢出的水则表示直接被丢弃不处理的请求。
3、基础配置
下面这里我们列举一个简单的nginx限速配置:
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
server {
location /login/ {
limit_req zone=mylimit;
proxy_pass http://my_upstream;
}
}
这里首先使用了limit_req_zone
指令定义了一个限速zone,名为mylimit
,大小为10MB,对应的变量是$binary_remote_addr
,限制的请求速率是每秒限制10个请求(10requests/secends),在login
这个location
中使用limit_req
指令指定了限制的zone
。接下来我们详细解析一下整个限速的过程:
首先是limit_req_zone
指令主要用于定义速度限制相关的参数,而limit_req
指令则是用于启用定义的限速参数(如这里是在