Nginx 单机下的请求限制

虽然我们总说项目都是单并发的流量,不过对限流的了解还是非常有必要的,毕竟有些时候,我们的项目可能会遇到一些特殊的情况,比如说,我们的项目可能会遇到一些恶意的请求,这些请求可能会导致我们的服务器崩溃,所以我们需要对这些请求进行限制,这样才能保证我们的服务器不会崩溃。

限流的方式有时候会带来负面效果,这块要自行评估。比如我们的 WFII 使用非常的频繁,我一个公司下面 100 个人都是使用这个 WIFI,那出口都是同一个 IP,然后我们一起去使用某一个服务,短时间内的请求非常多,那我们如果限制的规则要求过低,就会影响正常的使用。另外在爬虫层面,代理 IP 也是人人都会使用的,只是我们一些规则的限制会增加他们的成本,但这两个场景下你要都能解决是很难的,安全的防护是来自方方面面,代码也好,服务器也好,都是需要我们去做好的。

从上面的场景看,我们还是希望在 Nginx 更多是应对正常流量层面,确保业务的正常运行。针对非法恶意或者攻击层面,购买云服务商的安全防护产品是最优的选择。

Nginx 官方的提供了两种限流的模块,分别是 ngx_http_limit_req_modulengx_http_limit_conn_module,这两个模块的区别在于,ngx_http_limit_req_module 是基于请求的限流,而 ngx_http_limit_conn_module 是基于连接的限流。但他们可以限制共同的东西,比如限制整个域名的请求、连接数,或者限制某个接口的请求、连接数,因为我们可以自行设置限制的 key。

来看一下一些场景的使用:

  • 限制整个域名的请求速率

每秒可以接收 100 个请求,突发 50 个请求,超过 50 个请求的部分会被延迟处理。

1
2
3
4
5
6
7
8
9
10
limit_req_zone $server_name zone=domain:100m rate=100r/s;

server {
listen 80;
server_name _;

location / {
limit_req zone=domain burst=50 nodelay;
}
}
  • 限制 IP 的请求速率

每秒可以接收 10 个请求,突发 5 个请求,超过 5 个请求的部分会被延迟处理。

1
2
3
4
5
6
7
8
9
10
limit_req_zone $binary_remote_addr zone=ip:100m rate=10r/s;

server {
listen 80;
server_name _;

location / {
limit_req zone=ip burst=5 nodelay;
}
}
  • 限制 IP 和 User-Agent 的请求速率

每秒可以接收 10 个请求,突发 5 个请求,超过 5 个请求的部分会被延迟处理。

1
2
3
4
5
6
7
8
9
10
limit_req_zone $binary_remote_addr$http_user_agent zone=ipandua:100m rate=10r/s;

server {
listen 80;
server_name _;

location / {
limit_req zone=ipandua burst=5 nodelay;
}
}
  • 只对某一个接口进行限制

每秒可以接收 10 个请求,突发 5 个请求,超过 5 个请求的部分会被延迟处理。

1
2
3
4
5
6
7
8
9
10
limit_req_zone $binary_remote_addr zone=ip:100m rate=10r/s;

server {
listen 80;
server_name _;

location /api {
limit_req zone=ip burst=5 nodelay;
}
}
  • 限制整一个域名的连接数
1
2
3
4
5
6
7
8
9
10
limit_conn_zone $server_name zone=domain:100m;

server {
listen 80;
server_name _;

location / {
limit_conn domain 100;
}
}
  • 同时限制 IP 和 User-Agent 的连接数、请求速率
1
2
3
4
5
6
7
8
9
10
11
12
13

limit_req_zone $binary_remote_addr$http_user_agent zone=ipandua:100m rate=10r/s;
limit_conn_zone $binary_remote_addr$http_user_agent zone=ipandua:100m;

server {
listen 80;
server_name _;

location / {
limit_req zone=ipandua burst=5 nodelay;
limit_conn ipandua 100;
}
}
往上