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

本文是根据开涛的博客 聊聊高并发系统之限流特技-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;
        }

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; #限流2
            echo "success";
        }
        ......
     }
  }
  ``` 用ab工具进行测试,并发数为5,总请求数为5 `ab -n 5 -c 5 http://localhost:8080/limit`

得到以下结果,限流成功

** - - [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,否则执行步骤3
 2.1 如果没有配置桶容量(burst),则桶容量为0;按照固定速率处理请求;如果请求被限流,则直接返回相应的错误码(默认5032.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;
     ......
  }
  ``` 限流逻辑

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

}

 这种配置下,当请求速率超过1r/s时,接下来的5个请求会放入burst,如果这时候再有请求到来将会被限流

 由于不知道为什么在windows上用ab做测试呈现不了效果,于是通过写java代码来模拟
 ```
 public class NginxLimit {

     public static void main(String[] args) throws IOException {
         final NginxLimit distrubuteLimit = new NginxLimit();
         final CountDownLatch latch = new CountDownLatch(1);//两个工人的协作
         final Random random = new Random(10);
         for (int i = 0; i < 10; i++) {
             final int finalI = i;
             Thread t = new Thread(new Runnable() {
                 public void run() {
                     try {
                         latch.await();
                             String rev = 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 = "";
         BufferedReader in = null;
         try {
             String urlNameString = url + "?" + param;
             URL realUrl = new URL(urlNameString);
             // 打开和URL之间的连接
             URLConnection connection = 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 = new BufferedReader(new InputStreamReader(
                     connection.getInputStream()));
             String line;
             while ((line = in.readLine()) != null) {
                 result += line;
             }
         } catch (Exception e) {
             System.out.println("发送GET请求出现异常");
         }
         // 使用finally块来关闭输入流
         finally {
             try {
                 if (in != null) {
                     in.close();
                 }
             } catch (Exception e2) {
                 e2.printStackTrace();
             }
         }
         return result;
     }
 }
 ```

 测试结果
 ```
 10.50.101.69 - - [08/Jul/2016:14:25:30 +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 +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 +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 +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 +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 +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 +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 +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 +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 +0800] "GET /limit?null HTTP/1.1" 200 18 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"
 ```
 一共有10个请求,其中6个成功,4个失败。但是为什么有6个成功而不是5个呢?因为固定请求速率是1r/s,而burst容量是5,所以1+5得到6。剩下放不进burst的请求会别限流。另外通过日志观察,请求一秒处理一个。

###固定请求速率为1r/s,burst为5,nodelay
维度设置

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

限流逻辑

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

}

测试代码

public class NginxLimit {

public static void main(String[] args) throws IOException, InterruptedException {
    final NginxLimit distrubuteLimit = new NginxLimit();
    final CountDownLatch latch = new CountDownLatch(1);//两个工人的协作
    final Random random = new Random(10);
    //阶段一
    for (int i = 0; i < 10; i++) {
        final int finalI = i;
        Thread t = new Thread(new Runnable() {
            public void run() {
                try {
                    latch.await();
                    String rev = 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 = 0; i < 10; i++) {
        String rev = 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 = new CountDownLatch(1);//两个工人的协作
    for (int i = 0; i < 10; i++) {
        final int finalI = i;
        Thread t2 = new Thread(new Runnable() {
            public void run() {
                try {
                    latch2.await();
                    String rev = 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();
}
.......

}

–阶段一
10.50.101.69 - - [08/Jul/2016:15:16:23 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +0800] “GET /limit?null HTTP/1.1” 503 537 “-” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)”
“`

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

总结

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

欢迎关注个人公众号

你可能感兴趣的:(系统限流实践 - 接入层限流(上))