摘要:本文将详细介绍Nginx限流模块的使用方法,包括基于IP地址的限流、基于并发连接的限流以及如何应对突发流量。通过实际案例,帮助读者掌握Nginx限流策略,确保服务器在高并发场景下的稳定运行。
一、引言
在高并发场景下,服务器资源有限,为防止恶意访问或突发流量导致服务器过载,需要对访问频率进行限制。Nginx作为一款高性能的Web服务器,提供了丰富的限流模块,可以帮助我们实现这一需求。本文将重点介绍Nginx限流模块的使用方法。
二、Nginx速率限流
Nginx使用 ngx_http_limit_req_module 模块进行限流,基于漏桶算法原理实现。主要包括以下三个指令:
- limit_req_zone:定义限流区域,用于存储客户端请求的计数信息。
- limit_req:限制每个请求的处理速率。
- limit_req_status:设置限流时返回给客户端的错误状态码。
定义限流空间
语法:limit_req_zone key zone rate
- key:定义限流对象,如binary_remote_addr表示基于remote_addr(客户端IP) 来做限流,binary_ 的目的是压缩内存占用量。
- zone:定义共享内存区来存储请求计数信息, ipRateLimit:10m 表示创建一个名字为ipRateLimit,大小为10M的内存区域。1M能存储16000 IP地址的访问信息,10M可以存储16W IP地址访问信息。
- rate:用于设置最大访问速率,rate=10r/s 表示每秒最多处理10个请求
案例:
limit_req_zone $binary_remote_addr zone=ipRateLimit:10m rate=10r/s;
这里,$binary_remote_addr表示客户端IP地址,zone=ipRateLimit:10m表示创建一个名为ipRateLimit的共享内存区域,大小为10MB,rate=1r/s表示每秒最多处理10个请求。
应用限流规则
我们需要先配置限流缓存空间,然后在对应请求的location段下面添加以下配置:
语法:
limit_req zone=ipRateLimit burst=5 nodelay;
limit_req_status 429;
zone=ipRateLimit
:指定一个共享内存区域,需要在http段或server段中先定义这个区域burst=5
:设置一个缓冲区大小,允许短时间内超过限制的请求数量。在这个例子中,缓冲区大小为5,意味着如果客户端在短时间内发送了超过限制的请求,Nginx会允许最多5个请求进入缓冲区等待处理。nodelay
:当启用这个参数时,Nginx会立即处理缓冲区中的请求,而不是按照配置的速率(rate
)延迟处理。如果不使用nodelay
,即使缓冲区中有请求,Nginx也会按照配置的速率来处理请求。limit_req_status
:设置返回给客户端的错误状态码
这里,zone=ipRateLimit指定使用前面定义的限流区域,burst=5表示允许短时间内超过限制的请求数量为5个,nodelay表示立即处理超出限制的请求。如果请求超出了限制,Nginx将返回429状态码(Too Many Requests)
实战配置
http {
# 定义限流区域配置
limit_req_zone $binary_remote_addr zone=one:10m rate=10/s;
server {
listen 80;
server_name www.changai.online;
root /opt/software/run/web/dist;
index index.html;
location / {
# 应用限流规则
limit_req zone=one burst=20 nodelay;
limit_req_status 429;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}
重启启动nginx,频繁访问具有限流配置的请求。
error重定向
在Nginx中,当使用limit_req模块进行请求速率限制,并且请求超出了设定的速率限制时,默认情况下Nginx会返回503 Service Temporarily Unavailable错误。如果你想要在这种情况下返回指定的页面(比如一个友好的错误页面),你可以通过error_page指令来实现,通过error_page指令来捕获503错误,并将其重定向到你指定的页面。
http {
# ... 其他http块配置 ...
# 定义请求限制区域
limit_req_zone $binary_remote_addr zone=ipRateLimit:10m rate=10r/s;
server {
listen 80;
server_name localhost;
# 定义错误页面位置
error_page 503 @limit_error;
# 请求速率限制
limit_req zone=ipRateLimit burst=10 nodelay;
# 其他server块配置...
# 捕获503错误并返回指定页面
location @limit_error {
# 指定错误页面的路径,这里假设你的错误页面是/error/503.html
root /path/to/your/error/pages;
try_files /error/503.html =503;
}
location / {
# ... 其他location块配置 ...
}
# ... 其他location块 ...
}
# ... 其他server块或http块配置 ...
}
在这个配置中,当请求因为超出ipRateLimit区域的速率限制而被Nginx拒绝时,Nginx会返回503错误。由于我们在server块中设置了error_page 503 @limit_error;,所以Nginx会捕获这个503错误,并将请求内部重定向到名为@limit_error的location块。在这个location块中,我们指定了错误页面的路径,并通过try_files指令尝试直接服务该页面。如果找不到该页面,则Nginx会再次返回503错误(但通常你已经提供了页面,所以这种情况不会发生)。
请注意,你需要将/path/to/your/error/pages替换为你的错误页面实际所在的目录路径,并将/error/503.html替换为你想要返回的具体错误页面文件名。
效果:
参数详解
1. burst参数作用?
burst参数在Nginx的limit_req模块中非常有用,它为处理突发流量提供了一个缓冲区,当请求以不超过rate定义的速率到达时,Nginx会按照配置的速率处理请求,此时burst不起作用。当请求速率超过rate时,超出的请求会被放入一个队列中,这个队列的大小由burst定义。如果队列已满,额外的请求将被延迟处理或直接丢弃,这取决于是否配置了nodelay参数。
我们需要配置burst来应对一些正常的请求突发情况,对于超出rate速率的请求,如果超出部分请求在burst配置范围内则会被立即处理,但这些请求属于是特殊处理,即使后续又来了请求且在rate速率内也不会马上处理,需要将burst额外占用的请求补上才能处理后续的请求。这既可以解决正常用户的访问,也能避免服务器受到攻击。
2. burst设置多少合适?
burst的大小应小于等于最大预期突发流量:如果你预期会有突发流量,burst的大小应该设置得足够大,以处理这些突发请求,但不应过大,以免影响服务器的稳定性。
rate与burst的比例:通常,rate应该设置得足够低,以确保服务器不会因为请求处理而超载,而burst则应该设置得足够高,以处理正常的突发流量。burst的大小通常是rate的几倍,具体数值取决于应用程序的具体需求和服务器的能力。
处理延迟:如果burst设置得过大,而rate保持不变,那么在处理完burst中的所有请求后,后续请求可能会经历较长的等待时间,因为Nginx会按照rate的速率逐个处理队列中的请求。
2. nodelay参数作用
当启用这个参数时,Nginx会立即处理缓冲区中的请求,而不是按照配置的速率(rate)延迟处理。如果没有使用nodelay参数,Nginx默认会延迟处理超出rate和burst定义的请求数量。这意味着超出部分的请求不会立即被丢弃,而是会被放入队列中,Nginx会按照配置的速率(rate)逐个处理队列中的请求。
如果你使用了nodelay参数,Nginx会立即处理所有在burst大小内的请求,而不会按照rate定义的速率进行延迟。这意味着在burst允许的额外请求数量内,请求会尽可能快地被处理
总结来说,Nginx默认的行为是延迟处理超出rate和burst的请求,除非你使用了nodelay参数或者请求量非常大导致队列溢出,这时超出的请求可能会被丢弃。
三、Nginx连接限流
在Web服务器的高并发场景中,除了限制请求速率外,限制并发连接数也是保护服务器资源的一个重要手段。Nginx的ngx_http_limit_conn_module模块正是为了满足这一需求而设计的。本文将带你了解如何使用这个模块来设置连接限制。
定义限流区域
首先,在Nginx配置文件的http段中定义一个限流区域:
limit_conn_zone $binary_remote_addr zone=connLimitZone:10m;
这里,$binary_remote_addr是客户端IP地址的变量,zone=connLimitZone:10m定义了一个名为connLimitZone的共享内存区域,大小为10MB。
应用限流规则
接下来,在server或location块中应用连接限制:
limit_conn connLimitZone 10;
这个配置表示,对于每个客户端IP,最多允许10个并发连接。
处理超出连接
当客户端的并发连接数超过限制时,Nginx默认的行为是拒绝新的连接。我们可以通过日志记录超出限制的连接,以便于后续分析。
limit_conn_log_level error;
limit_conn_status 503;
这里,limit_conn_log_level设置记录日志的级别,limit_conn_status设置返回给客户端的错误状态码(503表示服务不可用)。
实战配置
http {
limit_conn_zone $binary_remote_addr zone=connLimitZone:10m;
server {
location /download/ {
limit_conn connLimitZone 5;
limit_conn_log_level warn;
limit_conn_status 503;
# 其他location配置...
}
}
}
通过使用ngx_http_limit_conn_module模块,我们可以有效地限制客户端的并发连接数,从而保护服务器免受过多并发连接的影响。合理配置这个模块对于确保服务器在高并发环境下的稳定运行至关重要。在配置时,应根据服务器的实际能力和业务需求来设置合适的连接数限制。
当前连接查看请参考文章:Nginx如何查看当前连接数