linux系统nginx流量控制

发布时间:2024年01月24日

概念

流量限制(rate-limiting)。可以用来限制用户在给定时间内HTTP请求的数量。
流量限制可以用作安全目的。
通过将传入请求的速率限制为真实用户的典型值,并标识目标URL地址(通过日志),还可以用来抵御DDOS攻击。
该功能被用来保护上游应用服务器不被同时太多用户请求所压垮。

nginx如何限流

流量限制使用漏桶算法(leaky bucket algorithm),该算法在通讯和分组交换计算机网络中广泛使用,用以处理带宽有限时的突发情况。
同样,在请求处理方面,水代表来自客户端的请求,水桶代表根据”先进先出调度算法”(FIFO)等待被处理的请求队列,桶底漏出的水代表离开缓冲区被服务器处理的请求,桶口溢出的水代表被丢弃和不被处理的请求。

正常访问

server {
    listen 80;
    server_name localhost;

    location /{
                root    /usr/share/nginx/html;
                index   index.html index.html;
                }
}

基本限流

limit_req_zone指令定义了流量限制相关的参数,而limit_req指令在出现的上下文中启用流量限制

limit_req_zone指令通常在HTTP块中定义,使其可在多个上下文中使用,它需要以下三个参数:

  • Key :定义应用限制的请求特性。

  • Zone :定义用于存储每个IP地址状态以及被限制请求URL访问频率的共享内存区域。

  • Rate :定义最大请求速率。

limit_req_zone指令设置流量限制和共享内存区域的参数,但实际上并不限制请求速率。所以需要通过添加

limit_req指令,将流量限制应用在特定的location或者server块。

流量限制配置两个主要的指令,limit_req_zone和limit_req

limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
#$binary_remote_addr   记录二进制的ip
#zone=mylimit:10m      限制规则的名字:从内存中拿取10m     名字在limit_req中直接调用
#rate=10r/s            每秒最多处理十个请求

server {
    listen 80;
    server_name localhost;

    location /{
                root    /usr/share/nginx/html;
                index   index.html index.html;
                limit_req zone=mylimit;
                }
}

增加缓冲配置

处理请求速率限制在每秒10个请求,超量的请求放入等待队列,等处理有空余位置,从队列中拿取请求

在limit_req中使用burst参数

limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
#$binary_remote_addr   记录二进制的ip
#zone=mylimit:10m      限制规则的名字:从内存中拿取10m     名字在limit_req中直接调用
#rate=10r/s            每秒最多处理十个请求

server {
    listen 80;
    server_name localhost;

    location /{
                root    /usr/share/nginx/html;
                index   index.html index.html;
                limit_req zone=mylimit burst=20;
                }
}

无延迟缓冲配置

使用nodelay参数,将第一批超量的请求添加到缓冲队列,并对第一批缓冲队列请求进行访问,后续再来的请求继续进入缓冲队列进行排队,等待空余请求位置

在burst参数后添加nodelay参数

limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
#$binary_remote_addr   记录二进制的ip
#zone=mylimit:10m      限制规则的名字:从内存中拿取10m     名字在limit_req中直接调用
#rate=10r/s            每秒最多处理十个请求

server {
    listen 80;
    server_name localhost;

    location /{
                root    /usr/share/nginx/html;
                index   index.html index.html;
                limit_req zone=mylimit burst=20 nodelay;
                }
}

注意: 对于大部分部署,使用burstnodelay参数来配置limit_req指令。

高级配置

白名单
geo $lim{
default 1;               //默认
10.12.153.0/24 1;        //指定网段
10.12.153.209 0;         //客户端ip地址
}

map $lim $lim_key{
1 "";                     //那个为空,那个是白名单,不受限制的
0 $binary_remote_addr;    //根据二进制ip限制
}

limit_req_zone $lim_key zone=mylimit:10m rate=10r/s;     //$lim_key调用白名单

geo块将给在白名单中的IP地址对应的$lim变量分配一个值1,给其它不在白名单中的分配一个值0。使用一个映射将这些值转为key

  • 如果$lim变量的值是1,$limit_key变量将被赋值为空字符串
  • 如果$lim变量的值是0,$limit_key变量将被赋值为客户端二进制形式的IP地址

