Nginx - 限流模块 ngx_http_limit_conn_module

用户数量庞大的应用,尤其是互联网应用,面对庞大的用户群体,在高并发场景下,因为请求过多,压力转移到服务器,容易导致服务宕机等故障,因此需要使用限流对服务进行保护。
瞬时大量用户访问服务器,导致服务器超载而宕机。
恶意请求攻击服务器,导致服务器超载而宕机。
对于特定应用,例如爬虫等,针对性的进行分析、限流。

1 限制单IP并发访问数量

ngx_http_limit_conn_module模块用于限制连接数量,特别是来自单个IP地址的连接数量。并非所有的连接都被计数。只有当服务器正在处理的请求并且已经读取了整个请求头时,连接才被计数。

The ngx_http_limit_conn_module module is used to limit the number of connections per the defined key, in particular, the number of connections from a single IP address.

例子:

http {
    limit_conn_zone $binary_remote_addr zone=addr:10m;
    ...
    server {
        ...
        location /download/ {
            limit_conn addr 1;
        }
}

$binary_remote_addr对于IPv4地址,变量的大小始终为4个字节,对于IPv6地址则为16个字节。存储状态在32位平台上始终占用32或64个字节,在64位平台上占用64个字节。一个兆字节的区域可以保持大约32000个32字节的状态或大约16000个64字节的状态。如果区域存储耗尽,服务器会将错误返回 给所有其他请求。10M可存储160000个状态
设置给定键值的共享内存区域和最大允许连接数。超过此限制时,服务器将返回 错误以回复请求。

测试时如果请求处理过快,则不会出现效果,可下载文件进行测试:

location 里面添加下载目录  alias /home/

ab -r -k -c 3 -n 2000 http://192.168.1.10:8010/DOWN.zip

后台日志:

2020/04/20 12:39:40 [error] 1966#0: *722 limiting connections by zone "addr", client: 192.168.1.10, server: localhost, request: "GET /DOWN.zip HTTP/1.0", host: "192.168.1.10:8010"

注意:如果要同时限制  the total number of connections to the virtual server:

limit_conn_zone $binary_remote_addr zone=perip:10m;
limit_conn_zone $server_name zone=perserver:10m;
server {
    ...
    limit_conn perip 10;
    limit_conn perserver 100;
}

the following configuration will limit the number of connections to the server per a client IP and, at the same time,

the total number of connections to the virtual server:


2 限制单IP访问速度

ngx_http_limit_req_module模块(0.7.21)用于限制每一个请求的处理速率,特别是从一个单一的IP地址的请求的处理速率。

例子:

http {
    limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
    ...
    server {
        ...
        location /search/ {
            limit_req zone=one burst=5;
        }
}

代表的含义是:平均每秒不超过1个请求,并且突发不超过5个请求,也就是同时可处理6个请求,超过的请求delay,慢慢处理。如果不想delay 则后面可加  nodelay 代表超出最大连接数的请求直接丢弃,不保存在队列,返回503 

limit_req zone=one burst=5 nodelay;

设置共享内存区域和请求的最大突发大小。如果请求速率超过为某个区域配置的速率,则它们的处理会延迟,从而使请求按指定速率处理。过多的请求被延迟,直到它们的数量超过最大突发大小,在这种情况下请求被终止并出现错误。

测试:

请求速度测试:
ab -r -k -c 10 -n 100 http://192.168.1.10:8010/

日志:

 2021/04/20 13:19:24 [error] 5305#0: *764 limiting requests, excess: 5.984 by zone "one", client: 192.168.1.10, server: localhost, request: "GET / HTTP/1.0", host: "192.168.1.10:8010"

总结:

http {
....
limit_conn_zone $binary_remote_addr zone=addr:10m;#记录160000个请求 超过将返回失败
limit_conn_zone $server_name zone=perserver:10m;
limit_req_zone $binary_remote_addr zone=why_req:10m rate=1r/s; #共享内存区大小,单个IP平均每秒请求数不能超过5个
.....
location {
limit_conn addr 1;
limit_conn perserver 1;
limit_req zone=why_req burst=1; #nodelay超出最大连接数直接丢弃,不保存在队列
.....
}
}

参考:

ngx_http_limit_conn_module模块文档:
http://nginx.org/en/docs/http/ngx_http_limit_conn_module.html
ngx_http_limit_req_module模块文档:
http://nginx.org/en/docs/http/ngx_http_limit_conn_module.html


posted on 2021-04-20 12:58  TrustNature  阅读(406)  评论(0编辑  收藏  举报