目录

  • 参考
  • 前言
  • limit_conn_zone 模块
    • 配置
    • 测试
      • 测试小文件
      • 测试大文件
    • 总结
  • limit_request 模块
    • 配置
    • 测试
      • 测试1 - 不加 burst 和 不加 nodelay
      • 测试2 - 加 burst 和 不加 nodelay
      • 测试3 - 加 burst 和 加 nodelay
    • 总结
  • limit_rate 根据 ip 限制流量
    • 配置
    • 测试

参考

Nginx如何实现并发连接与IP流量限速功能

前言

本文针对 Nginx 的三个模块进行配置,并证实各自的功能特点:

(1)limit_conn_zone 模块 - 限制统一 IP 地址并发连接数;

(2)limit_request 模块 - 限制同一 IP 某段时间的访问量;

(3)core 模块提供 - limit_rate 限制同一 IP 流量。

在 Nginx 中 以 LIMIT 开头的 配置项,都是做 限制 功能,以上三个功能都是 Nginx 编译后就有的功能,属于内置模块。

limit_conn_zone 模块

通过 limit_zone 模块来达到限制用户的连接数的目的,即限制同一用户 IP 地址的并发连接数。

配置


limit_conn_zone $binary_remote_addr zone=test:10m;
server {listen       88;server_name  127.0.0.1;# 测试限制location /limit/{limit_conn test 1;alias   D:/test/;sendfile on;autoindex on;  # 开启目录文件列表autoindex_exact_size on;  # 显示出文件的确切大小,单   位是bytesautoindex_localtime on;  # 显示的文件时间为文件的服务器时间charset utf-8,gbk;  # 避免中文乱码}
}

指令名称:limit_conn_zone(nginx 1.18以后用 limit_conn_zone 取代了 limit_conn)
语法:limit_conn_zone key zone=name:size;
默认:no
区域:http
功能:该指令定义一个 zone,该 zone 存储会话的状态。
例如:上面的例子中,$binary_remote_addr 是 获取客户端ip地址的变量,长度为 4 字节,会话信息的长度为 32 字节。zone=test:10m:表示生成一个 10M ,名字为 test的内存区域,用来存储访问的频次信息

指令名称:limit_conn
语法:limit_conn zone number;
默认:no
区域:http、server、location
功能:该指令用于为一个会话设定最大并发连接数。如果并发请求超过这个限制,那么将返回预定错误(limit_conn_status )

指令名称:limit_conn_status
语法:limit_conn_status code;
默认:limit_conn_status 503;
区域:http、server、location
功能:设置要返回的状态码以响应被拒绝的请求。

指令名称:limit_conn_log_level
语法:limit_conn_log_level info | notice | warn | error
默认值:error
区域:http、server、location
功能:该指令用于设置日志的错误级别,当达到连接限制时,将会产生错误日志。

上面的配置示例中,没有显式配置 limit_conn_status 、limit_conn_log_level ,如果没有配置,则启用它们的默认值。

测试

测试小文件

http://127.0.0.1:88/limit/ext.js
使用jmeter模拟1秒钟内发出10个请求

测试结果

测试大文件

http://127.0.0.1:88/limit/113m.zip,大小113MB

总结

通过上面两次测试结果来看:第一次测试结果,配置的并发请求为 1 的限制貌似没有起到作用。第二次测试结果,比较符合配置项的限制规则。而这两次测试唯一的不同就是:数据文件大小不同。

这里只能猜想:对于较小的文件或页面,在千兆网络的环境里,单个时刻请求数据的速度很快,并没有造成多个连接同时并发的情况产生,而对于较大的页面或文件来说,文件正在传输的时候处于 ESTABLISHED连接时间长,非常容易形成并发的效果,并发就会触发限制规则。

limit_request 模块

使用 ngx_http_limit_req_module 模块可以 限制某一 IP 在一段时间内对服务器发起请求的连接数,该模块为内置模块。

配置

limit_req_zone $binary_remote_addr zone=addr:10m rate=1r/s;
server {listen       88;server_name  127.0.0.1;# 测试请求连接数location /limit_req/{limit_req zone=addr burst=5 nodelay;alias   D:/test/;sendfile on;autoindex on;  # 开启目录文件列表autoindex_exact_size on;  # 显示出文件的确切大小,单位是bytesautoindex_localtime on;  # 显示的文件时间为文件的服务器时间charset utf-8,gbk;  # 避免中文乱码}
}

