精通Nginx配置,实施高效精准的限流策略

鱼云 2024-12-11 18:23:18

1. 概述

速率限制是一种服务降级方法,通过限制系统的输入和输出流量来保护系统。

例如,我们的网站暴露在公共网络环境中。除了正常的用户访问外,网络爬虫、恶意攻击、大额销售等突发流量也可能给系统带来压力。如果这种压力超过服务器的处理能力,就会导致响应缓慢甚至系统崩溃。

因此,当并发​​请求数过大时,我们通过限制部分请求(如限制同一IP的频繁请求)来保证服务器能够正确响应另一部分请求。

nginx提供了两种限流方式,一种是限制请求速率,一种是限制连接数。

还提供了下载/上传速度的限制。

2. 限制请求速率

nginx的odule模块提供了限制请求处理速率的能力,使用漏桶算法(leaky)。我们可以想象一个水桶,水从顶部流入,水从底部以恒定的速度流出。如果桶里有水,刚刚进入的水就会储存在桶里,直到下面的水喝完。速度快的话,桶里的水就满了。这时水不会进入桶内,而是直接从桶顶溢出。

对应于处理网络请求,水代表来自客户端的请求,桶代表一个队列,其中请求按照先进先出(FIFO)算法等待处理。泄漏意味着请求离开缓冲区并由服务器处理,溢出意味着请求被丢弃并且永远不会得到服务。

图片

2.1.正常限流

nginx 中有两个主要指令可用于配置限制: 和 。

下面是最简单的限流例子:

limit_req_zone $binary_remote_addr znotallow=test:10m rate=2r/s; server { location / { limit_req znotallow=test; } }

用于设置电流限制和共享内存区域的参数,格式为:关键区域速率。

只需设置限流参数即可。如果要生效,必须与 一起使用。格式为:=名称[突发=][]。

上面的例子只是简单的指定了=test,表示测试区的配置是用来在请求html文件时进行限流的。我们可以理解,这个桶目前没有任何存储水滴的能力,所有到达的不能立即泄漏的请求都会被拒绝。如果我在1秒内发送10个请求,其中前500毫秒1个,后500毫秒9个,那么只有前500毫秒的请求和后500毫秒的第一个请求会响应,其余的请求将被拒绝。

图片

2.2.处理突发流量

上述配置保证了nginx以固定的速度(2r/s)提供服务,但是这种情况不适合突发流量的情况。我们希望尽可能缓存请求并处理它们。这时候我们需要增加burst参数:

limit_req_zone $binary_remote_addr znotallow=test:10m rate=2r/s; server { location / { limit_req znotallow=test burst=5; } }

burst表示超过设定的访问速率后可以处理的额外请求数。当rate=2r/s时,表示每500ms可以处理一个请求。当burst=5时,如果同时有10个请求到达,nginx会处理第一个请求,剩下的9个请求中的5个会放入队列,剩下的4个请求会直接被拒绝。然后每隔500ms从队列中获取一个请求进行处理。如果后面有更多的请求进来,如果队列中的请求数量超过5,就会被拒绝。如果队列中的请求数小于5,则将其添加到队列中等待。我们可以理解为当前的水桶可以存放5滴水:

图片

配置burst后,虽然所有同时到达的请求都不会被拒绝,但仍然需要等待500ms的处理时间。放入桶中的第五个请求需要等待 500ms * 4 才能处理。等待时间越长,就意味着用户的流失。在很多情况下,这个等待时间是不可接受的。此时我们需要添加参数并与burst一起使用。

limit_req_zone $binary_remote_addr znotallow=test:10m rate=2r/s; server { location / { limit_req znotallow=test burst=5 nodelay; } }

表示没有延迟。设置后,第一个到达的请求以及队列中的请求都会立即处理,不会有等待的请求。

图片

需要注意的是,虽然队列中的5个请求是立即处理的,但队列中的位置仍然以500ms的速度顺序释放。接下来的四个请求仍然被拒绝,从长远来看这不会增加吞吐量的上限。长期吞吐量的上限由设定的速率决定。

2.3.设置白名单

如果遇到不需要限流的情况,比如进行压力测试等测试,可以通过配置白名单的方式取消限流设置。白名单需要 nginx 和模块。