两个指令配合使用,白名单内IP地址的$lim_key变量被赋值为空字符串,不在白名单内的被赋值为客户端的IP地址。当limit_req_zone后的第一个参数是空字符串时,不会应用“流量限制”,所以白名单内的不会被限制。其它所有IP地址都会被限制到每秒10个请求。

location 包含多limit_req指令

可以在一个location块中配置多个limit_req指令。符合给定请求的所有限制都被应用时,意味着将采用最严格的那个限制。

geo $lim{
default 1;               //默认
10.12.153.0/24 1;        //指定网段
10.12.153.209 0;         //客户端ip地址
}

map $lim $lim_key{
1 "";                     //那个为空,那个是白名单,不受限制的
0 $binary_remote_addr;    //根据二进制ip限制
}

limit_req_zone $lim_key zone=mylimit:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=mylimit2:10m rate=5r/s;

server {
    listen 80;
    server_name localhost;

    location /{
                root    /usr/share/nginx/html;
                index   index.html index.html;
                limit_req zone=mylimit burst=20 nodelay;
                limit_req zone=mylimit2 burst=20 nodelay;
                }
}
白名单内的IP网段不会匹配到“流量限制”,但是10.12.153.209会受到mylimit2的限制,并且被限制到每秒5个请求。如果不在白名单内的IP地址两个限制能匹配到,所以应用限制更强的那个:每秒5个请求。

发送给客户错误码

一般情况下,客户端超过配置的流量限制时,Nginx响应状态码为503,可以使用limit_req_status指令来设置为其它状态

geo $lim{
default 1; 
10.12.153.0/24 1;
10.12.153.209 0;
}

map $lim $lim_key{
1 "";                      //那个是空,那个是白名单
0 $binary_remote_addr;
}

limit_req_zone $lim_key zone=mylimit:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=mylimit2:10m rate=10r/s;
server {
    listen 80;
    server_name localhost;

    location /{
				root    /usr/share/nginx/html;
                index   index.html index.html;
                limit_req zone=mylimit burst=20 nodelay;
                limit_req zone=mylimit2 burst=20 nodelay;
                limit_req_status 520;                       //返回错误码改为502
                }
}

配置日志记录

默认情况下,Nginx会在日志中记录由于流量限制而延迟或丢弃的请求

默认情况下,Nginx以error级别来记录被拒绝的请求,如上面示例中的[error]所示(Ngin以较低级别记录延时请求,一般是info级别)。如要更改Nginx的日志记录级别,需要使用limit_req_log_level指令。

geo $lim{
default 1; 
10.12.153.0/24 1;
10.12.153.209 0;
}

map $lim $lim_key{
1 "";                   //那个是空,那个是白名单
0 $binary_remote_addr;
}

limit_req_zone $lim_key zone=mylimit:10m rate=10r/s;             //流量控制1
limit_req_zone $binary_remote_addr zone=mylimit2:10m rate=10r/s; //流量控制2
server {
    listen 80;
    server_name localhost;
    location /{
				root    /usr/share/nginx/html;
                index   index.html index.html;
                limit_req zone=mylimit burst=20 nodelay;     //调用流量控制1
                limit_req zone=mylimit2 burst=20 nodelay;    //调用流量控制2
                limit_req_log_level warn;   //修改被拒绝请求的日志记录级别设置为warn
                }
}
例如该条日志记录

2019/02/13 04:20:00 [error] 120315#0: *32086 limiting requests, excess: 1.000 by zone "mylimit", client: 192.168.1.2, server: nginx.com, request: "GET / HTTP/1.0", host: "nginx.com"

包含的字段有:
limiting requests - 表明日志条目记录的是被“流量限制”请求
excess - 每毫秒超过对应“流量限制”配置的请求数量
zone - 定义实施“流量限制”的区域
client - 发起请求的客户端IP地址
server - 服务器IP地址或主机名
request - 客户端发起的实际HTTP请求
host - HTTP报头中host的值
文章来源:https://blog.csdn.net/qq_59207739/article/details/135726938
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。