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

本文介绍了如何在接入层使用Nginx进行限流,特别是通过ngx_http_limit_conn_module模块限制IP或服务域名的并发连接数。讨论了Java实现接入层的缺点,并提出Nginx作为接入层的优势,如动态配置和优雅重启。文中详细阐述了ngx_http_limit_conn_module的配置和工作原理,通过示例展示了如何限制IP的并发连接数。
摘要由CSDN通过智能技术生成

本文是根据开涛的博客 聊聊高并发系统之限流特技-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;
         }
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值