指令名称:limit_req_zone
语法:limit_req_zone key zone=name:size rate= number r/s
默认值:no
区域:http
使用示例:limit_req_zone $binary_remote_addr zone=addr:10m rate=1r/s
对于上面的示例:
$binary_remote_addr :表示通过remote_addr 这个标识用来做限制.
zone=addr:10m:表示生成一个 10M ,名字为 addr 的内存区域,用来存储访问的频次信息
rate=1r/s:表示允许相同标识的客户端的访问频次,这里限制的是每秒1次,即每秒只处理一个请求,还可以有比如 30r/m , 即限制每 2秒 访问一次,即每 2秒 才处理一个请求。

指令名称:limit_req
语法:limit_req zone=name [burst=number] [nodelay | delay=number];
默认:no
区域:http、server、location
使用示例:limit_req zone=zone burst=5 nodelay;
zone=zone:设置使用哪个配置名来做限制,与上面 limit_req_zone 里的 name 对应
burst=5 :这个配置的意思是设置一个大小为5的缓冲区,当有大量请求过来时,超过访问频次限制 rate=1r/s 的请求可以先放到这个缓冲区内等待,但是这个缓冲区只有5个位置,超过这个缓冲区的请求直接报503并返回。
nodelay:无延迟队列(Queueing with No Delay),如果设置,会在瞬间提供处理(rate+burst)个请求的能力,请求超时(rat+burst)的时候直接返回503,永远不存在请求需要等待的情况。如果没有设置,则所有请求会依次等待排队;

上面的示例内容没有显式写明 limit_req_status 、limit_req_log_level 两个配置项,所以采用默认值。

burst 为啥意思,这里可以理解为连接等待队列长度。
这里就使用到了 ‘漏斗算法(Leaky Bucket)’,该算法有两种处理方式 Traffic Shaping 和 Traffic Policing
在桶满了之后,常用的两种处理方式为:

  • 暂时拦截住上方水的向下流动,等待桶中的一部分水漏走后,再放行上方水;
  • 溢出的上方水直接抛弃。

举个栗子:

比如上面的配置: rate=1r/s burst=5

第一秒来了6个请求 - 1 个处理 - 5个等待;

第二秒来了2个请求 - 1个处理 - 5个等待 - 1 个丢弃;

上面总共8个请求,时间2秒,2秒处理了2个请求,还剩6个,但是缓冲队列只能存放5个请求,剩下1个丢弃。

或者

第一秒:来了10个请求 - 1个处理 - 5个等待 - 4个丢弃

就是按照这样的方式来进行计算的,也就是说,上面的配置,每秒最多只能保持 6 个请求,但是每秒最多只能处理 1 个请求。

测试

本模块测试分为三种不同的方式进行测试验证:

  • (1)不加 burst 和 不加 nodelay

  • (2)加 burst 和 不加 nodelay

  • (3)加burtst 和 加 nodelay

测试1 - 不加 burst 和 不加 nodelay

客户端主机: 通过 ab 命令模拟并发访问:

[root@client ~]#ab -n 10 -c 10 http://127.0.0.1:88/limit_req/ai.key

通过测试后的结果,10 个并发连接,只有 1 个成功,剩余 9 个都返回 非200 状态,查看 Nginx 日志:

1秒钟的10次并发请求,只有 1 个返回 200 ,剩余全是 503 请求被拒绝。
不加 burst 和 不加 nodelay 的情况下,rate=1r/s 1 秒钟只能处理 1 个请求,剩余的所有请求都会直接返回 503

测试2 - 加 burst 和 不加 nodelay

nodelay:无延迟队列(Queueing with No Delay)如果设置,会在瞬间提供处理(rate+burst)个请求的能力,不会把它们放入burst队列中,而是直接将它们转发给upstream服务器,同时标记队列中的这5个插槽(slot)为已使用,请求超过(rat+burst)的时候直接返回503,永远不存在请求需要等待的情况。如果没有设置,则所有请求会依次缓存到burst中等待排队;超过burst的返回503。


处理了10个连接请求,其中失败了 4 个,成功了 6个。

在本次测试中,使用 burst = 5 建立了一个可以存放 5 个并发连接的缓冲区。根据上面的 漏斗算法 来进行分析:

第一秒:10个连接并发请求,1个处理 5个等待,4个丢弃;

第二秒:1个处理 4 个等待;

第三秒:1个处理 3 个等待;

第四秒:1个处理 2 个等待;

第五秒:1个处理 1 个等待;

第六秒:1个处理 完毕。

通过上面的推算,一共需要 6 秒才能处理完所有的请求,查看 Nginx 日志,验证推算是不是正确

通过日志,可以看出,第一秒处理了 1 个请求,拒绝了 4 个连接,剩下的请求分别是每秒 1个连接请求的处理。

规则:rate=1r/s 、burst=5

一次来了 10 个连接并发请求,处理 1 个,缓存 5 个后续 1 秒一个的处理,其他的全部丢弃。

加 burst 和 不加 nodelay 的情况下,rate=1r/s burst=5 处理 1 个,缓存 5 个后续 1 秒一个的处理,其他的全部丢弃。

