【Nginx】下载,请求限流限速,根据URL参数限速,nginxurl


这个场景是限制单个连接的下载速度,还有限制单个IP的连接数,或者单位时间内的请求数,实验环境 nginx1.9.x。 小例子为主,具体的细节请多看文档。

限制下载速度

location /download { 
    limit_rate 128k; 
  } 

#如果想设置用户下载文件的前10m大小时不限速,大于10m后再以128kb/s限速可以增加以下配内容,修改nginx.conf文件

location /download { 
       limit_rate_after 10m; 
       limit_rate 128k; 
 }  

限制IP的连接和并发

  • limit_req_zone 用来限制单位时间内的请求数

  • limit_req_conn 用来限制同一时间连接数

限制某一段时间内同同一个ip访问的次数

http{
    ...
    #定义一个名为allips的limit_req_zone用来存储session,大小是10M内存,
    #以$binary_remote_addr 为key,限制平均每秒的请求为20个, 超出频率返回503错误
    #1M能存储16000个状态,rete的值必须为整数,
    #如果限制两秒钟一个请求,可以设置成30r/m
    limit_req_zone $binary_remote_addr zone=allips:10m rate=20r/s;
    ...
    server{
        ...
        location / {
            ...
            #限制每ip每秒不超过20个请求,漏桶数burst为5
            #brust的意思就是,如果第1秒、2,3,4秒请求为19个,
            #第5秒的请求为25个是被允许的。
            #但是如果你第1秒就25个请求,第2秒超过20的请求返回503错误。
            #nodelay,如果不设置该选项,严格使用平均速率限制请求数,
            #第1秒25个请求时,5个请求放到第2秒执行,
            #设置nodelay,25个请求将在第1秒执行。
            limit_req zone=allips burst=5 nodelay;
            ...
        }
        ...
    }
    ...
}

上面的配置中key是 $binary_remote_addr ,所以说是根据IP来限速,其实不光是IP,也可以是$server_name等其他的Nginx变量或者是自定义的变量,根据需求来配置。

限制单个IP同一时间的连接数

http{
    ...
    #定义一个名为one的limit_zone,大小10M内存来存储session,
    #以$binary_remote_addr 为key,也就是IP
    #且只能放在http作用域
    limit_conn_zone  $binary_remote_addr  zone=one:10m;  
    ...
    server{
        ...
        location {
            ...
           limit_conn one 20;          #连接数限制,超过限制返回503错误
           #带宽限制,对单个连接限数,如果一个ip两个连接,就是500x2k
           #limit_rate 500k;            
            ...
        }
        ...
    }
    ...
}

根据参数,uri中特殊字符来限速

由于用户都是NAT之后来连接服务器,所以根据IP来限制没法做,但是每个用户访问时的URL都会带有用户唯一的参数,这时候使用url参数比ip更有限速意义。 下面的配置的含义是 /hello这个请求中,lan参数相同的请求每秒钟只能请求一次,可以类比的把lan参数当成用户的IP,每个IP每秒只能成功访问一次服务端来理解。

这里还可以延伸为使用 nginx可以拿到的参数限速,例如通过 ip地址+ua限速,通过header中的特殊标记+ip限速等,比较复杂逻辑的通过 openresty 会更方面一些

其他的选择

  • lua-resty-limit-traffic 基于openresty 的限速模块,使用lua实现更复杂的业务控制

  • ngx-limit-req2 这个哥们写的一个C 模块

测试配置

map $arg_lan $name {
    default $arg_lan;
    "~*python" python;
    "~*golang" golang;
}
limit_req_zone $name zone=xspython:10m rate=1r/s;
server {
    listen       8001;
    server_name  localhost;
    location /hello {
        limit_req_log_level notice;
            limit_req zone=xspython burst=1 nodelay;
        echo hello $name;
    }
    location ~ /hi {
        #不限速对照
        echo hi;
    }
}

简单测试脚本

#!/bin/bash
#limit_test1.sh
#orangleliu
#第一种情况 同一个key,查看是否能限速
#第二种情况 不同key,是否能顺利通过
#主要是根据access.log来判断结果
op=$1
url="http://127.0.0.1:8001/hello?lan="
if [ $1 = "1" ];then
    echo "情况一"
    for i in {1..5};do
        for j in {1..5};do
            curl "${url}python"
        done
        sleep 1
    done
else
    echo "情况二"
    lanname=(python java golang c lua)
    for i in {1..5};do
        for j in "${lanname[@]}"; do
            curl "${url}${j}"
        done
        sleep 1
    done
fi

相关内容

    暂无相关文章