欢迎大家关注本博,同时欢迎大家评论交流,可以给个赞哦!!!
ngx_http_limit_conn_module用于限制每个已定义关键字的连接数,特别是来自单个IP地址的连接数。
并非所有连接都被计数,仅当连接是服务器正在处理的请求且已读取整个请求头时,才对连接进行技术。
为什么需要限流
限流实际是控制服务入口的流量,防止服务出现流量过载导致服务宕机等问题。
用户数量庞大的应用,尤其是互联网应用,面对庞大的用户群体,在高并发场景下,因为请求过多,压力转移到服务器,容易导致服务宕机等故障,因此需要使用限流对服务进行保护。
· 瞬时大量用户访问服务器,导致服务器超载而宕机。
· 恶意请求攻击服务器,导致服务器超载而宕机。
· 对于特定应用,例如爬虫等,针对性的进行分析、限流。
什么是连接限流
Http协议建立在Tcp协议之上,要建立Http连接,需要先进行Tcp三次握手,然后才能建立Http连接,在Http连接之上进行请求和响应。
连接限流模块主要限制的就是Http连接,由于Http协议的发展,目前Http可以保持长连接,在一个连接中进行多次请求和响应,此时连接限流模块计数时,仅会把这种情况计作1,不会关心请求数量。
连接限流模块 语法即语义
limit_conn
语法:limit_conn zone number;
语义:设置共享内存区域和给定键值的最大允许连接数。当超过此限制时,服务器将返回错误响应请求。
当且仅当limit_conn当前级别上未定义任何指令时,这些指令才从先前的配置级别继承。
limit_conn_dry_run
语法:limit_conn_dry_run on | off;
语义:启用空运行模式。在此模式下,连接数不受限制,但是,在共享内存区域中,过多连接的数将照常计算。
limit_conn_log_level
语法:limit_conn_log_level info | notice | warn | error;
语义:为服务器限制连接数的情况设置所需的日志记录级别。
limit_conn_status
语法:limit_conn_status code;
语义:设置状态代码以响应被拒绝的请求作为返回。
limit_conn_zone
语法:limit_conn_zone key zone=name:size;
语义:设置共享内存区域的参数,该参数将保留各种键的状态。特别是,状态包括当前的连接数。该key可以包含文本,变量,他们的组合。具有空键值的请求不予考虑。
key:请求匹配的规则,若客户端请求匹配key,则进入zone。常用的键包括:$ binary_remote_addr(客户端地址(二进制形式),对于IPv4地址,值的长度始终为4个字节,对于IPv6地址,值的长度始终为16个字节)、$ uri(请求中的当前URI)、$ request_uri(完整的原始请求URI(带有参数))、$server_name(接受请求的服务器的名称)。
limit_zone
语法:limit_zone name $variable size;
语义:该指令在1.1.8版中已过时,在1.7.6版中已删除。应当使用等效的limit_conn_zone指令。
连接限流模块 示例
在默认nginx.conf基础上增加limit_conn相关配置:
worker_processes 1;
error_log logs/error.log;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
# $binary_remote_addr:客户端地址(二进制形式),对于IPv4地址,值的长度始终为4个字节,对于IPv6地址,值的长度始终为16个字节.
# 定义名为'remote_addr_zone'的共享内存区域,用于针对单个客户端地址计数.
limit_conn_zone $binary_remote_addr zone=remote_addr_zone:1m;
# $server_name:接受请求的服务器的名称.
limit_conn_zone $server_name zone=server_name_zone:1m;
server {
listen 80;
server_name localhost;
location / {
limit_conn remote_addr_zone 1;
limit_conn server_name_zone 1;
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
接下来,使用ab(Apache Bench)进行并发压力测试,本人使用windows版本:
d:
cd K:\Service\Apache Bench\Server\httpd-2.4.41-win64-VS16\Apache24\bin
ab -n 10000 -c 100 http://192.168.20.9/index.html
上面模拟100个客户端、10000个请求,执行之后,查看ab的统计结果如下图:
需要注意的是,当-c和-n设置较小时,可能无法出现上面的情况,需要多次尝试才可以达到效果。若是希望尽快达到效果,可以根据个人机器情况,适当提高-c和-n的值。
可以看到,ab共发送了10000个请求,其中69次非2xx响应码,此时,查看Nginx的error.log(/usr/local/nginx/logs/error.log),会发现日志中在提示下图中的信息,说明limit_conn连接限流模块开始起作用了。
连接限流模块 完整配置
上面示例中,只配置了limit_conn_zone和limit_conn指令,其他指令未做展示,下面提供连接限流模块的完整配置,具体验证,可以自行验证。
worker_processes 1;
error_log logs/error.log;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
# $binary_remote_addr:客户端地址(二进制形式),对于IPv4地址,值的长度始终为4个字节,对于IPv6地址,值的长度始终为16个字节.
# 定义名为'remote_addr_zone'的共享内存区域,用于针对单个客户端地址计数.
limit_conn_zone $binary_remote_addr zone=remote_addr_zone:1m;
# $server_name:接受请求的服务器的名称.
limit_conn_zone $server_name zone=server_name_zone:1m;
# 1.1.8版本已过时,1.7.6版本已删除,与limit_conn_zone等效.
# limit_zone
server {
listen 80;
server_name localhost;
location / {
# 指定连接限流模块日志级别.
limit_conn_log_level error;
# 指定限流时返回Http响应码.
limit_conn_status 503;
# 指定每个客户端地址并发连接数为1.
limit_conn remote_addr_zone 1;
# 指定当前服务器并发连接数为1.
limit_conn server_name_zone 1;
# 启用空运行模式。在此模式下,连接数不受限制,但是,在共享内存区域中,过多连接的数将照常计算.
# limit_conn_dry_run off;
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
虽然ngx_http_limit_conn_module提供了很多指令,但某些应用场景十分有限,在应用时使用默认值即可,没必要太纠结所有指令是否齐全。
总结
应用上线后,需要复制机制对应用进行长期监视和分析,若出现服务过载的情况,需要酌情分析,当代理或负载配置时,针对某些可能导致服务宕机的业务进行限流,在影响某些客户使用体验的情况下,保证绝大部分用户可以正常且无误的使用应用。
若文中存在错误和不足,欢迎指正!
本博微信公众号“超哥说码”,欢迎大家订阅,公众号正在完善中,会及时将更优质的博文推送于您!