测试3 - 加 burst 和 加 nodelay

# 测试请求连接数location /limit_req/{#limit_req zone=addr;#limit_req zone=addr burst=5;limit_req zone=addr burst=5 nodelay;

客户端主机:client 通过 ab 命令模拟并发访问:


[root@client ~]#ab -n 10 -c 10 http://127.0.0.1:88/limit_req/ai.key


10 个并发连接请求,很快就直接返回了,其中 4 个非200错误, 6 个成功。查看 Nginx 日志:

这次的测试结果,同一秒钟,处理了 rate+burst 个请求,其他的全部返回连接请求拒绝。

总结

通过测试的三种情况,返回了不同的结果,因此有必要详细说明:

  • (1)不加 burst 和 不加 nodelay 的情况

按照 rate 设定的规则,严格执行。

例如:rate=1r/s ,则1秒只处理1个请求,其他的全部返回连接503

  • (2)加 burst 和 不加 nodelay 的情况

首先按照 rate 规则处理,并且缓存 burst 个连接,剩余的全部返回503.

后续缓存的 burst 按照 rate 规则进行处理。
缺点:上面的方法虽然使得请求的流量变得**“均匀平滑”**,但是确很大程度上增加了响应时间,排在队列越后面的请求的等待时间越长,这就导致了它们的响应时间平白无故地增加了许多,过长的响应时间甚至可能会导致客户端认为请求异常或者直接导致请求超时

  • (3)加 burst 和 nodelay 的情况

第一次处理 rate+burst 个连接请求,剩余的请求全部返回 503。,只不过没有了前面的“均匀平滑”*的特性,但是却有效降低了响应时间。**因此如果我们需要在不限制每个请求之间的时间间隔的情况下限制请求速率,可以考虑使用nodelay参数。

limit_rate 根据 ip 限制流量

对于提供下载的网站,肯定是要进行流量控制的。Nginx 通过 core模块的 limit_rate 等指令可以做到限流的目的。

配置

     # 测试请求连接数location /limit_rate/{limit_rate_after 3m;limit_rate 512k;alias   D:/test/;sendfile on;autoindex on;  # 开启目录文件列表autoindex_exact_size on;  # 显示出文件的确切大小,单位是bytesautoindex_localtime on;  # 显示的文件时间为文件的服务器时间charset utf-8,gbk;  # 避免中文乱码}

指令名称:limit_rate

语法:limit_rate speed;

默认值:no

使用环境:http、server、location

示例: limit_rate 512k;

功能:该指令用于指定向客户端传输数据的速度,速度的单位是每秒传输的字节数。注意:该限制只是针对一个连接的设定,也就是说,如果同时有2个连接,那么它的速度将会是该指令设置的两倍。

指令名称:limit_rate_after

语法:limit_rate_after size;

默认值:limit_rate_after 1m;

使用环境:http、server、location

示例:limit_rate_after 3m;

功能:以最大的速度下载 size大小后,在进行 limit_rate speed 限速,例如:limit_rate_after 3m
解释为:以最大的速度下载3m后,再进行限速。

测试

测试前疑问:对于这个模块是通过什么来进行限速的呢? 上面的两个模块都有声明 $binary_remote_addr 远端ip地址进行操作的,而 limit_rate 什么都没规定。针对这个问题,做以下测试:

curl 127.0.0.1:88/limit_rate/test.zip

这里使用的是千兆网络,超过3m,速度被限制在512K 以下。这是一个连接下载,如果同时开启多个终端,都进行下载呢?

因为 limit_rate 并没有声明以什么条件作为限制,所以同一个ip无论发起多少个请求,每个请求都会是 512k 下载。在迅雷等多种下载软件中,使用多线程的方式下载同一个文件,这个速度就翻倍了。 那这个限速就形同虚设。

因此,如果要进行限速,可以和 limit_conn_zone 模块配合进行使用。配置如下:


limit_conn_zone $binary_remote_addr zone=test:10m;
server {listen       88;server_name  127.0.0.1;# 测试限制location /limit_rate/{limit_conn test 1;limit_rate_after 3m;limit_rate 512k;alias   D:/test/;sendfile on;autoindex on;  # 开启目录文件列表autoindex_exact_size on;  # 显示出文件的确切大小,单  位是bytesautoindex_localtime on;  # 显示的文件时间为文件的服务器时间charset utf-8,gbk;  # 避免中文乱码}
}

同一时刻,只有一个连接请求。

再进行同主机多线程下载:当再次发起第二个连接的时候,服务器就直接返回连接拒绝 503,这样就达到了限速的目的。

