点击上方 Java后端,选择 设为星标

优质文章,及时送达


限流算法:令牌桶算法

算法思想是:

  • 令牌以固定速率产生,并缓存到令牌桶中;
  • 令牌桶放满时,多余的令牌被丢弃;
  • 请求要消耗等比例的令牌才能被处理;
  • 令牌不够时,请求被缓存。

漏桶算法

算法思想是:

  • 水(请求)从上方倒入水桶,从水桶下方流出(被处理);
  • 来不及流出的水存在水桶中(缓冲),以固定速率流出;
  • 水桶满后水溢出(丢弃)。
  • 这个算法的核心是:缓存请求、匀速处理、多余的请求直接丢弃。
    相比漏桶算法,令牌桶算法不同之处在于它不但有一只“桶”,还有个队列,这个桶是用来存放令牌的,队列才是用来存放请求的。

从作用上来说,漏桶和令牌桶算法最明显的区别就是是否允许突发流量(burst)的处理,漏桶算法能够强行限制数据的实时传输(处理)速率,对突发流量不做额外处理;而令牌桶算法能够在限制数据的平均传输速率的同时允许某种程度的突发传输。Nginx按请求速率限速模块使用的是漏桶算法,即能够强行保证请求的实时处理速度不会超过设置的阈值。Nginx官方版本限制IP的连接和并发分别有两个模块:

  • limit_req_zone 用来限制单位时间内的请求数,即速率限制,采用的漏桶算法 "leaky bucket"。
  • limit_req_conn 用来限制同一时间连接数,即并发限制。

limit_req_zone 参数配置

Syntax: limit_req zone=name [burst=number] [nodelay];Default: —Context: http, server, locationlimit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
  • 第一个参数:$binary_remote_addr 表示通过remote_addr这个标识来做限制,“binary_”的目的是缩写内存占用量,是限制同一客户端ip地址。
  • 第二个参数:zone=one:10m表示生成一个大小为10M,名字为one的内存区域,用来存储访问的频次信息。
  • 第三个参数:rate=1r/s表示允许相同标识的客户端的访问频次,这里限制的是每秒1次,还可以有比如30r/m的。

limit_req zone=one burst=5 nodelay;

  • 第一个参数:zone=one 设置使用哪个配置区域来做限制,与上面limit_req_zone 里的name对应。
  • 第二个参数:burst=5,重点说明一下这个配置,burst爆发的意思,这个配置的意思是设置一个大小为5的缓冲区当有大量请求(爆发)过来时,超过了访问频次限制的请求可以先放到这个缓冲区内。
  • 第三个参数:nodelay,如果设置,超过访问频次而且缓冲区也满了的时候就会直接返回503,如果没有设置,则所有请求会等待排队。

例子:

http {limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;server {location /search/ {limit_req zone=one burst=5 nodelay;        }}

下面配置可以限制特定UA(比如搜索引擎)的访问:

limit_req_zone  $anti_spider  zone=one:10m   rate=10r/s;limit_req zone=one burst=100 nodelay;if ($http_user_agent ~* "googlebot|bingbot|Feedfetcher-Google") {set $anti_spider $http_user_agent;}

其他参数

Syntax: limit_req_log_level info | notice | warn | error;Default:limit_req_log_level error;Context: http, server, location

当服务器由于limit被限速或缓存时,配置写入日志。延迟的记录比拒绝的记录低一个级别。例子:limit_req_log_level notice延迟的的基本是info。

Syntax: limit_req_status code;Default:limit_req_status 503;Context: http, server, location

设置拒绝请求的返回值。值只能设置 400 到 599 之间。

ngx_http_limit_conn_module 参数配置

这个模块用来限制单个IP的请求数。并非所有的连接都被计数。只有在服务器处理了请求并且已经读取了整个请求头时,连接才被计数。

Syntax: limit_conn zone number;Default: —Context: http, server, locationlimit_conn_zone $binary_remote_addr zone=addr:10m;server {location /download/ {limit_conn addr 1;    }

一次只允许每个IP地址一个连接。

limit_conn_zone $binary_remote_addr zone=perip:10m;limit_conn_zone $server_name zone=perserver:10m;server {    ...    limit_conn perip 10;    limit_conn perserver 100;}

可以配置多个limit_conn指令。例如,以上配置将限制每个客户端IP连接到服务器的数量,同时限制连接到虚拟服务器的总数。

Syntax: limit_conn_zone key zone=name:size;Default: —Context: httplimit_conn_zone $binary_remote_addr zone=addr:10m;

在这里,客户端IP地址作为关键。请注意,不是$ remote_addr,而是使用$ binary_remote_addr变量。$ remote_addr变量的大小可以从7到15个字节不等。存储的状态在32位平台上占用32或64字节的内存,在64位平台上总是占用64字节。对于IPv4地址,$ binary_remote_addr变量的大小始终为4个字节,对于IPv6地址则为16个字节。存储状态在32位平台上始终占用32或64个字节,在64位平台上占用64个字节。一个兆字节的区域可以保持大约32000个32字节的状态或大约16000个64字节的状态。如果区域存储耗尽,服务器会将错误返回给所有其他请求。

Syntax: limit_conn_log_level info | notice | warn | error;Default:limit_conn_log_level error;Context: http, server, location

当服务器限制连接数时,设置所需的日志记录级别。

Syntax: limit_conn_status code;Default:limit_conn_status 503;Context: http, server, location

设置拒绝请求的返回值。

实战

实例一 限制访问速率

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

上述规则限制了每个IP访问的速度为2r/s,并将该规则作用于根目录。如果单个IP在非常短的时间内并发发送多个请求,结果会怎样呢?

我们使用单个IP在10ms内发并发送了6个请求,只有1个成功,剩下的5个都被拒绝。我们设置的速度是2r/s,为什么只有1个成功呢,是不是Nginx限制错了?当然不是,是因为Nginx的限流统计是基于毫秒的,我们设置的速度是2r/s,转换一下就是500ms内单个IP只允许通过1个请求,从501ms开始才允许通过第二个请求。更多 Nginx 相关的文章可以关注微信公众号:Java后端 ,回复 666 下载。

实例二 burst缓存处理

我们看到,我们短时间内发送了大量请求,Nginx按照毫秒级精度统计,超出限制的请求直接拒绝。这在实际场景中未免过于苛刻,真实网络环境中请求到来不是匀速的,很可能有请求“突发”的情况,也就是“一股子一股子”的。Nginx考虑到了这种情况,可以通过burst关键字开启对突发请求的缓存处理,而不是直接拒绝。
来看我们的配置:

limit_req_zone $binary_remote_addr zone=mylimit:10m rate=2r/s;server {location / {limit_req zone=mylimit burst=4;    }}

我们加入了burst=4,意思是每个key(此处是每个IP)最多允许4个突发请求的到来。如果单个IP在10ms内发送6个请求,结果会怎样呢?

相比实例一成功数增加了4个,这个我们设置的burst数目是一致的。具体处理流程是:1个请求被立即处理,4个请求被放到burst队列里,另外一个请求被拒绝。通过burst参数,我们使得Nginx限流具备了缓存处理突发流量的能力。但是请注意:burst的作用是让多余的请求可以先放到队列里,慢慢处理。如果不加nodelay参数,队列里的请求不会立即处理,而是按照rate设置的速度,以毫秒级精确的速度慢慢处理。

实例三  nodelay降低排队时间

实例二中我们看到,通过设置burst参数,我们可以允许Nginx缓存处理一定程度的突发,多余的请求可以先放到队列里,慢慢处理,这起到了平滑流量的作用。但是如果队列设置的比较大,请求排队的时间就会比较长,用户角度看来就是RT变长了,这对用户很不友好。有什么解决办法呢?nodelay参数允许请求在排队的时候就立即被处理,也就是说只要请求能够进入burst队列,就会立即被后台worker处理,请注意,这意味着burst设置了nodelay时,系统瞬间的QPS可能会超过rate设置的阈值。nodelay参数要跟burst一起使用才有作用。延续实例二的配置,我们加入nodelay选项:

limit_req_zone $binary_remote_addr zone=mylimit:10m rate=2r/s;server {location / {limit_req zone=mylimit burst=4 nodelay;    }}

单个IP 10ms内并发发送6个请求,结果如下:

跟实例二相比,请求成功率没变化,但是总体耗时变短了。这怎么解释呢?实例二中,有4个请求被放到burst队列当中,工作进程每隔500ms(rate=2r/s)取一个请求进行处理,最后一个请求要排队2s才会被处理;实例三中,请求放入队列跟实例二是一样的,但不同的是,队列中的请求同时具有了被处理的资格,所以实例三中的5个请求可以说是同时开始被处理的,花费时间自然变短了。但是请注意,虽然设置burst和nodelay能够降低突发请求的处理时间,但是长期来看并不会提高吞吐量的上限,长期吞吐量的上限是由rate决定的,因为nodelay只能保证burst的请求被立即处理,但Nginx会限制队列元素释放的速度,就像是限制了令牌桶中令牌产生的速度。看到这里你可能会问,加入了nodelay参数之后的限速算法,到底算是哪一个“桶”,是漏桶算法还是令牌桶算法?当然还算是漏桶算法。考虑一种情况,令牌桶算法的token为耗尽时会怎么做呢?由于它有一个请求队列,所以会把接下来的请求缓存下来,缓存多少受限于队列大小。但此时缓存这些请求还有意义吗?如果server已经过载,缓存队列越来越长,RT越来越高,即使过了很久请求被处理了,对用户来说也没什么价值了。所以当token不够用时,最明智的做法就是直接拒绝用户的请求,这就成了漏桶算法。

示例四 自定义返回值

limit_req_zone $binary_remote_addr zone=mylimit:10m rate=2r/s;server {location / {limit_req zone=mylimit burst=4 nodelay;limit_req_status 598;    }}

默认情况下 没有配置 status 返回值的状态:

自定义 status 返回值的状态:

参考文档

Nginx限制访问速率和最大并发连接数模块--limit (防止DDOS攻击)

http://www.cnblogs.com/wjoyxt/p/6128183.html

Nginx 限流

http://colobu.com/2015/10/26/nginx-limit-modules/
关于nginx的限速模块

https://www.cnblogs.com/chenpingzhao/p/4971308.html
Nginx 源代码笔记 - HTTP 模块 - 流控

http://ialloc.org/posts/2014/07/26/ngx-notes-module-http-limit/
Module ngx_http_limit_conn_module

http://nginx.org/en/docs/http/ngx_http_limit_conn_module.html
Module ngx_http_limit_req_module
Nginx限速模块初探

https://www.cnblogs.com/CarpenterLee/p/8084533.html


-END-

如果看到这里,说明你喜欢这篇文章,请 转发、点赞。同时 标星(置顶)本公众号可以第一时间接受到博文推送。

1. Lambda 表达式入门

2. 卧槽!原来 IOC 这么简单

3. Java 处理 Exception 的 9 个最佳实践

4. 这本 Java 开发手册出炉啦!

最近整理一份面试资料《Java技术栈学习手册》,覆盖了Java技术、面试题精选、Spring全家桶、Nginx、SSM、微服务、数据库、数据结构、架构等等。

获取方式:点“ 在看,关注公众号 Java后端 并回复 777 领取,更多内容陆续奉上。

喜欢文章,点个在看 

sql server 配置管理器里为什么是32位_死磕 Nginx 系列:Nginx 限流配置相关推荐

  1. sql server 配置管理器里为什么是32位_幽灵山庄49 储物柜里的恶臭

    情节回顾: 幽灵山庄1 我的邻居是变性人 幽灵山庄 2 一个可以帮你实现所有梦想的地方 幽灵山庄 3 我的变性人邻居死了 幽灵山庄4 世界上除了双胞胎,还会有长得如此相像的人吗 幽灵山庄5 在恐怖城走 ...

  2. sql server 配置管理器里为什么是32位_Windows Server2012 配置打印服务器图文教程

    一. 测试环境 本教程详细介绍了在Windows Server 2012系统中安装配置打印服务器的过程,很基础的东西有没有,大神就直接跳过喽.我们用到了一台Windows 10的物理机,以及虚拟的Wi ...

  3. Windows10中“SQL Server 配置管理器”哪去了?

    SQL Server 配置管理器是一种工具,用于管理与 SQL Server 相关联的服务.配置 SQL Server 使用的网络协议以及从 SQL Server 客户端计算机管理网络连接配置.SQL ...

  4. 如何使用SQL Server配置管理器

    SQL Server configuration manager is a tool provided by Microsoft SQL Server. When we install SQL Ser ...

  5. 解决打不开SQL Server配置管理器的问题

    最近被Sql Server搞得贼烦,下了俩次SQL SERVER,重装了一次系统,先对这次遇到的问题发一下感慨:深深地意识到权限的重要性了,一般计算机里面的软件都有不同的访问权限,普通用户(Users ...

  6. server缺少sqlexpress sql_SQL Server----解决SQL Server 配置管理器不见了

    错误重现: 之前安装好的SQL Server 2012打开都没有问题,好多天没有打开了,今天打开我的SQL Server 2012 连接时出现错误: 在与SQL Server 建立连接时出现与网络相关 ...

  7. Windows 7 上怎样打开SQL Server 配置管理器

    场景 在Windows 7 上打开 SQL Server 的配置管理器. 实现 右击电脑--管理 在计算机管理--服务和应用程序-SQL Server 配置管理器 注: 博客首页: https://b ...

  8. mybatis学习(11): sql server配置管理器请求失败或服务未及时响应

    遇到这种情况,打开sql server配置管理器,双击[sql server网络配置]将其展开,双击子项[MSSQLSERVER的协议],在右面的内容窗口中找到[VIA]选项将其设置为禁用就可以了.

  9. 【SQL Server配置管理器】提示:无法连接到 WMI 提供程序。您没有权限或者该服务器无法访问...

    [SQL Server配置管理器]提示:无法连接到 WMI 提供程序.您没有权限或者该服务器无法访问 //开始运行Cmd.exe进命令行 //进入MSsql2008安装目录cd /Program Fi ...

最新文章

  1. 文件同步工具 lsyncd2.1.6 安装使用问题
  2. 微信小程序引入Vant组件库
  3. 动态网页制作PHP常用的正则表达式
  4. 评价算法的性能从利用计算机资源角度,计算机专业数据结构课后练习题汇编
  5. Oracle 行转列
  6. FastReport4.6程序员手册_翻译
  7. angularjs modal模态框----创建可拖动的指令
  8. windows下pclpy安装失败的解决方法——本地安装
  9. python3 selenium ie 拒绝连接报错_selenium+python自动化测试--解决无法启动IE浏览器及报错问题...
  10. java 泛型去重_泛型,list集合去重
  11. unity的安装教程
  12. Windows Server2012 服务器修改密码过期时间
  13. 弹幕视频社交时代:如何玩转弹幕文化
  14. Python 实验二 tkinter 版小学数学口算题生成器设计与实现
  15. ERP项目实施方法论
  16. 数据中台怎么选型?终于有人讲明白了
  17. 以vgg为backbone的简易图像检索系统
  18. 走近棒球运动·韩国职业棒球联盟·MLB棒球创造营
  19. QualcommMTK平台lcd/tp调试及问题总结(一)----背光
  20. 工地上的这些工种工资差距很大,你知道是哪些工种吗?

热门文章

  1. 011_AOP注解开发
  2. 第四篇:mysql管理工具
  3. 计算机专业i7 7500u,8550U比7500U提升多少 8550U和7500U的区别-太平洋电脑网
  4. js正则贪婪模式_C# 正则表达式贪婪模式案例
  5. c# redis hashid如何设置过期时间_Redis数据库实现原理(划重点)
  6. 24个笔画顺序表_400个生字笔顺表,孩子照着写,家长省心省力!
  7. python打开中文文件名_[请教]python的中文文件名处理
  8. cesium鼠标控制键盘_用 Python 控制 鼠标和键盘,花式操作
  9. kattle的java安装,Kettle自定义JDK版本(附Linux下安装部署步骤)
  10. Pycharm安装和基本使用