geo $limit { default 1; 10.0.0.0/8 0; 192.168.0.0/24 0; } map $limit $limit_key { 0 ""; 1 $binary_remote_addr; } limit_req_zone $limit_key znotallow=mylimit:10m rate=2r/s;

geo指令可以根据IP创建变量$limit。 $limit默认值为1,如果匹配到下面的IP,则返回对应的值(这里返回0)。

然后使用map命令将$limit的值映射到$:如果在白名单中,$为空字符串,如果不在白名单中,则为$。当指令的第一个参数为空字符串时,限制不起作用,因此白名单中的 IP 地址(10.0.0.0/8 和 192.168.0.0/24 子网中)不受限制,所有其他 IP 地址都受到限制至2转/秒

2.4.重复

如果在同一指令下配置了多条指令,则将使用这些指令定义的限制。

geo $limit { default 1; 10.0.0.0/8 0; 192.168.0.0/24 0; } map $limit $limit_key { 0 ""; 1 $binary_remote_addr; } limit_req_zone $limit_key znotallow=mylimit:10m rate=2r/s; limit_req_zone $binary_remote_addr znotallow=myLimit2:10m rate=10r/s; server { location ~* \.(html)$ { limit_req znotallow=mylimit burst=5 nodelay; limit_req znotallow=myLimit2 burst=5 nodelay; } }

上面的例子配置了两条规则, 和 。白名单用户虽然不符合规则,但根据规则限制为10r/s。对于不在白名单中的用户,必须同时匹配 和 ,并且两者中最严格的条件 2r/s 才会生效。

3.限制连接数

nginx模块提供了限制连接数的能力,包括两条指令和,以key zone的格式。

limit_conn_zone $binary_remote_addr znotallow=perip:10m; limit_conn_zone $server_name znotallow=perserver:10m; server { location ~* \.(html)$ { limit_conn perip 10; limit_conn perserver 100; } }

需要注意的是,这个连接只有经过后端处理后才被统计。

4. 上传/下载速率限制

主要用于限制用户和服务器之间传输的字节数。最常用的场景可能是下载/上传速度限制。没有单独的模块,但它位于 .同时它的相关指令也比较少,只有这两条指令。

4.1.

server { location / { limit_rate 4k; } }

4.2.

server { location / { limit_rate_after 500k; limit_rate 4k; } }

传输部分数据后允许限速。例如,上述配置中,传输数据的前500k不限速,500k之后限速。比较常见的应用场景包括分段下载限速,对超过指定大小的部分进行速度限制;或者流媒体视频网站一般不会限制首屏速度,以保证用户体验,保证能够尽快下载。加载出来,然后在用户开始观看视频后将带宽限制在合理的范围内,从而减少因客户端网速过快而提前加载过多内容而带来的额外成本。

4.3.

基本原理和用法几乎是一样的。唯一的区别是nginx与后端服务器之间的连接速率是有限的,而nginx与客户端之间的连接速率是有限的。需要注意的是,该命令需要开启才能生效。

#语法: Syntax: proxy_limit_rate rate; Default: proxy_limit_rate 0; Context: http, server, location This directive appeared in version 1.7.7.

4.4.动态限速

一大特点是可以使用变量,也就是说通过与地图指令等结合,可以实现动态限速功能。这里仅进行一些简单的演示。

4.4.1.基于时间的动态限速

这里介绍一下nginx内置的一个ssi模块。该模块有两个有趣的时间变量:$和$,分别对应当前时间和GMT时间。

这里我们使用变量和map指令的组合,用正则表达式来匹配不同的时间段,然后结合map变量将不同的时间段不同的限速结合起来。

map $date_local $limit_rate_time { default 4K; ~(00:|01:|02:|03:|04:|05:|06:|07:).*:.* 16K; ~(08:|12:|13:|18:).*:.* 8K; ~(19:|20:|21:|22:|23:).*:.* 16K; } limit_rate $limit_rate_time

4.2.基于变量的动态限速

某些服务对于不同的用户可能有不同的速度限制。例如VIP用户的速度更快。例如,可以为不同的用户设置以下速度限制。

map $cookie_User $limit_rate_cookie { gold 64K; silver 32K; copper 16K; iron 8K; } limit_rate $limit_rate_cookie

鱼云提供全球范围的云服务器和物理服务器租赁服务,具备强大的DDoS防御功能,确保您业务安全稳定运行,同时提供灵活定制和专业支持以满足多样化需求。
0 阅读:0