精通Nginx配置,实现高效精准的流量限制策略
时间:2026-09-24 16:14 来源:未知 人气:
1、概述
限流(Rate Limitting)是服务降级的一种方式,通过限制系统的输入和输出流量以达到保护系统的目的。
比如我们的网站暴露在公网环境中,除了用户的正常访问,网络爬虫、恶意攻击或者大促等突发流量都可能都会对系统造成压力,如果这种压力超出了服务器的处理能力,会造成响应过慢甚至系统崩溃的问题。
因此,当并发请求数过大时,我们通过限制一部分请求(比如限制同一IP的频繁请求)来保证服务器可以正确响应另一部分的请求。
nginx 提供了两种限流方式,一种是限制请求速率,一种是限制连接数量。
另外还提供了对下载/上传速度的限制。
2、限制请求速率
nginx 的 ngx_http_limit_req_module 模块提供限制请求处理速率的能力,使用了漏桶算法(leaky bucket algorithm)。我们可以想像有一只上面进水、下面匀速出水的桶,如果桶里面有水,那刚进去的水就要存在桶里等下面的水流完之后才会流出,如果进水的速度大于水流出的速度,桶里的水就会满,这时水就不会进到桶里,而是直接从桶的上面溢出。
对应到处理网络请求,水代表从客户端来的请求,而桶代表一个队列,请求在该队列中依据先进先出(FIFO)算法等待被处理。漏的水代表请求离开缓冲区并被服务器处理,溢出代表了请求被丢弃并且永不被服务。
图片
2.1、正常限流
nginx 中有两个主要的指令可以用来配置限流:limit_req_zone和limit_req。
下面是一个最简单的限流的例子:
limit_req_zone $binary_remote_addr znotallow=test:10m rate=2r/s;
server {
location / {
limit_req znotallow=test;
}
}
imit_req_zone 用于设置限流和共享内存区域的参数,格式为:limit_req_zone key zone rate。
- key:定义限流对象,$binary_remote_addr是 nginx 中的变量,表示基于remote_addr(客户端IP) 来做限流,binary_是二进制存储。使用$binary_remote_addr而不是$remote_addr是因为二进制存储可以压缩内存占用量。$remote_addr变量的大小从7到15个字节不等,而$binary_remote_addr变量的大小对于 IPv4 始终为4个字节,对于 IPv6 地址则为16个字节。
- zone:定义共享内存区来存储访问信息,访问信息包括每个 IP 地址状态和访问受限请求 URL 的频率等。zone 的定义又分为两个部分:由 znotallow= 关键字标识的区域名称,以及冒号后面的区域大小。test:10m 表示一个大小为10M,名字为 test 的内存区域。1M 能存储16000个 IP 地址的访问信息,test 大概可以存储约160000个地址。nginx 创建新记录的时候,会移除前60秒内没有被使用的记录,如果释放的空间还是存储不了新的记录,会返回503的状态码。