nginx 的限流特技

2019-05-28  本文已影响0人  OOM_Killer

nginx的限流是十分重要的一个技能,当大规模的流量洪峰到来,后端应用有可能被打垮。需要在Nginx这一层上作出限制。防止流量达到后端,雪上加霜。
nginx的限流模块是在 preaccess 阶段,这个阶段有两个模块,分别是 limit_req 和 limit_conn。一个是限制每秒请求数的,一个是限制每秒连接数的。

limit_conn 模块

这个模块会在全部的worker进程中生效(基于共享内存)。
限流是基于realip 模块提供的 $remote_addr 这个变量提供的真实的客户端ip地址。
为了限速首先需要定义一块共享内存(包括大小),以及key关键字。

# 定义共享内存,key 表示用什么来限速(一般是客户端ip)
Syntax: limit_conn_zone key zone=name size;

# 限制并发连接数  
Syntax:limit_conn zone number;

# 限制发生时的日志级别
Syntax:limit_conn_log_level info|notice|warn|error

# 限制发生后的客户端返回错误码
Syntax:limit_conn_status code   (默认是 503)  

一个最简单的配置。

limit_conn_zone $binary_remote_addr zone=myaddr:10m;

server {
        server_name limit.loki.wjx;
        root html/;

        location / {
                limit_conn_status 500;
                limit_conn_log_level warn;
                limit_conn myaddr 1;
        }
}

这个配置中的 $binary_remote_addr 是十进制的客户ip地址,zone共享内存起名叫做myaddr,开了10m。
这里针对客户端ip限制每个客户端的最大并发数是1 。

limit_req 模块

同样 limit_req 也是基于共享内存的,生效于全部的worker进程。
其用的是 leaky bucket 算法
限制突发流量
限制突发流量的方式就是用到了这个模块。假设有个峰值12Mbps。而平时流量只有2Mbps。用了 leaky bucket 算法可以把流量限制成恒定的3-4Mbps。
当 bursty 盆 满了之后,请求会被立刻返回错误。若没有满,则流量暂存盆中,响应会变慢。

#定义共享内存,key关键字以及限制速率
Syntax: limit_req_zone key zone=name:size rate=rate;

#限制并发连接数
Syntax:limit_req zone=name [burst=number] [nodelay];
burst 默认为0 。
nodelay会在瞬时提供处理(burst + rate)个请求的能力,请求超过(burst + rate)的时候就会直接返回503,永远不存在请求需要等待的情况。(这里的rate的单位是:r/s)

# 限制发生时的日志级别
Syntax:limit_req_log_level info|notice|warn|error

# 限制发生后的客户端返回错误码
Syntax:limit_req_status code   (默认是 503)  

一个简单的配置。

limit_req_zone $binary_remote_addr zone=one:10m rate=3r/m;

server {
        server_name limit.loki.wjx;
        root html/;

        location / {
                limit_req_status 500;
                limit_req_log_level warn;
                limit_req zone=one;
                #limit_req zone=one burst=3;
                #limit_req zone=one burst=3 nodelay;
                
        }
}

这段配置写的是限制每分钟三个请求。
当启用 limit_req zone=one; 每秒3个。
当启动 limit_req zone=one burst=3; 每秒3个,桶里最大存3个。
当启用nodelay时,超出3个请求后直接返回失败,无视桶的存在。

接下来是实战中的例子

##### limit req
map $http_user_agent $agent {
    default "";
    ~*apachebench $http_user_agent;
    ~*spider $http_user_agent;
    ~*bot  $http_user_agent;
    ~*slurp $http_user_agent;
    ~WinHttp\.WinHttpRequest $http_user_agent;
}
#limit_conn_zone $agent zone=ua_test:10m;
limit_req_zone $agent zone=req_ua:10m rate=1r/m;

geo $whiteiplist  {
    default 1;
    127.0.0.1 0;
    10.0.0.0/8 0;
}

map $whiteiplist  $limit {
    1 $binary_remote_addr;
    0 "";
}

limit_req_zone $limit zone=ac_limit:500m rate=8r/s;

限速

location / {
        limit_req zone=req_ua burst=3 nodelay forbid_action=@excess;
        limit_req zone=ac_limit burst=16 nodelay forbid_action=@excess;
        proxy_pass http://xxxxx_backend;
    }

location @excess {
            set $xlocation 'excess';
            return 204 "{\"status\":1}";
    }

limit_rate 指令

limit_rate 不是一个limit_conn 和 limit_req 提供的限速指令,这是http_core_module 提供的。其功能也十分的简单。 限制每秒传输字节数。例如:

location /flv/ {
    flv;
    limit_rate_after 20m;
    limit_rate       100k;
}

表示在下载前20m时不限速,后续限速100k/s。

上一篇 下一篇

猜你喜欢

热点阅读