每天进步一点点:Nginx限流设置

in #cn2 months ago

最近一个网站被访问到爆炸,按说有人气是好事,但是如果这个人气并不是真实的访客,有极大可能是一个工具类从同一个IP发起的访问,那就没意思了,并且会影响正常的用户使用。

image.png
(图源 :pixabay)

眼看着原本瞬间可以返回的请求要三五秒之后才能返回而我的一些工具都近乎无法使用,我知道必须想办法解决这个问题了。

Nginx限流模块

因为网站我使用的Nginx+反向代理,所以想到的方法就是使用Nginx限制流量,查了一下文档,Nginx有两个限流模块:

ngx_http_limit_conn_module
ngx_http_limit_req_module

两者定义如下:

The ngx_http_limit_conn_module module is used to limit the number of connections per the defined key, in particular, the number of connections from a single IP address.

The ngx_http_limit_req_module module (0.7.21) is used to limit the request processing rate per a defined key, in particular, the processing rate of requests coming from a single IP address.

从字面意思来看,我觉得一个是限制同时链接数,另一个是限制请求处理速率。

使用限流模块

限制链接数

在使用限制链接数指令之前,需要用如下指令开辟一个共享内存区域用来保存状态:

limit_conn_zone key zone=name:size;

其中key是我们要限制的对象,name是这个区域的命名,size表示这个区域的大小。

实际例子:

limit_conn_zone $binary_remote_addr zone=perip:10m;

有了上述zone设置后,我们就可以在server或者location下设置限制同一来源IP的同时链接数了。

server {
    ...
    limit_conn perip 1;
}

上述指令限制同一来源IP最多同时最多有1个链接到这个server上来。

限制请求速率

尽管我们限制了同一IP同时只能有一个链接到server,但是假设我们server处理请求的速度非常快,那么这个IP就可以不停地发送新的请求过来,比如说一秒钟内发送了1000次请求,这显然也是滥用server,所以限制请求速率也很重要。

同样我们先需要开辟一块共享内存区域用来保存状态:

limit_req_zone key zone=name:size rate=rate [sync];

相比于limit_conn_zonekey, name基本上一样,rate则代表允许的请求速率。一个实际的例子大致是这样:

limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;

有了上述zone设置后,我们就可以在server或者location下设置限制同一来源IP的请求速率了,比如:

server {
    ...
    limit_req zone=one burst=5 nodelay;
}

$server_name

除了使用$binary_remote_addr来针对同一来源IP进行同时链接数或者请求速率限制外,还可以使用$server_name限制针对此server的同时链接数或者请求速率。

比如限制针对这个server最多允许100个同时连接或者每秒100个请求。但是这样做可能会导致正常的连接已经请求被拒绝,所以如无必要,不建议对此进行设置。

实战

在了解上述知识后,在我的服务器上应用了上述设置后,原本要爆炸的服务器总算恢复正常访问了。需要说明的是我们可以定义不同的zone,然后针对不同location进行更为复杂的组合设置,这样可以满足更加复杂的需求。

另外,我们还可以用一些指令来定义出错信息以及日志之类的,这里就不再赘述了。不得不说的是nginx真的是太强大啦。

参考链接

注:本文首发HIVE平台,欢迎大家到HIVE上关注我,并参与讨论。