nginx实现并发连接与IP流量限速功能相关推荐

  1. Nginx查看并发连接

    Nginx查看并发连接 通过界面查看 通过界面查看通过web界面查看时Nginx需要开启status模块,也就是安装Nginx时加上 --with-http_stub_status_module 然后 ...

  2. Linux FTP并发连接及带宽限制

    问题 沿用练习一,通过调整FTP服务端配置,实现以下目标: 最多允许100个FTP并发连接 每个IP地址最多允许2个并发连接 匿名访问时,将速度限制为 50KB/s 用户登录访问时,将速度限制为 50 ...

  3. TL-WR541G/542G路由器设置电信宽带上网限速功能

    购买TL-WR541G路由器原由 家里使用电信2M宽带,多接邻居一台电脑来共享上网,每天晚上下班回家,上网速度都非常慢,原来邻居天天在线看电影这些,我原来的路由器没有ADSL上网限速功能,于是下载P2 ...

  4. 【控制篇 / 流量】(5.2) ❀ 03. 对每个 IP 进行限速 ❀ FortiGate 防火墙

    [简介]在大型企业中人员比较多而带宽又不太够的情况下,需要对上网进行限速,但是领导的速你不能限吧,在限制员工上网的速度同时又要保证领导上网的速度,这就需要用到针对每个IP限速了.   地址对象 我们需 ...

  5. linux 限制单个ip流量,centos 的單ip流量控制-CentOS下利用iptables限速及限制每IP連接數...

    第一步:建立adsl連接,在系統設置--網絡設置處有.在圖形界面下很容易搞定. 第二步:打開IP轉發和偽裝(也就是路由與NAT) 1.作為根用戶打開/etc/sysconfig/network文件,在 ...

  6. 单机千万并发连接实战(修订版)

    c10k,c100k,c1000k等问题大家都已经司空见惯,那么10m(千万)并发连接呢?今天就来一起挑战一下. 下面我们使用handy库自带的例子程序,来跑出一个单机千万并发连接的实例,先上操作步骤 ...

  7. lvs增加并发连接,解决因为哈希表过小导致软中断过高问题

    LVS,一个N久前就在使用的东西,目前来说配置什么的也没什么问题.只是个人觉得随着业务的上涨和流量的增加,它的连接数必然也会增长,所以在配置的时候就想直接把它改大.       在安装好后(Cento ...

  8. 千万并发连接下,如何保障网络性能

    过去几十年互联网呈爆发式的增长,内容的丰富以及层出不穷的DDoS攻击等,对网络性能提出了极大的挑战,也同样促进了网络基础设施的快速发展.运营商的带宽越来越大,CPU/网卡等硬件的性能也会越来越强.但在 ...

  9. Nginx高并发系统内核优化

    Nginx高并发系统内核优化 Socket优化 Nginx 系统内核 文件优化 Nginx 系统内核 配置文件优化 Nginx配置文件 内核配置文件 PHP7配置文件 PHP-FPM配置文件 php- ...

最新文章

  1. IDEA高级用法:集成JIRA、UML类图插件、SSH、FTP、Database管理...
  2. linux 32位redis安装,CentOS 5.5 32位上安装Redis 2.6报错解决
  3. Netty学习笔记(一)
  4. Docker的私有镜像仓库搭建
  5. 0.2 控制系统的状态空间表示法
  6. FTPClient登录慢的问题
  7. python怎样分析文献综述怎么写_怎么写文献综述?
  8. LeetCode 599. 两个列表的最小索引总和(哈希map)
  9. windows7电脑删除文件特别慢的解决方法
  10. 自动驾驶:蛇形曲线跟踪(Stanley Model)
  11. java中使用配置文件_Java中使用Properties配置文件的简单方法
  12. 电视开机还要看广告?超80%的人一秒都忍不了
  13. python win32 窗口截图
  14. 小程序使用wxs处理手机号
  15. 在官网下载linux版本的tomcat
  16. linux c实现键盘模拟,C++模拟键盘按键的实例
  17. 关于EI计算机视觉投稿
  18. SpringBoot配置与应用 SpringBoot与(Spring和springmvc的区别)
  19. mysql脏读,幻读,不可重复读以及间隙所解决幻读
  20. 爬取豆瓣前250电影数据

热门文章

  1. 你所不知道的秘密,戴玉有什么好处?
  2. 满了18岁你就要这样
  3. 谁会嫌钱多啊,最适合学生党的Python兼职攻略以及接私活经验
  4. 晒晒我这两年的私活单,业余时间月入6k
  5. 小龟机器人Python开发手册——舵机控制
  6. Typescript面向对象---上篇
  7. 中国餐饮行业报告,中国传统餐厅成本结构分析,净利润占比20%
  8. 【信号与系统】2. 信号的基本运算
  9. Android噪音检测系统
  10. 大数据潮起 三领域争抢蛋糕