侧边栏壁纸
博主头像
张种恩的技术小栈博主等级

绿泡泡:___zze,添加备注来意

  • 累计撰写 748 篇文章
  • 累计创建 65 个标签
  • 累计收到 39 条评论

目 录CONTENT

文章目录

Nginx(10)之连接及请求限制

zze
zze
2020-03-04 / 0 评论 / 0 点赞 / 913 阅读 / 7295 字

连接限制

ngx_http_limit_conn_module 模块用于限制每个已记录键同一时刻的连接数,常用来根据 IP 地址限定每个客户端的连接数。

并非所有连接都被计数,仅有那些已经被服务器处理并且整个请求头已被读取保存的连接才会进行计数。

下面看一下该模块的指令:

  • limit_conn_zone:设定一个名称引用指定大小的内存空间,这个名称用于后续使用。
语法: limit_conn_zone key zone=name:size;
	key: 内存中保存的 key 值。
	name: 引用该片内存的参数名。
	size: 声明的内存大小。
默认: —
可使用的上下文: http

在此,key 值一般是客户端 IP 地址,$binary_remote_addr$remote_addr 都是引用 IP 地址的宏,它们的区别如下:

  • $remote_addr 变量的大小为 7 ~ 15 个字节不等,存储状态信息在 32 位平台上占用 32 或 64 字节的内存,在 64 位平台上始终占用 64 字节的内存;
  • $binary_remote_addr 变量的大小对于 IPv4 地址始终为 4 个字节,对于 IPv6 地址始终为 16 个字节。在 32 位平台上,存储状态信息始终占据 32 或 64 字节,在 64 位平台上,存储状态始终占据 64 字节。

一个 1 兆字节的区域可以保留大约 3.2 万个 32 字节状态或大约 1.6 万个 64 字节状态。
如果存储空间用尽,服务器将把错误返回给所有其他请求。

  • limit_conn:设置共享内存区域中给定键值的最大允许连接数。当超过此限制时,服务器将返回错误以回复请求。

这里的限制对象需要根据使用 limit_conn_zone 设定空间时使用的 key 来判断:

  • 如果给定 key 键值是客户单 IP 地址(如 $binary_remote_addr$remote_addr),那么就 是对每个 IP 连接数的限制;
  • 如果给定键主机名(如 $server_name),那么就是对当前虚拟主机连接数的限制。
语法: limit_conn zone number;
	zone: 已通过 limit_conn_zone 设定的空间名称。
	number: 限制同一时刻的连接数量;
默认: —
可使用的上下文: http, server, location

当前级别上没有 limit_conn 指令但上级定义了该指令时,会从上级继承限制。

  • limit_conn_dry_run:启用试运行模式。在这种模式下,连接的数量是不受限制的,但是,在共享内存区域中,过量连接的数量通常会被计算在内。
语法: limit_conn_dry_run on | off;
默认: limit_conn_dry_run off;
可使用的上下文: http, server, location
这个指令出现在 1.17.6 版本。
  • limit_conn_log_level:设定连接数超出限制时的日志记录级别。
语法: limit_conn_log_level info | notice | warn | error;
默认: limit_conn_log_level error;
可使用的上下文: http, server, location
这个指令出现在 0.8.18 版本。
  • limit_conn_status:设定连接数超出限制时拒绝连接的响应状态码。
语法: limit_conn_status code;
默认: limit_conn_status 503;
可使用的上下文: http, server, location
这个指令出现在 1.3.15 版本

下面来看一个示例:

http {
    limit_conn_zone $binary_remote_addr zone=perip:10m;
    limit_conn_zone $server_name zone=perserver:10m;
    server { # server1
        listen 8080;
        server_name test1.zze.xyz;

        location / {
            stub_status;
            limit_conn perip 1;
            limit_conn perserver 10;
        }
    }

    server { # server2
        listen 8081;
        server_name test2.zze.xyz;

        location / {
            stub_status;
            limit_conn perip 3;
            limit_conn perserver 100;
        }
    }
}

注意,该配置设定空间的 limit_conn_zone 指令需要在 http 上下文定义,所以需要在主配置文件中做修改,server 上下文依旧可以在 conf.d 下单独定义,这里为演示简单就写一起了。

上述配置的含义:

  • server1 中每一个 IP 同一时刻仅能建立 1 个连接,server1 主机同一时刻只能接收最多只能建立 10 个连接;
  • server2 中每一个 IP 同一时刻既能建立 3 个连接,server2 主机同一时刻只能接收最多 100 个连接;

请求限制

