基础
main #全局设置
events { ... }
http{
upstream #负载均衡服务器设置
server{ #主机设置
location { #URL匹配设置
...
}
}
}
server继承main,location继承server,upstream即不会继承其他设置也不会被继承。
Nginx查看安装版本
# nginx -v
nginx version: nginx/1.20.1
Nginx配置了哪些模块
# nginx -V
nginx version: nginx/1.20.1
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)
built with OpenSSL 1.1.1k 25 Mar 2021
TLS SNI support enabled
configure arguments: --user=www --group=www --prefix=/www/server/nginx --add-module=srclib/ngx_devel_kit --add-module=srclib/lua_nginx_module --add-module=srclib/ngx_cache_purge --add-module=srclib/nginx-sticky-module --with-openssl=srclib/openssl --with-pcre=srclib/pcre-8.43 --with-http_v2_module --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --with-http_stub_status_module --with-http_ssl_module --with-http_image_filter_module --with-http_gzip_static_module --with-http_gunzip_module --with-ipv6 --with-http_sub_module --with-http_flv_module --with-http_addition_module --with-http_realip_module --with-http_mp4_module --with-ld-opt=-Wl,-E --with-cc-opt=-Wno-error --with-http_dav_module --add-module=srclib/nginx-dav-ext-module
限流配置
Nginx提供几种限流方式。
- 请求速率控制,限制单个IP的请求处理速率
- 并发连接数控制,限制单个IP连接数,server的总连接数
- 每个连接的下载速度
以上3种限流方式可以搭配结合使用,在指定的server或者location上限流。
请求限制QPS
ngx_http_limit_req_module 模块提供限制请求处理速率能力,使用了漏桶算法(leaky bucket),限制单个IP的请求处理速率。
-
漏桶算法
- 作用:保证数据的最大的传输速率,桶的出口滴水速度恒定;不能应对突发流量,突发流量直接溢出丢弃
-
令牌桶算法
- 作用:能够限制数据的平均传输速率外,还允许某种程度的突发传输。
适用场景:如果要让自己的系统不被打垮,用令牌桶。如果保证别人的系统不被打垮,用漏桶算法
示例如下:
先在http
范围定义一个limit_req_zone
,然后在server
或者location
范围使用它。
http {
# 定义了一个ip_limit缓冲区(容器),同一个IP请求频率为每秒10个请求(r/s)
limit_req_zone $binary_remote_addr zone=ip_limit:10m rate=10r/s;
server {
...
location /login {
limit_req zone=ip_limit burst=12 nodelay;
proxy_pass http://login_upstream;
}
}
}
limit_req_zone
只能配置在http
范围内;$binary_remote_addr
客户端请求的IP地址,表示基于 remote_addr(客户端IP) 来做限流,binary_ 的目的是压缩内存占用量。;zone=ip_limit:10m
自己定义限流规则名称为ip_limit,允许使用**10MB(存储16W个IP)**的内存空间来记录ip对应的限流状态;- 官方给出1M的缓存空间可以在 32位的系统中服务 3.2万IP地址,在 64 位的系统中可以服务 1.6万IP地址。不够的话自己加大点。
- 当NGINX需要添加新的记录时,如果此时存储耗尽了,最老的记录会被移除。如果释放的存储空间还是无法容纳新的记录,NGINX返回**503 (Service Temporarily Unavailable)**状态码。此外,为了防止内存被耗尽,每次NGINX创建一个新的记录的同时移除多达两条前60秒内没有被使用的记录。
rate=10r/s
限流速度为每秒10次请求,实际上是按毫秒计算, 即每 1次/100ms- 每100毫秒处理一个请求。这意味着,自上一个请求处理完后,若后续100毫秒内又有请求到达,将拒绝处理该请求。
burst=12
漏桶的大小设置为12 是FIFO队列,把得不到执行的请求暂时缓存起来。nodelay
配合burst使用,要么立刻执行,要么被拒绝,请求不会因为限流而增加延迟了。location /login
仅仅对登录接口进行限流,如果放在server下,即对整个server限流。
并发限制连接数
ngx_http_limit_conn_module 提供了限制连接数的能力。
示例如下:
先在http
范围定义一个limit_conn_zone
,然后在server
或者location
范围使用它。
http {
limit_conn_zone $binary_remote_addr zone=perip:10m;
limit_conn_zone $server_name zone=perserver:10m;
server {
...
# 每个IP只允许一个连接
limit_conn perip 10;
# 限制服务器的总连接数
limit_conn perserver 100;
# 限制传输速度(如果有N个并发连接,则是 N * limit_rate)
limit_rate 1024k;
}
}
-
limit_conn_zone
只能配置在http
范围内; -
$binary_remote_addr
表示客户端请求的IP地址; -
$server_name
表示虚拟主机(server) 同时能处理并发连接的总数; -
limit_conn perip 10
表示限制单个IP同时最多能持有10个连接; -
limit_conn perserver 100
表示虚拟主机(server) 同时能处理并发连接的总数; -
limit_rate 1024k
限制单个连接传输速度,如果有N个并发连接,则是N * limit_rate
下载速度限制带宽
ngx_http_core_module 还提供了限制数据传输速度的能力(即常说的下载速度)。
例如:
location / {
...
limit_rate_after 20m;
limit_rate 100k;
}
这个限制是针对每个请求的,表示客户端下载前20M时不限速,后续限制100kb/s。
被限制后发送给客户端的错误码
默认,当某个客户端超过它的限流,NGINX用503(Service Temporarily Unavailable)状态码来响应。使用limit_req_status指令设置一个不同的状态码(在下面的例子是444):
location /login {
limit_req zone=mylimit burst=20 nodelay;
limit_req_status 444;
}
拒绝对特定位置的所有请求
如果你想拒绝对于某个特定URL的所有请求,而不是仅仅的限制它们。
location /buyer {
deny all;
}
限流日志
默认,NGNIX记录由于限流导致的延迟或丢弃的请求的日志,如下面的例子:
2015/06/13 04:20:00 [error] 120315#0: *32086 limiting requests, excess: 1.000 by zone "lakerlimit", client: 192.168.1.2, server: nginx.com, request: "GET / HTTP/1.0", host: "nginx.com"
该日志记录包含的字段:
- limiting requests — 日志条目记录了某个限流的标志
- excess — 超过这个请求代表的配置的速率的每毫秒请求数目
- zone — 定义了启用了限流的区域
- client — 产生请求的客户端IP地址
- server — 服务器的IP地址或主机名
- request — 客户端产生的实际的HTTP请求
- host — HTTP头部主机名的值
默认,NGINX日志在error级别拒绝请求,如上面例子中的**[error]所示。(它在低一个级别上记录延迟的请求,因此默认是info**。)用limit_req_log_level指令来改变日志级别。
limit_conn_log_level info
| notice
| warn
| error
;
下面我们设置在warn级别上记录被拒绝的请求的日志:
location /login {
limit_req zone=mylimit burst=20 nodelay;
limit_req_log_level warn;
}
黑白名单限流
白名单不限量,黑名单上的IP进行限流。
geo $limit {
default 1;
10.0.0.0/8 0;
192.168.0.0/24 0;
}
map $limit $limit_key {
0 "";
1 $binary_remote_addr;
}
limit_req_zone $limit_key zone=req_zone:10m rate=5r/s;
server {
location / {
limit_req zone=req_zone burst=10 nodelay;
# ...
}
}
这个例子同时使用了geo和map指令。对于IP地址在白名单中的,geo块分配0值给$limit
;其它所有不在白名单中的IP地址,分配1值。然后我们使用一个map去将这些值映射到某个key中,例如:
- 如果
$limit
是0,$limit_key被设置为空字符串 - 如果
$limit
是1,$limit_key被设置为客户端的IP地址的二进制格式
这个两个结合起来,对于白名单中的IP地址,$limit_key被设置为空字符串;否则,被设置为客户端的IP地址。当limit_req_zone指令的第一个参数是一个空字符串,限制不起作用,因此白名单的IP地址(在10.0.0.0/8和192.168.0.0/24子网中)没有被限制。其它所有的IP地址都被限制为5个请求每秒。
limit_req指令将限制作用在/
定位中,并且允许在没有转发延迟的情况下,转发多达10个数据包。
限流整体示例
http {
#限制每个uri请求速率
limit_req_zone $uri zone=api_read:20m rate=50r/s;
#限制并发数
#按ip配置一个连接 zone
limit_conn_zone $binary_remote_addr zone=perip_conn:10m;
#按server配置一个连接 zone
limit_conn_zone $server_name zone=perserver_conn:100m;
server {
#请求限流排队通过 burst默认是0
limit_req zone=api_read burst=100 nodelay;
#连接数限制,每个IP并发请求为50
limit_conn perip_conn 50;
#服务所限制的连接数(即限制了该server并发连接数量)
limit_conn perserver_conn 200;
#连接限速
limit_rate 512k;
}
}
参考:
-
http://nginx.org/en/docs/http/ngx_http_limit_req_module.html
-
http://nginx.org/en/docs/http/ngx_http_limit_conn_module.html
-
https://chenyongjun.vip/articles/81