NGINX的速率限制(限流)

NGINX 的速率限制(限流)

NGINX最有用但经常被误解和配置错误的功能之一是限流。它允许您限制用户在给定时间段内可以发出的HTTP请求量。

限流可以用于安全目的,例如减慢暴力破解密码的攻击。它可以通过限制请求速率为真实用户的典型值来帮助防御分布式拒绝服务(DDoS)攻击,并且(通过记录日志)可以识别被攻击的URL。更一般地说,它用于保护上游应用服务器免受过多用户请求同时到达而导致的压力过大。

在本博客中,我们将介绍 NGINX 限流的基础知识以及更高级的配置。当然限流在 NGINX Plus 中的工作方式相同。

NGINX限流的工作原理

NGINX 限流使用漏桶算法,该算法广泛用于电信和数据包交换计算机网络,用于在带宽有限时处理突发性。好比一个水桶,水从上面倒入,从下面漏出;如果倒入水的速度超过漏水的速度,水桶就会溢出。在请求处理方面,水代表客户端的请求,桶代表一个队列,请求按照先进先出(FIFO)调度算法等待处理。漏水代表退出缓冲区供服务器处理的请求,溢出代表被丢弃且从未得到服务的请求。

限流基本配置

限流由两个主要指令limit_req_zone和进行配置limit_req,如下例所示:

需要注意的一个点是rate速率是正整数,/s是每秒;/m是每分

limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;server {location /qhyu/ {limit_req zone=mylimit;proxy_pass http://my_upstream;}
}

limit_req_zone指令定义了速率限制的参数,同时limit_req在它出现的上下文中启用速率限制(在示例中,对于 /qhyu/ 的所有请求)。

我用postman做了一个并发测试,除了第一个接口返回200,其他的都被限流了。
在这里插入图片描述

nginx日志如下:

在这里插入图片描述

该limit_req_zone指令通常在http块中定义,使其可在多个上下文中使用。它需要以下三个参数:

  • key-定义应用的请求特征。在示例中,它是nginx变量 $binary_remote_addr,它保存客户端IP地址的二进制表现形式。这意味着我们将每个唯一的IP地址限制为第三个参数定义的请求速率。(我们使用此变量是因为它比客户端 IP 地址的字符串表示占用的空间更少$remote_addr

  • zone-定义用于存储每个IP地址的状态及其访问请求限制URL的频率的共享内存区域。将信息保存在共享内存中意味着它可以在nginx工作进程之间共享。该定义有两部分:由关键字标识的区域名称zone=,以及冒号后面的大小。大约16000个IP地址的状态信息需要1兆字节,因为我们的区域可以存储大约160000个地址。

    如果nginx需要添加新条目时存储空间耗尽,它将删除最旧的条目。如果释放的空间仍不足以容纳新记录,nginx将返回状态码。此外,为了防止内存耗尽,每次nginx创建条目时,它都会删除最多两个在前60s内未使用的条目。503 Service Temporarily Unavailable

  • rate-设置最大请求速率。在示例中,速率不能超过每秒10个请求。nginx实际上以毫秒粒度跟踪请求,因此此限制对应于每 100 毫秒 (ms) 1 个请求。因为我们不允许突发(请参阅下一节),这意味着如果请求在上一个允许的请求之后不到 100 毫秒到达,则该请求将被拒绝。

limit_req_zone指令设置了速率限制和共享内存区域的参数,但它实际上并不限制请求速率。为此,您需要通过在其中包含指令来将限制应用于特定location或块。在示例中,我们对 /qhyu/ 的请求进行速率限制。limit_req

因此,现在每个唯一的 IP 地址限制为每秒 10 次 /qhyu/ 请求 ,或者更准确地说,不能在前一个 URL 的 100 毫秒内对该 URL 发出请求。

处理突发

如果我们在 100 毫秒内收到 2 个请求怎么办?对于第二个请求,NGINX 将状态代码返回503给客户端。一些业务场景下这可能不是我们想要的,因为应用程序本质上往往是突发性的。相反,我们希望缓冲任何多余的请求并及时为它们提供服务。如这个更新的配置所示:

location /qhyu/ {limit_req zone=mylimit burst=20;proxy_pass http://my_upstream;
}

该burst参数定义客户端可以发出超出区域指定速率的请求数量(对于我们的示例mylimit区域,速率限制为每秒 10 个请求,或每 100 毫秒 1 个请求)。比上一个请求晚 100 毫秒到达的请求将被放入队列中,这里我们将队列大小设置为 20。

这意味着如果 21 个请求同时从给定的 IP 地址到达,NGINX 会立即将第一个请求转发到上游服务器组,并将剩余的 20 个放入队列中。然后,它每 100 毫秒转发一个排队请求,503只有当传入请求使排队请求数量超过 20 时才返回客户端。

排队无延迟

这种配置burst可以使流量流畅,但不太实用,因为它会使您的网站显得很慢。在我们的示例中,队列中的第 20 个数据包等待 2 秒才能转发,此时对其的响应可能不再对客户端有用。为了解决这种情况,将nodelay参数与参数burst一起添加:

location /qhyu/ {limit_req zone=mylimit burst=20 nodelay;proxy_pass http://my_upstream;
}

使用该nodelay参数,NGINX 仍然根据该burst参数在队列中分配插槽并施加配置的速率限制,但不会间隔转发排队的请求。相反,当请求“太快”到达时,NGINX 会立即转发它,只要队列中有可用的槽位。它将该插槽标记为“已占用”,并且在经过适当的时间(在我们的示例中,100 毫秒后)之前不会将其释放以供其他请求使用。

与之前一样,假设 20 槽队列为空,并且有 21 个请求同时从给定 IP 地址到达。NGINX 立即转发所有 21 个请求,并将队列中的 20 个槽标记为已占用,然后每 100 毫秒释放 1 个槽。(如果有 25 个请求,NGINX 将立即转发其中 21 个,将 20 个槽标记为已占用,并拒绝 4 个状态为503的请求。)

现在假设第一组请求转发后 101 毫秒,另外 20 个请求同时到达。队列中只有 1 个槽被释放,因此 NGINX 转发 1 个请求并拒绝其他 19 个状态为 的请求 503。相反,如果在 20 个新请求到达之前已经过去了 501 毫秒,则有 5 个插槽空闲,因此 NGINX 会立即转发 5 个请求并拒绝 15 个。

效果相当于每秒 10 个请求的速率限制。nodelay如果您想要施加速率限制而不限制请求之间允许的间距,则该选项非常有用。

注意: 对于大多数部署,我们建议 在指令limit_req中包含burstnodelay 参数。

两阶段限速

综合上述内容,我们可以将nginx配置为允许突发请求以适应典型的web浏览器请求模式,然后将额外的过多请求限制到某个点,通过阈值拒绝其他过多的请求。使用limit_req指令的delay参数启用两级速率限制。

为了说明两阶段速率限制,这里我们配置 NGINX 通过施加每秒 5 个请求 (r/s) 的速率限制来保护网站。该网站通常每页有 4-6 个资源,但永远不会超过 12 个资源。该配置允许突发最多 12 个请求,其中前 8 个请求将立即得到处理。在 8 个过多请求后添加延迟以强制执行 5 r/s 限制。超过 12 次请求后,任何进一步的请求都会被拒绝。

limit_req_zone $binary_remote_addr zone=ip:10m rate=5r/s;server {listen 80;location / {limit_req zone=ip burst=12 delay=8;proxy_pass http://website;}
}

delay参数定义了在突发大小内限制(延迟)过多请求以符合定义的速率限制的点。完成此配置后,以 8 r/s 发出连续请求流的客户端会经历以下行为。
在这里插入图片描述

前 8 个请求( delay的值)由 NGINX无延迟地代理。接下来的 4 个请求 ( burst - delay) 将被延迟,以便不超过定义的 5 r/s 速率。接下来的 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 zone=req_zone:10m rate=5r/s;server {location / {limit_req zone=req_zone burst=10 nodelay;# ...}
}

此示例同时使用了geomap指令

  • 如果$limit0$limit_key设置为空字符串
  • 如果$limit1$limit_key则设置为二进制格式的客户端 IP 地址

将两者放在一起,$limit_key对于列入白名单的 IP 地址,设置为空字符串,否则设置为客户端的 IP 地址。当目录的第一个参数limit_req_zone(密钥)为空字符串时,不应用限制,因此列入白名单的 IP 地址(在 10.0.0.0/8 和 192.168.0.0/24 子网中)不受限制。所有其他 IP 地址限制为每秒 5 个请求。

limit_req指令将限制应用于 / 位置,并允许突发超过配置限制的最多 10 个数据包,且转发无延迟

在一个位置中包含多个limit_req指令

可以limit_req在一个位置包含多个指令。应用与给定请求匹配的所有限制,这意味着使用最严格的限制。例如,如果多个指令施加延迟,则使用最长的延迟。同样,如果这是任何指令的效果,则请求将被拒绝,即使其他指令允许它们通过。

扩展前面的示例,我们可以对白名单上的 IP 地址应用速率限制:

http {# ...limit_req_zone $limit_key zone=req_zone:10m rate=5r/s;limit_req_zone $binary_remote_addr zone=req_zone_wl:10m rate=15r/s;server {# ...location / {limit_req zone=req_zone burst=10 nodelay;limit_req zone=req_zone_wl burst=20 nodelay;# ...}}
}

允许名单上的 IP 地址与第一个速率限制 ( req_zone )不匹配,但与第二个速率限制 ( req_zone_wl )匹配,因此限制为每秒 15 个请求。不在允许列表中的 IP 地址与两个速率限制均匹配,因此选择限制性更强的速率限制:每秒 5 个请求。

配置相关功能

记录

日志条目中的字段包括:

  • 2023/08/25 04:20:00 – 写入日志条目的日期和时间
  • [error] – 严重程度
  • 120315#0 – NGINX工作线程的进程ID和线程ID,用符号#分隔
  • *32086 – 速率受限的代理连接的 ID
  • limiting requests – 指示日志条目记录速率限制
  • excess – 此请求所代表的配置速率上的每毫秒请求数
  • zone – 定义施加速率限制的区域
  • client – 发出请求的客户端的 IP 地址
  • server – 服务器的 IP 地址或主机名
  • request – 客户端发出的实际 HTTP 请求
  • hostHostHTTP 标头的值

默认情况下,NGINX 在该级别记录拒绝的请求,如上例error所示。[error](默认情况下,它会在低一级记录延迟请求warn。)要更改日志记录级别,请使用该limit_req_log_level指令。这里我们将拒绝的请求设置为日志级别warn

location /qhyu/ {limit_req zone=mylimit burst=20 nodelay;limit_req_log_level warn;proxy_pass http://my_upstream;
}

发送给客户端的错误代码

默认情况下,当客户端超出其速率限制时,NGINX 会返回状态代码503 ( Service Temporarily Unavailable) 。使用limit_req_status指令设置不同的状态代码(444在本例中):

location /login/ {limit_req zone=mylimit burst=20 nodelay;limit_req_status 444;
}

拒绝对特定位置的所有请求

如果您想拒绝对特定 URL 的所有请求,而不仅仅是限制它们,请location为其配置一个块并包含以下指令:

location /foo.php {deny all;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/104834.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

动物体外受精手术VR模拟仿真培训系统保证学生及标本的安全

奶牛是养殖业主要的资源,因此保证奶牛的健康对养殖业的成功和可持续发展具有重要已用,奶牛有一些常见易发病,一旦处理不当,对奶牛业都会造成较大的经济损失,传统的奶牛手术培训实操难度大、风险高且花费大,…

打家劫舍00

题目链接 打家劫舍 题目描述 注意点 如果两间相邻的房屋在同一晚上被小偷闯入&#xff0c;系统会自动报警0 < nums[i] < 400 解答思路 最初想的是使用深度优先遍历&#xff0c;到达任意一个位置时&#xff0c;小偷想要偷窃最高金额&#xff0c;一定要选择后面第2个房…

WEB APIs day5

一、window对象 BOM属于window对象 1.BOM&#xff08;浏览器对象模型&#xff09; bom里面包含着dom,只不过bom我们平时用得比较少&#xff0c;我们经常使用的是dom操作&#xff0c;因为我们页面中的这些标签都是在dom中取的&#xff0c;所以我们操作dom多一点。 window对象…

[Go版]算法通关村第十三关青铜——数字数学问题之统计问题、溢出问题、进制问题

这里写自定义目录标题 数字统计专题题目&#xff1a;数组元素积的符号思路分析&#xff1a;无需真计算&#xff0c;只需判断负数个数是奇是偶复杂度&#xff1a;时间复杂度 O ( n ) O(n) O(n)、空间复杂度 O ( 1 ) O(1) O(1)Go代码 题目&#xff1a;阶乘尾数0的个数思路分析&am…

CPU、MCU、MPU、SOC、SOCPC、概念解释之在嵌入式领域常听到的名词含义

CPU、MCU、MPU、SOC等几个在嵌入式领域学习过程中会涉及到的几个名词。我们来学习一下&#xff0c;资料从网上搜集的&#xff0c;有错的地方可以指出。。。 CPU、MCU、MPU、SOC、SOCPC、 1. CPU2. MPU3.MCUMPU和MCU的区别&#xff1a;4.SOC5. SoPC 1. CPU CPU&#xff0c;即中…

iis站点备份以及端口号查找

文件地址 %windir%\system32\inetsrv\config

iOS 17 及 Xcode 15.0 Beta7 问题记录

1、iOS 17 真机调试问题 iOS 17之后&#xff0c;真机调试Beta版本必须使用Beta版本的Xcode来调试&#xff0c;用以前复制DeviceSupport 方式无法调试&#xff0c;新的Beta版本Xcode中&#xff0c;已经不包含 iOS 17目录。如下图&#xff1a; 解决方案&#xff1a; 1&#x…

Nodejs-nrm:快速切换npm源 / npm官方源和其他自定义源之间切换

一、理解 Nodejs nrm Nodejs nrm 是一个管理 npm 源的工具。由于 npm 在国内的速度较慢&#xff0c;很多开发者会使用淘宝的 npm 镜像源&#xff0c;但是也会遇到一些问题&#xff0c;例如某些包在淘宝镜像源中不存在&#xff0c;或者淘宝镜像源本身也会有问题。 Nodejs nrm …

SpringCloud教程 | 第六篇: 分布式配置中心(Spring Cloud Config)

在上一篇文章讲述zuul的时候&#xff0c;已经提到过&#xff0c;使用配置服务来保存各个服务的配置文件。它就是Spring Cloud Config。 一、简介 在分布式系统中&#xff0c;由于服务数量巨多&#xff0c;为了方便服务配置文件统一管理&#xff0c;实时更新&#xff0c;所以需…

根据源码,模拟实现 RabbitMQ - 虚拟主机设计(5)

目录 一、虚拟主机设计 1.1、需求分析 1.1.1、核心 API 1.1.2、虚拟主机的是用来干什么的&#xff1f; 1.1.3、如何表示 交换机和虚拟主机 之间的从属关系&#xff1f; 二、实现 VirtualHost 类 2.1、属性 2.2、锁对象 2.3、公开实例 2.4、虚拟主机构造方法 2.5、交…

语言、习俗与成功:海外网红营销的文化敏感性

随着全球互联网的普及和社交媒体的兴起&#xff0c;海外网红营销正成为越来越多品牌和企业的选择。然而&#xff0c;要在海外市场取得成功&#xff0c;单纯的翻译内容和机械式的推广已经远远不够&#xff0c;文化敏感性成为海外网红营销的关键。本文Nox聚星将深入探讨语言、习俗…

算法与数据结构(十)--图的入门

一.图的定义和分类 定义&#xff1a;图是由一组顶点和一组能够将两个顶点连接的边组成的。 特殊的图&#xff1a; 1.自环&#xff1a;即一条连接一个顶点和其自身的边; 2.平行边&#xff1a;连接同一对顶点的两条边&#xff1b; 图的分类&#xff1a; 按照连接两个顶点的边的…

Linux 压缩解压(归档管理):tar命令

计算机中的数据经常需要备份&#xff0c;tar是Unix/Linux中最常用的备份工具&#xff0c;此命令可以把一系列文件归档到一个大文件中&#xff0c;也可以把档案文件解开以恢复数据。 tar使用格式 tar [参数] 打包文件名 文件 tar命令很特殊&#xff0c;其参数前面可以使用“-”&…

java八股文面试[java基础]——异常

自定义异常&#xff1a; 异常Exception 是指程序运行时&#xff0c; 由于输入错误、网络、程序逻辑等原因导致运行时出现的问题。出现异常时&#xff0c;程序会暂时中断执行&#xff0c;并根据产生异常的原因&#xff0c;创建对应异常类型的异常对象&#xff0c;并抛出给JVM捕…

七大排序算法详解

1.概念 1.排序的稳定性 常见的稳定的排序有三种&#xff1a;直接插入排序&#xff0c;冒泡排序&#xff0c;归并排序 对于一组数据元素排列&#xff0c;使用某种排序算法对它进行排序&#xff0c;若相同数据之间的前后位置排序后和未排序之前是相同的&#xff0c;我们就成这种…

数学建模(五)非线性规划

课程推荐&#xff1a; 13 非线性规划算法在数学建模中的应用与编程实现_哔哩哔哩_bilibili 一、非线性规划模型 如果目标函数或约束条件中包含非线性函数&#xff0c;就称这种规划问题为非线性规划问题。一般说来&#xff0c;解非线性规划要比解线性规划问题困难得多。而且&am…

cs231n assignment3 q4 Generative Adversarial Networks

文章目录 嫌墨迹直接看代码Q4 :Generative Adversarial Networkssample_noise题面解析代码输出 discriminator题面解析代码输出 generator题面解析代码输出 discriminator_loss题面解析代码输出 generator_loss题面解析代码 get_optimizer题面解析代码输出 ls_discriminator_lo…

c语言函数指针和指针函数的区别,以及回调函数的使用。

函数指针是什么&#xff0c;函数指针本质也是指针&#xff0c;不过是指向函数的指针&#xff0c;存储的是函数的地址。 指针函数是什么,指针函数其实就是返回值是指针的函数&#xff0c;本质是函数。 函数指针是如何定义的呢&#xff0c;如下 void (*pfun)(int a,int b) 这…

服务器的介绍

1.服务器概述 1.1 服务器的基本概念 服务器是计算机的一种&#xff0c;是网络中为客户端计算机提供各种服务的高性能计算机&#xff1b; 服务器在网络操作系统的控制下&#xff0c;将与其相连的硬盘、磁带、 打印机及昂贵的专用通讯设备提供给网络上的客户站点共享&#xf…

2023年国赛 高教社杯数学建模思路 - 案例:最短时间生产计划安排

文章目录 0 赛题思路1 模型描述2 实例2.1 问题描述2.2 数学模型2.2.1 模型流程2.2.2 符号约定2.2.3 求解模型 2.3 相关代码2.4 模型求解结果 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 最短时…