ngx_http_limit_req_module 模块(0.7.21)用于限制每个已定义键的请求处理速率,常用来根据 IP地址限定客户端请求的处理速率,使用“leaky bucket”完成限制。

  • limit_req_zone:设定一个名称引用指定大小的内存空间,并指定存在于这个空间中的键对应的请求的速率,这个名称用于后续使用。
语法: limit_req_zone key zone=name:size rate=rate [sync];
	key: 内存中保存的 key 值。
	name: 引用该片内存的参数名。
	size: 声明的内存大小。
	rate: 请求处理速率,如 1q/s 表示每秒处理一个请求,时间单位还支持分钟(m)。
	sync: 启用共享内存区域的同步,1.15.3 版本后支持。
默认: —
可使用的上下文: http

在此,key 值一般是客户端 IP 地址,$binary_remote_addr$remote_addr 都是引用 IP 地址的宏,$binary_remote_addr 变量的大小对于 IPv4 地址始终为 4 个字节,对于 IPv6 地址始终为 16 个字节。存储状态信息在 32 位平台上始终占据 64 字节,在 64 位平台上始终占据 128 字节。
建议使用 $binary_remote_addr 替代 $remote_addr
一个 1 兆字节的区域可以保留约 1.6 万个 64 字节状态或约 8000 个 128 字节状态。
如果存储空间已用尽,则将删除最近最少使用的状态信息。
例:

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

这里的请求状态信息记录在名称为 one10m 大小空间,并且该空间的平均请求处理速率不能超过每秒 1 个请求。
速率以每秒请求数(r/s)指定。如果希望速率小于每秒一个请求,则以每分钟请求数(r/m)来指定。例如,每秒半请求为 30r/m

  • limit_req:设置共享内存区域中请求的最大突发大小。如果请求速率超过为区域配置的速率,则会延迟其处理,以便以定义的速率继续处理请求。延迟的请求的数量如果超过最大突发大小,那么请求会因错误而终止,默认情况下,最大突发大小等于零。
语法: limit_req zone=name [burst=number] [nodelay | delay=number];
	name: 已通过 limit_req_zone 设定的空间名称。
	number: 允许的突发请求数量,同一时刻最大的处理请求数量 = 平均请求数量 + 允许的突发请求数量。
	nodelay: 不延迟请求,立马响应拒绝。
	delay=number: 允许延迟处理的请求数,默认值为 0 表示所有多余的请求都延迟处理。
默认: —
可使用的上下文: http, server, location

当前级别上没有 limit_req 指令但上级定义了该指令时,会从上级继承限制。

  • limit_req_dry_run:启用空运行模式。在这种模式下,请求处理速率不受限制,但是,在共享内存区域中,过多请求的数量将照常计算。
语法: limit_req_dry_run on | off;
默认: limit_req_dry_run off;
可使用的上下文: http, server, location
这个指令出现在 1.17.1 版本。
  • limit_req_log_level:设定请求数超出限制时的日志记录级别,延迟记录比拒绝记录低一个级别。
语法: limit_req_log_level info | notice | warn | error;
默认: limit_req_log_level error;
可使用的上下文: http, server, location
这个指令出现在 0.8.18 版本。

例:如果指定了 limit_req_log_level notice,那么延迟级别将会是 info

  • limit_req_status:设定请求数超出限制时拒绝请求的响应状态码。
语法: limit_conn_status code;
默认: limit_conn_status 503;
可使用的上下文: http, server, location
这个指令出现在 1.3.15 版本

下面来看一个示例:

http {
    limit_req_zone $binary_remote_addr zone=perip:10m rate=1r/s;
    limit_req_zone $server_name zone=perserver:10m rate=10r/s;
    server { # server1
        listen 8080;
        server_name test1.zze.xyz;

        location / {
            stub_status;
            limit_req zone=perip burst=5 nodelay;
            limit_req zone=perserver burst=10;
        }
    }

    server { # server2
        listen 8081;
        server_name test2.zze.xyz;

        location / {
            stub_status;
            limit_req zone=perip burst=10 nodelay;
            limit_req zone=perserver burst=15;
        }
    }
}

注意,该配置设定空间的 limit_req_zone 指令需要在 http 上下文定义,所以需要在主配置文件中做修改,server 上下文依旧可以在 conf.d 下单独定义,这里为演示简单就写一起了。

上述配置的含义:

  • server1 对每一个 IP 每秒仅能处理 (1 + 5) 个请求,server1 主机每秒最多只能处理 10 + 10 个请求。
  • server2 对每一个 IP 每秒仅能处理 (1 + 10) 个请求,server2 主机每秒最多只能处理 10 + 15 个请求。
0

评论区