热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

系统限流实践接入层限流(上)

本文是根据开涛的博客聊聊高并发系统之限流特技-2整理而成,自学笔记第一篇欢迎访问我的个人博客http:rayleung.xyz目录1.系统限流实践-理论篇2.系统限流

本文是根据开涛的博客 聊聊高并发系统之限流特技-2 整理而成,自学笔记第一篇 
欢迎访问我的个人博客 http://rayleung.xyz/


目录

1.系统限流实践 - 理论篇 
2.系统限流实践 - 应用限流 
3.系统限流实践 - 分布式限流 
4.系统限流实践 - 接入层限流(上) 
5.系统限流实践 - 接入层限流(下*完结)

开篇

上篇学习了分布式限流(传送门),接下来学习一下接入层限流的方法

对于简单的web应用,我们一般直接通过容器例如Tomcat/Jetty直接把应用暴露给外部使用,这样做简单方便快速。 
但是对以下的场景就有点有心无力或者实现成本比较大,例如安全校验、负载均衡、请求聚合、服务降级、限流、A/B测试、服务质量监控等等。 
因此一般可以抽象出一个层次——-接入层,来实现以上场景。曾经在某外资银行工作做过,当时他们的系统也有接入层,叫”GateWay”层,实现了用户的身份校验,应用的Token验证以及服务路由等功能,用的是Java工程来实现的。 
不过个人觉得用Java来实现接入层有几个缺点: 
实现复杂 
例如写一个路由功能需要自己实现路径配置、路径解析等工作,目前已经有web服务器(Nginx)能够实现基于正则表达式的路由功能,配合Lua脚本的话,能做的东西就更多更灵活了 
配置更新不灵活 
Java项目要做到动态配置,可以通过Zookeeper或者Redis来做配置中心,因此要一系列的基础设施做配合,才能使得更新配置不用重启Java应用。要知道重启Java应用成本是一件成本比较高的事情。 
而通过Nginx的 -s reload 命令,能够很优雅地重启Nginx而不会对现有的连接造成影响,用户感知不到Nginx曾经重启过。 
如果想通过UI界面来更新路由而不重启Nginx,还可以使用nginx-upsync-module模块配合Consul和Consul Web UI来实现

说了那么多,下面进入正题

接入层限流

对于Nginx接入层限流可以使用Nginx自带的两个模块:连接数限流模块ngx_http_limit_conn_module和漏桶算法实现的请求限流模块ngx_http_limit_req_module。 
还可以使用OpenResty提供的Lua限流模块lua-resty-limit-traffic进行更复杂的限流场景。

ngx_http_limit_conn_module


limit_conn对某个KEY对应的总的网络连接数进行限流。可以按照IP来限制IP维度的总连接数,或者按照服务域名来限制某个域名的总连接数。但是不是每一个请求连接都会被计数器统计,只有那些被Nginx处理的且已经读取了整个请求头的请求连接才会被计数器统计。 
参考链接-http://nginx.org/en/docs/http/ngx_http_limit_conn_module.html


配置示例

