我们系统上线后可能会遭遇外部刷接口、暴力测试等行为,尤其是权益类的服务,羊毛党的黄牛特别多。我之前有做过权益兑换系统,这个服务经常会被暴力刷接口,我们可以通过
Nginx 限流机制,熔断刷子流量,从而提升服务可用性。
在 Nginx 中,可以使用 ** 限流 ** (Rate Limiting)功能来控制进入服务器的请求数量。Nginx 提供了两个主要的限流模块:
limit_req模块:限制请求的速率(单位时间内请求的次数)。limit_conn模块:限制并发连接数(每个 IP 地址允许的最大并发连接数)。
这两个模块可以组合使用,用于不同的限流需求,比如限制单位时间内的请求数或并发连接数。
limit_req 模块:限制请求速率
limit_req 模块可以限制特定 IP 地址的请求频率。例如,限制每秒钟一个 IP 地址只能发出一定数量的请求。
配置示例:
http {
# 定义一个限流区域
limit_req_zone$binary_remote_addr zone=req_limit_per_ip:10m rate=10r/s;
server {
listen80;
server_name example.com;
location / {
# 使用上面定义的限流区域,限制请求频率
limit_req zone=req_limit_per_ip burst=20 nodelay;
# 处理正常请求
root /usr/share/nginx/html;
index index.html;
}
}
}
解释:
limit_req_zone定义一个名为req_limit_per_ip的限流区域。$binary_remote_addr是客户端的 IP 地址,以二进制格式存储,可以减少内存消耗。rate=10r/s限制每秒最多 10 次请求。zone=req_limit_per_ip:10m表示存储在内存中,并且该区域的大小是 10MB,可以存储多个 IP 地址的限流信息。limit_req在具体的location配置中启用限流,使用定义好的req_limit_per_ip区域。burst=20允许一定的请求突发,即在瞬间请求量超过正常限速时,最多可以允许 20 个请求超出限速。nodelay表示一旦超出请求限制,就立即拒绝请求,而不是延迟处理。
limit_conn 模块:限制连接数
limit_conn 模块限制每个客户端(每个客户端都有 IP 地址)的并发连接数。这对于防止单个客户端占用过多服务器资源非常有效。
配置示例:
http {
# 定义每个客户端(IP 地址)的最大连接数为 1
limit_conn_zone$binary_remote_addr zone=conn_limit_per_ip:10m;
server {
listen80;
server_name example.com;
location / {
# 限制每个 IP 的最大连接数
limit_conn conn_limit_per_ip 1;
# 处理正常请求
root /usr/share/nginx/html;
index index.html;
}
}
}
解释:
limit_conn_zone定义了一个名为conn_limit_per_ip的区域,用于存储每个 IP 地址的连接信息,zone=conn_limit_per_ip:10m指定了 10MB 的存储空间。limit_conn在location配置中启用连接限制,限制每个 IP 地址只能有一个并发连接。
组合使用 limit_req 和 limit_conn
我们可以同时使用 limit_req 和 limit_conn 来限制请求速率和并发连接数,从而实现更严格的流量控制。
配置示例:
http {
# 定义请求频率限制区域
limit_req_zone$binary_remote_addr zone=req_limit_per_ip:10m rate=5r/s;
# 定义并发连接数限制区域
limit_conn_zone$binary_remote_addr zone=conn_limit_per_ip:10m;
server {
listen80;
server_name example.com;
location / {
# 限制请求速率,每秒最多 5 次请求
limit_req zone=req_limit_per_ip burst=10 nodelay;
# 限制并发连接数,每个 IP 最多允许 1 个连接
limit_conn conn_limit_per_ip 1;
# 处理正常请求
root /usr/share/nginx/html;
index index.html;
}
}
}
解释:
limit_req_zone限制每个 IP 地址的请求频率,每秒最多 5 次请求。burst=10允许 10 次请求的突发。limit_conn_zone限制每个 IP 地址的最大并发连接数为 1。
** 其他常见配置选项 **
burst表示允许的请求突发数量。例如,burst=10允许在短时间内超过规定的请求速率(如每秒 10 次请求),但是请求数不会超过突发限制。nodelay表示一旦请求超过了速率限制,则立即返回 503 错误,而不是延迟处理。
** 限流时返回的状态码 **
当请求超过了限流限制, Nginx 会返回 ** 503 Service Unavailable ** 错误。我们可以通过以下配置定制返回的错误页面:
http {
limit_req_zone$binary_remote_addr zone=req_limit_per_ip:10m rate=5r/s;
server {
listen80;
server_name example.com;
location / {
limit_req zone=req_limit_per_ip burst=10 nodelay;
# 设置请求超限时返回的页面
error_page503 /custom_503.html;
root /usr/share/nginx/html;
index index.html;
}
}
}
在这个配置中,当请求超过限制时,Nginx 会返回自定义的 503 页面 /custom_503.html 。
如何查看访问日志中的 503 错误
通过以下命令行查看:搜索日志中 503 字符
grep " 503 " /var/log/nginx/access.log