Nginx HTTP模块篇 limit_conn和limit_req模块 (十二)-张柏沛IT博客

正文内容

Nginx HTTP模块篇 limit_conn和limit_req模块 (十二)

栏目:Linux 发布时间:2020-02-15 20:26 浏览量:321

limit_conn和limit_req是11个处理请求阶段中的preaccess阶段。


limit_conn 模块
用于限制每个客户端的并发连接数

生效范围:
全部worker进程(基于共享内容)
限制的有效性取决于key的设计,依赖于realip获取到的真实客户端ip

limit_conn_zone指令:用于定义共享内存和key关键字
上下文:http
limit_conn_zone key zone=name:size;     # key一般是真实客户端ip,zone就是共享内存,那么是共享内存的名字,size大小


limit_conn指令:限制并发连接数
上下文:server,http,location
limit_conn zone_name number;     #zone_name就是刚刚定义的共享内存的名字

limit_conn_log_level指令:发生限制并发时的日志级别,当限制了并发,就会记录到日志中,默认[error]级别。
上下文:server,http,location
limit_conn_log_level error|info|notice|warn;

limit_conn_status指令:限制发生时返回客户端的错误码
上下文:server,http,location
limit_conn_status code;     # 默认503

小实验:

# 创建共享内存
limit_conn_zone $binary_remote_addr zone=addr:10m;      # $binary_remote_addr变量存放着二进制格式的IP地址,创建了一个名为addr,大小10m的共享内存 

server {
    server_name limit.zbpblog.com;
    listen 8080;
    root /var/www/html;
    error_log /var/www/html/error.log info;
    
    location / {
        #发生限制时返回500状态码
        limit_conn_status 500; 
        
        #发生限制时记录warn级别的日志
        limit_conn_log_level warn;
        
        #限制每秒传输50字节的内容,这样容易实现并发
        limit_rate 50;
        
        # 限制单个ip最大并发数为1,只要同一个ip的并发连接超过1个就会触发限制。
        limit_conn addr 1;
    }
}

/var/www/html/index.html的内容写多一点,这样一个请求就会花较长的时间才能请求完,在这段时间内马上再开一个窗口再请求一次就可以模拟2个并发。

本地开2个cmd,都执行命令:
curl http://limit.zbpblog.com:8080

第一个显示index.html内容
第二个报500错误

试验成功。


limit_req模块

该模块用于限制同一个IP在特定时间内的请求数。作用范围也是所有worker进程,所以也需要分配共享内存。

使用算法leaky bucket。可以想象流量是一个水龙头,limit_req是一个桶,当有突发流量的时候,如果没有桶水龙头的水流的太快,服务器处理不过来;有桶的时候,水龙头的水流入桶中,桶的水再慢速的流出来,水龙头的水流入桶的速度比水流出桶的速度快,此时桶就会蓄水,这样bucket就限制了流速。如果桶满了,水龙头就关掉不再放水,也就是不再接受请求(返回一个503状态码)。等桶里面有空间了再继续放水。
使用这个算法,可以把突发流量变成每秒恒定的速度处理请求。可以在配置文件中定义这个“桶”有多大。


limit_req_zone key zone=name:size rate=rate;    #定义共享内存,限速,rate单位r/s或r/m即限制每秒或每分钟处理的请求数

limit_req zone=name [burst=number] [nodelay]    # 限制请求
其中burst就是桶的大小,即桶内可以存放多少个多出来的请求数
默认burst=0
nodelay 对burst中的请求不采取延时处理,而是立刻处理 

limit_req_log_level         # 同 limit_conn_log_level

limit_req_status            # 同 limit_conn_status


问:如果同时设置了limit_conn和limit_req,即同时限制了限制并发数和限速,哪个先生效?
根据上面的流程图,limit_req在limit_conn之前。所以limit_req先生效,而且一旦触发限速,limit_conn就不会再检测,因为此时已经返回503

小实验:

# 定义两个共享内存 conn 和 req
limit_conn_zone $binary_remote_addr zone=conn:10m;
limit_req_zone $binary_remote_addr zone=req:10m rate=2r/m;     # 限速每分钟只通过两个请求

server {
    listen 8080;
    server_name limit.zbpblog.com;
    root /var/www/html;
    error_log /var/www/html/error.log info;
    
    location / {
        #limit_conn conn 1;
        #limit_conn_status 500;
        #limit_rate 50;
        #limit_conn_log_level warn;
        limit_req zone=req;
        #limit_req zone=req burst=3 nodelay;
    }
}

在cmd中连续请求2次
curl http://limit.zbpblog.com:8080
发现第二次请求的时候就报503

使用 limit_req zone=req burst=3 nodelay; 再试一下,此时可以多请求个3,4次。

限速和限制并发数在 preaccess 阶段之前不生效

请区分 limit_conn 和 limit_req 的区别,一个是限制单ip用户的并发连接数,一个是限制单ip用户规定时间内的请求数。前者限制的是TCP连接数量,后者限制的是http请求数量。



如果您需要转载,可以点击下方按钮可以进行复制粘贴;本站博客文章为原创,请转载时注明以下信息

张柏沛IT技术博客 > Nginx HTTP模块篇 limit_conn和limit_req模块 (十二)

热门推荐
推荐新闻