http {limit_conn_zone $binary_remote_addr zone=addr:10m;limit_conn_log_level error;limit_conn_status 503;...server {...location /download/ {limit_conn addr 1;}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

limit_conn_zone 
命令格式:limit_conn_zone key zone=name:size; 
说明:设置一个共享内存区域给key,这个区域里面保存key的状态,进一步来说就是保存当前链接数的数量,$binary_remote_addr其表示IP地址,也可以使用如$server_name作为KEY来限制域名级别的最大连接数。

limit_conn_log_level 
配置记录被限流后的日志级别,默认error级别。

limit_conn_status 
配置被限流后返回的状态码,默认返回503。

limit_conn 
配置共享区域里面key(这里的key是addr)的最大链接数。此处指定的最大连接数是1,表示Nginx最多同时并发处理1个连接。

### limit_conn的主要执行过程 
1.请求进入首先判断当前limit_conn_zone中相应的key的连接数是否超出了配置的最大链接数 
2.如果超出了,则被限流,返回limit_conn_status定义的错误码;否则相应的key链接数加1,并注册请求处理完成的回调函数 
3.进行请求处理 
4.结束请求阶段会调用注册的回调函数对相应的链接数减1

###按照IP限制并发连接数 
首先定义根据IP维度的限流区域

http {......limit_conn_zone $binary_remote_addr zone=addr:10m;limit_conn_log_level error;limit_conn_status 503;......}```然后定义限流接口```http {......limit_conn_zone $binary_remote_addr zone=addr:10m;limit_conn_log_level error;limit_conn_status 503;......server {......location /limit {limit_conn addr 2; #限流2echo "success";}......}}```
用ab工具进行测试,并发数为5,总请求数为5
`
ab -n 5 -c 5 http://localhost:8080/limit`得到以下结果,限流成功

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

** - - [07/Jul/2016:11:06:28 +0800] “GET /limit HTTP/1.0” 200 8 “-” “ApacheBench/2.3” 
** - - [07/Jul/2016:11:06:28 +0800] “GET /limit HTTP/1.0” 200 8 “-” “ApacheBench/2.3” 
** - - [07/Jul/2016:11:06:28 +0800] “GET /limit HTTP/1.0” 503 537 “-” “ApacheBench/2.3” 
** - - [07/Jul/2016:11:06:28 +0800] “GET /limit HTTP/1.0” 503 537 “-” “ApacheBench/2.3” 
** - - [07/Jul/2016:11:06:28 +0800] “GET /limit HTTP/1.0” 503 537 “-” “ApacheBench/2.3”

###按照域名限流跟上节基本相同,区别在于维度不一样了,key字段改为了`$server_name`
`limit_conn_zone $server_name zone = perserver:10m;`## ngx_http_limit_req_module> limit_req是根据请求速率来做限流,是令牌桶算法的实现
[参考链接-http://nginx.org/en/docs/http/ngx_http_limit_req_module.html](http://nginx.org/en/docs/http/ngx_http_limit_req_module.html)###配置示例```
http {
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;...server {...location /search/ {limit_req zone=one burst=5;}```
**limit_req**配置限流区域、桶容量(突发容量,默认0)、是否延迟模式(默认延迟)**limit_req_zone**配置限流KEY、及存放KEY对应信息的共享内存区域大小、固定请求速率;此处指定的KEY是“$binary_remote_addr”表示IP地址;固定请求速率使用rate参数配置,支持10r/s和60r/m,即每秒10个请求和每分钟60个请求,不过最终都会转换为每秒的固定请求速率(10r/s为每100毫秒处理一个请求;60r/m,即每1000毫秒处理一个请求)**limit_req_status**配置被限流后返回的状态码,默认返回503**limit_req_log_level**配置记录被限流后的日志级别,默认error级别###limit_req的主要执行过程1 请求进入后首先判断最后一次请求时间相对于当前时间(第一次是0)是否需要限流,如果需要限流则执行步骤2,否则执行步骤32.1 如果没有配置桶容量(burst),则桶容量为0;按照固定速率处理请求;如果请求被限流,则直接返回相应的错误码(默认503)2.2 如果配置了桶容量(burst>0)且延迟模式(没有配置nodelay);如果桶满了,则新进入的请求被限流;如果没有满则请求会以固定平均速率被处理(按照固定速率并根据需要延迟处理请求,延迟使用休眠实现)2.3(burst>0)且非延迟模式(配置了nodelay);不会按照固定速率处理请求,而是允许突发处理请求;如果桶满了,则请求被限流,直接返回相应的错误码;后面令牌将会按章速率重新补充回桶里面3 如果没有被限流,则正常处理请求4 Nginx会在相应实际选择一些限流Key进行过期处理,进行内存回收###固定请求速率为1r/s,bustr为0维度设置```
http {......
limit_req_zone $binary_remote_addr zone=test:10m rate=1r/s;......}```
限流逻辑```
http {......server {......location /limit {limit_req zone = test; #burst为0,且为delay模式echo "success";}......}......}```
这种配置下,当请求速率超过1r/s时,其余的请求将会被拒绝测试
`ab -n 10 -c 1 http://192.168.235.190:8080/limit`
```
10.50.101.69 - - [08/Jul/2016:14:09:17 +0800] "GET /limit HTTP/1.0" 200 8 "-" "ApacheBench/2.3" --请求成功
10.50.101.69 - - [08/Jul/2016:14:09:17 +0800] "GET /limit HTTP/1.0" 503 537 "-" "ApacheBench/2.3" --剩下的请求全部被限流
10.50.101.69 - - [08/Jul/2016:14:09:17 +0800] "GET /limit HTTP/1.0" 503 537 "-" "ApacheBench/2.3"
10.50.101.69 - - [08/Jul/2016:14:09:17 +0800] "GET /limit HTTP/1.0" 503 537 "-" "ApacheBench/2.3"
10.50.101.69 - - [08/Jul/2016:14:09:17 +0800] "GET /limit HTTP/1.0" 503 537 "-" "ApacheBench/2.3"
10.50.101.69 - - [08/Jul/2016:14:09:17 +0800] "GET /limit HTTP/1.0" 503 537 "-" "ApacheBench/2.3"
10.50.101.69 - - [08/Jul/2016:14:09:17 +0800] "GET /limit HTTP/1.0" 503 537 "-" "ApacheBench/2.3"
10.50.101.69 - - [08/Jul/2016:14:09:17 +0800] "GET /limit HTTP/1.0" 503 537 "-" "ApacheBench/2.3"
10.50.101.69 - - [08/Jul/2016:14:09:17 +0800] "GET /limit HTTP/1.0" 503 537 "-" "ApacheBench/2.3"
10.50.101.69 - - [08/Jul/2016:14:09:17 +0800] "GET /limit HTTP/1.0" 503 537 "-" "ApacheBench/2.3"```
因为固定请求速率为1r/s,所以第一个请求成功,而且由于没有配置burst,接下来的请求被限流了### 固定请求速率为1r/s,burst为5维度设置```
http {......
limit_req_zone $binary_remote_addr zone=test:10m rate=1r/s;......}```
限流逻辑

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96

http { 
…… 
server { 
…… 
location /limit { 
limit_req zone = test burst=5; #burst为0,且为delay模式 
echo “success”; 

…… 

……

}

这种配置下&#xff0c;当请求速率超过1r/s时&#xff0c;接下来的5个请求会放入burst&#xff0c;如果这时候再有请求到来将会被限流由于不知道为什么在windows上用ab做测试呈现不了效果&#xff0c;于是通过写java代码来模拟&#96;&#96;&#96;public class NginxLimit {public static void main(String[] args) throws IOException {final NginxLimit distrubuteLimit &#61; new NginxLimit();final CountDownLatch latch &#61; new CountDownLatch(1);//两个工人的协作final Random random &#61; new Random(10);for (int i &#61; 0; i <10; i&#43;&#43;) {final int finalI &#61; i;Thread t &#61; new Thread(new Runnable() {public void run() {try {latch.await();String rev &#61; distrubuteLimit.sendGet("http://192.168.235.190:8080/limit", null);System.out.println(rev);} catch (InterruptedException e) {e.printStackTrace();}}});t.start();}latch.countDown();System.in.read();}public static String sendGet(String url, String param) {String result &#61; "";BufferedReader in &#61; null;try {String urlNameString &#61; url &#43; "?" &#43; param;URL realUrl &#61; new URL(urlNameString);// 打开和URL之间的连接URLConnection connection &#61; realUrl.openConnection();// 设置通用的请求属性connection.setRequestProperty("accept", "*/*");connection.setRequestProperty("connection", "Keep-Alive");connection.setRequestProperty("user-agent","Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");// 建立实际的连接connection.connect();// 定义 BufferedReader输入流来读取URL的响应in &#61; new BufferedReader(new InputStreamReader(connection.getInputStream()));String line;while ((line &#61; in.readLine()) !&#61; null) {result &#43;&#61; line;}} catch (Exception e) {System.out.println("发送GET请求出现异常");}// 使用finally块来关闭输入流finally {try {if (in !&#61; null) {in.close();}} catch (Exception e2) {e2.printStackTrace();}}return result;}}&#96;&#96;&#96;测试结果&#96;&#96;&#96;10.50.101.69 - - [08/Jul/2016:14:25:30 &#43;0800] "GET /limit?null HTTP/1.1" 200 18 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"10.50.101.69 - - [08/Jul/2016:14:25:30 &#43;0800] "GET /limit?null HTTP/1.1" 503 537 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"10.50.101.69 - - [08/Jul/2016:14:25:30 &#43;0800] "GET /limit?null HTTP/1.1" 503 537 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"10.50.101.69 - - [08/Jul/2016:14:25:30 &#43;0800] "GET /limit?null HTTP/1.1" 503 537 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"10.50.101.69 - - [08/Jul/2016:14:25:30 &#43;0800] "GET /limit?null HTTP/1.1" 503 537 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"10.50.101.69 - - [08/Jul/2016:14:25:31 &#43;0800] "GET /limit?null HTTP/1.1" 200 18 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"10.50.101.69 - - [08/Jul/2016:14:25:32 &#43;0800] "GET /limit?null HTTP/1.1" 200 18 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"10.50.101.69 - - [08/Jul/2016:14:25:33 &#43;0800] "GET /limit?null HTTP/1.1" 200 18 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"10.50.101.69 - - [08/Jul/2016:14:25:34 &#43;0800] "GET /limit?null HTTP/1.1" 200 18 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"10.50.101.69 - - [08/Jul/2016:14:25:35 &#43;0800] "GET /limit?null HTTP/1.1" 200 18 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"&#96;&#96;&#96;一共有10个请求&#xff0c;其中6个成功&#xff0c;4个失败。但是为什么有6个成功而不是5个呢&#xff1f;因为固定请求速率是1r/s&#xff0c;而burst容量是5&#xff0c;所以1&#43;5得到6。剩下放不进burst的请求会别限流。另外通过日志观察&#xff0c;请求一秒处理一个。###固定请求速率为1r/s&#xff0c;burst为5&#xff0c;nodelay
维度设置

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87

http { 
…… 
limit_req_zone $binary_remote_addr zone&#61;test:10m rate&#61;1r/s; 
…… 
}

限流逻辑

  • 1

http { 
…… 
server { 
…… 
location /limit { 
limit_req zone &#61; test burst&#61;5 nodelay; #burst为0&#xff0c;且为nodelay模式 
echo “success”; 

…… 

……

}

测试代码

  • 1

public class NginxLimit {

public static void main(String[] args) throws IOException, InterruptedException {final NginxLimit distrubuteLimit &#61; new NginxLimit();final CountDownLatch latch &#61; new CountDownLatch(1);//两个工人的协作final Random random &#61; new Random(10);//阶段一for (int i &#61; 0; i <10; i&#43;&#43;) {final int finalI &#61; i;Thread t &#61; new Thread(new Runnable() {public void run() {try {latch.await();String rev &#61; distrubuteLimit.sendGet("http://192.168.235.190:8080/limit", null);System.out.println(rev);} catch (InterruptedException e) {e.printStackTrace();}}});t.start();}latch.countDown();//阶段二for (int i &#61; 0; i <10; i&#43;&#43;) {String rev &#61; distrubuteLimit.sendGet("http://192.168.235.190:8080/limit", null);System.out.println(rev);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}//阶段三final CountDownLatch latch2 &#61; new CountDownLatch(1);//两个工人的协作for (int i &#61; 0; i <10; i&#43;&#43;) {final int finalI &#61; i;Thread t2 &#61; new Thread(new Runnable() {public void run() {try {latch2.await();String rev &#61; distrubuteLimit.sendGet("http://192.168.235.190:8080/limit", null);System.out.println(rev);} catch (InterruptedException e) {e.printStackTrace();}}});t2.start();}latch2.countDown();System.in.read();
}
.......

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55

}

  • 1

–阶段一 
10.50.101.69 - - [08/Jul/2016:15:16:23 &#43;0800] “GET /limit?null HTTP/1.1” 200 18 “-” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)” 
10.50.101.69 - - [08/Jul/2016:15:16:23 &#43;0800] “GET /limit?null HTTP/1.1” 200 18 “-” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)” 
10.50.101.69 - - [08/Jul/2016:15:16:23 &#43;0800] “GET /limit?null HTTP/1.1” 200 18 “-” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)” 
10.50.101.69 - - [08/Jul/2016:15:16:23 &#43;0800] “GET /limit?null HTTP/1.1” 200 18 “-” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)” 
10.50.101.69 - - [08/Jul/2016:15:16:23 &#43;0800] “GET /limit?null HTTP/1.1” 200 18 “-” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)” 
10.50.101.69 - - [08/Jul/2016:15:16:23 &#43;0800] “GET /limit?null HTTP/1.1” 200 18 “-” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)” 
10.50.101.69 - - [08/Jul/2016:15:16:23 &#43;0800] “GET /limit?null HTTP/1.1” 503 537 “-” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)” 
10.50.101.69 - - [08/Jul/2016:15:16:23 &#43;0800] “GET /limit?null HTTP/1.1” 503 537 “-” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)” 
10.50.101.69 - - [08/Jul/2016:15:16:23 &#43;0800] “GET /limit?null HTTP/1.1” 503 537 “-” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)” 
10.50.101.69 - - [08/Jul/2016:15:16:23 &#43;0800] “GET /limit?null HTTP/1.1” 503 537 “-” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)” 
–阶段二 
10.50.101.69 - - [08/Jul/2016:15:16:25 &#43;0800] “GET /limit?null HTTP/1.1” 200 18 “-” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)” 
10.50.101.69 - - [08/Jul/2016:15:16:26 &#43;0800] “GET /limit?null HTTP/1.1” 200 18 “-” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)” 
10.50.101.69 - - [08/Jul/2016:15:16:27 &#43;0800] “GET /limit?null HTTP/1.1” 200 18 “-” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)” 
10.50.101.69 - - [08/Jul/2016:15:16:28 &#43;0800] “GET /limit?null HTTP/1.1” 200 18 “-” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)” 
10.50.101.69 - - [08/Jul/2016:15:16:29 &#43;0800] “GET /limit?null HTTP/1.1” 200 18 “-” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)” 
10.50.101.69 - - [08/Jul/2016:15:16:30 &#43;0800] “GET /limit?null HTTP/1.1” 200 18 “-” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)” 
10.50.101.69 - - [08/Jul/2016:15:16:31 &#43;0800] “GET /limit?null HTTP/1.1” 200 18 “-” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)” 
10.50.101.69 - - [08/Jul/2016:15:16:32 &#43;0800] “GET /limit?null HTTP/1.1” 200 18 “-” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)” 
10.50.101.69 - - [08/Jul/2016:15:16:33 &#43;0800] “GET /limit?null HTTP/1.1” 200 18 “-” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)” 
10.50.101.69 - - [08/Jul/2016:15:16:34 &#43;0800] “GET /limit?null HTTP/1.1” 200 18 “-” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)” 
–阶段三 
10.50.101.69 - - [08/Jul/2016:15:16:35 &#43;0800] “GET /limit?null HTTP/1.1” 200 18 “-” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)” 
10.50.101.69 - - [08/Jul/2016:15:16:35 &#43;0800] “GET /limit?null HTTP/1.1” 200 18 “-” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)” 
10.50.101.69 - - [08/Jul/2016:15:16:35 &#43;0800] “GET /limit?null HTTP/1.1” 503 537 “-” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)” 
10.50.101.69 - - [08/Jul/2016:15:16:35 &#43;0800] “GET /limit?null HTTP/1.1” 503 537 “-” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)” 
10.50.101.69 - - [08/Jul/2016:15:16:35 &#43;0800] “GET /limit?null HTTP/1.1” 503 537 “-” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)” 
10.50.101.69 - - [08/Jul/2016:15:16:35 &#43;0800] “GET /limit?null HTTP/1.1” 503 537 “-” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)” 
10.50.101.69 - - [08/Jul/2016:15:16:35 &#43;0800] “GET /limit?null HTTP/1.1” 503 537 “-” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)” 
10.50.101.69 - - [08/Jul/2016:15:16:35 &#43;0800] “GET /limit?null HTTP/1.1” 503 537 “-” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)” 
10.50.101.69 - - [08/Jul/2016:15:16:35 &#43;0800] “GET /limit?null HTTP/1.1” 503 537 “-” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)” 
10.50.101.69 - - [08/Jul/2016:15:16:35 &#43;0800] “GET /limit?null HTTP/1.1” 503 537 “-” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)” 
“&#96;

nodelay模式下&#xff0c;limit_req允许一定程度的并发。 
阶段一的时候&#xff0c;程序并发10个请求&#xff0c;一下子被处理完&#xff08;不像之前delay模式下一秒一个地请求&#xff09;&#xff0c;其中前6个请求能被处理&#xff0c;后4个请求被限流。 
阶段二的时候&#xff0c;程序每隔1秒发起1个请求&#xff0c;循环10次。由于令牌补充的速率也是1r/s&#xff0c;所以每次请求到达的时候都有令牌可取&#xff0c;请求正常。 
阶段三的时候&#xff0c;程序有不少503&#xff0c;就是因为桶里面没有令牌了&#xff0c;请求被限流了。

总结

利用Nginx做分布式限流&#xff0c;主要用的就是ngx_http_limit_conn_modulengx_http_limit_req_module模块。 
ngx_http_limit_req_module通过配置nodelay参数决定使用漏桶算法还是令牌桶算法。 
当使用delay参数的时候&#xff0c;请求会按照固定请求速率被处理&#xff0c;即使有突发流量涌入&#xff0c;也不会影响请求处理的速率。当请求速率大于固定请求速率&#43;burst数量的时候&#xff0c;多余的请求会别限流抛弃。 
当使用nodelay参数的时候&#xff0c;系统能处理的并发数取决于固定请求速率&#43;burst里令牌数之和&#xff0c;然后令牌按照固定请求速率补充回令牌桶。 
需要说明一下的是&#xff0c;以上的推论是按照网上的资料以及自己实验观察所得&#xff0c;仅供参考&#xff0c;不保证完全正确。 
接下来最后一篇会学习用Openresty &#43; Lua来实现接入层限流。

参考资料

ngx_http_limit_conn_module - http://nginx.org/en/docs/http/ngx_http_limit_conn_module.html 

ngx_http_limit_req_module - http://nginx.org/en/docs/http/ngx_http_limit_req_module.html



http://blog.csdn.net/lzw_2006/article/details/51880583




推荐阅读
  • 第二章:Kafka基础入门与核心概念解析
    本章节主要介绍了Kafka的基本概念及其核心特性。Kafka是一种分布式消息发布和订阅系统,以其卓越的性能和高吞吐量而著称。最初,Kafka被设计用于LinkedIn的活动流和运营数据处理,旨在高效地管理和传输大规模的数据流。这些数据主要包括用户活动记录、系统日志和其他实时信息。通过深入解析Kafka的设计原理和应用场景,读者将能够更好地理解其在现代大数据架构中的重要地位。 ... [详细]
  • 2021年Java开发实战:当前时间戳转换方法详解与实用网址推荐
    在当前的就业市场中,金九银十过后,金三银四也即将到来。本文将分享一些实用的面试技巧和题目,特别是针对正在寻找新工作机会的Java开发者。作者在准备字节跳动的面试过程中积累了丰富的经验,并成功获得了Offer。文中详细介绍了如何将当前时间戳进行转换的方法,并推荐了一些实用的在线资源,帮助读者更好地应对技术面试。 ... [详细]
  • 小王详解:内部网络中最易理解的NAT原理剖析,挑战你的认知极限
    小王详解:内部网络中最易理解的NAT原理剖析,挑战你的认知极限 ... [详细]
  • 在JavaWeb项目架构中,NFS(网络文件系统)的实现与优化是关键环节。NFS允许不同主机系统通过局域网共享文件和目录,提高资源利用率和数据访问效率。本文详细探讨了NFS在JavaWeb项目中的应用,包括配置、性能优化及常见问题的解决方案,旨在为开发者提供实用的技术参考。 ... [详细]
  • 本文详细介绍了如何安全地手动卸载Exchange Server 2003,以确保系统的稳定性和数据的完整性。根据微软官方支持文档(https://support.microsoft.com/kb833396/zh-cn),在进行卸载操作前,需要特别注意备份重要数据,并遵循一系列严格的步骤,以避免对现有网络环境造成不利影响。此外,文章还提供了详细的故障排除指南,帮助管理员在遇到问题时能够迅速解决,确保整个卸载过程顺利进行。 ... [详细]
  • 2016-2017学年《网络安全实战》第三次作业
    2016-2017学年《网络安全实战》第三次作业总结了教材中关于网络信息收集技术的内容。本章主要探讨了网络踩点、网络扫描和网络查点三个关键步骤。其中,网络踩点旨在通过公开渠道收集目标信息,为后续的安全测试奠定基础,而不涉及实际的入侵行为。 ... [详细]
  • Nginx不仅是一款轻量级的高性能Web服务器,还具备出色的负载均衡和反向代理功能。它支持复杂的正则匹配规则、动静内容分离以及灵活的URL重写功能,使得配置和管理更加便捷高效。此外,Nginx提供了多种负载均衡算法,如轮询、加权轮询、最少连接数等,以满足不同应用场景的需求。 ... [详细]
  • 近年来,BPM(业务流程管理)系统在国内市场逐渐普及,多家厂商在这一领域崭露头角。本文将对当前主要的BPM厂商进行概述,并分析其各自的优势。目前,市场上较为成熟的BPM产品主要分为两类:一类是综合型厂商,如IBM和SAP,这些企业在整体解决方案方面具有明显优势;另一类则是专注于BPM领域的专业厂商,它们在特定行业或应用场景中表现出色。通过对比分析,本文旨在为企业选择合适的BPM系统提供参考。 ... [详细]
  • 2019年后蚂蚁集团与拼多多面试经验详述与深度剖析
    2019年后蚂蚁集团与拼多多面试经验详述与深度剖析 ... [详细]
  • 在优化Nginx与PHP的高效配置过程中,许多教程提供的配置方法存在诸多问题或不良实践。本文将深入探讨这些常见错误,并详细介绍如何正确配置Nginx和PHP,以实现更高的性能和稳定性。我们将从Nginx配置文件的基本指令入手,逐步解析每个关键参数的最优设置,帮助读者理解其背后的原理和实际应用效果。 ... [详细]
  • 线程能否先以安全方式获取对象,再进行非安全发布? ... [详细]
  • 在当前的软件开发领域,Lua 作为一种轻量级脚本语言,在 .NET 生态系统中的应用逐渐受到关注。本文探讨了 Lua 在 .NET 环境下的集成方法及其面临的挑战,包括性能优化、互操作性和生态支持等方面。尽管存在一定的技术障碍,但通过不断的学习和实践,开发者能够克服这些困难,拓展 Lua 在 .NET 中的应用场景。 ... [详细]
  • Cosmos生态系统为何迅速崛起,波卡作为跨链巨头应如何应对挑战?
    Cosmos生态系统为何迅速崛起,波卡作为跨链巨头应如何应对挑战? ... [详细]
  • FastDFS Nginx 扩展模块的源代码解析与技术剖析
    FastDFS Nginx 扩展模块的源代码解析与技术剖析 ... [详细]
  • 解读中台架构:微服务与分布式技术的区别及应用
    中心化与去中心化是长期讨论的话题。中心化架构的优势在于部署和维护相对简单,尤其在服务负载较为稳定的情况下,能够提供高效稳定的性能。然而,随着业务规模的扩大和技术需求的多样化,中心化架构的局限性逐渐显现,如扩展性和故障恢复能力较差。相比之下,微服务和分布式技术通过解耦系统组件,提高了系统的灵活性和可扩展性,更适合处理复杂多变的业务场景。本文将深入探讨中台架构中微服务与分布式技术的区别及其应用场景,帮助读者更好地理解和选择适合自身业务的技术方案。 ... [详细]
author-avatar
手机用户2502856183
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有