1、简介
-
限流两个算法漏桶(LeakyBucket)算法和令牌桶算法(TokenBucket)。
-
nginx接入层限流可以使用Nginx自带的两个模块:
漏桶算法实现的请求限流模块
ngx_http_1imit_req_module
控制速率。#limit_req_zone $binary_remote_addr zone=contentRateLimit:10m rate=l0r/s
limit_req zone=contentRateLimit burst=50 nodelay
连接数限流模块
ngx_http_limit_conn_module
控制并发数- limit_conn_zone
- limit_conn
-
SpringGateWay网关限流,使用的令牌桶算法。SpringCloudGateWay默认使用redis的RateLimter限流算法来实现。
2、限流算法(漏桶算法和令牌桶算法)
2.1、漏桶(LeakyBucket)算法
请求大于接口响应速率直接拒绝,接口响应速率匀速
思路很简单,水(请求)先进入到漏桶里,漏桶以一定的速度出水(接口有响应速率),当水流入速度过大会直接溢出(访问频率超过接口响应速率),然后就拒绝请求,可以看出漏桶算法能强行限制数据的传输速率。示意图如下:
2.2、令牌桶算法(TokenBucket)
和Leaky Bucket效果一样但方向相反的算法,更加容易理解。随着时间流逝,系统会按恒定1/QPS时间间隔(如果QPS=100,则间隔是10ms)往桶里加入Token(想象和漏洞漏水相反,有个水龙头在不断的加水),如果桶已经满了就不再加了,新请求来临时,会各自拿走一个Token,如果没有Token可拿了就阻塞或者拒绝服务。
2.3、两者区别
在于”漏桶算法“能够强行限制数据的传输速率,而“令牌桶算法“在能够限制数据的平均传输速率外,还允许某种程度的突发传输。在令牌桶算法“中,只要令牌桶中存在令牌,那么就允许突发地传输数据直到达到用户配置的门限,所以它适合于具有突发特性的流量。
3、Nginx控制速率配置
3.1、配置一个最基本的空桶
修改/usr/local/openresty/nginx/conf/nginx.conf
worker_processes auto;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
#cache
lua_shared_dict dis_cache 128m;
#限流设置
limit_req_zone $binary_remote_addr zone=contentRateLimit:10m rate=l0r/s
#根据ip地址来限制,存储内存大小10M
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
server{
listen 80;
server_name localhost;
location /update_content {
content_by_lua_file /root/lua/update_content.lua;
}
location /read_content{
#使用限流配置
limit_req zone=contentRateLimit;
content_by_lua_file /root/lua/read_content.lua;
}
}
}
# 1imit_req_zone表示用的是ngx_http_1imit_req_module
# $binary_remote_addr是一种key,表示基于remote_addr(客户端IP)来做限流,binary_ 的目的是压缩内存占用量。
# zone:定义共享内存区来存储访问信息,contentRateLimit:10m表示一个大小为10M,名字contentRateLimit的内存区域。1M能存储16000 IP地址的访问信息,10M可以存储16W IP地址访问信息。
# rate用于设置最大访问速率,rate=10r/s表示每秒最多处理10个请求。Nginx实际上以毫秒为粒度来跟踪请求信息,因此10r/s实际上是限制:每100毫秒处理一个请求。这意味着,自上一个请求处理完后,若后续100毫秒内又有请求到达,将拒绝处理该请求。
#所以如果10次请求同时到达,那么只有一个请求能够得到执行,其它的,都会被拒绝。
#这不太友好,大部分业务场景下我们希望这1个请求都能得到执行。(问题)
#因此,可以配置burst(解决)
3.2、配置burst
server{
listen 80;
server_name localhost;
location /update_content {
content_by_lua_file /root/lua/update_content.lua;
}
location /read_content{
#使用限流配置
limit_req zone=contentRateLimit burst=50;
content_by_lua_file /root/lua/read_content.lua;
}
}
#若同时有50个请求到达,Nginx会处理第一个请求,剩余49个请求将放入队列,然后每隔100ms从队列中获取一个请求进行处理。若请求数大于50将拒绝处理多余的请求,直接返回503.
#假设burst=50,rate依然为10r/s.如果有10次请求同时到达,它们会依次执行,每100ms执行1个,第50个请求却需要等待50*100ms即5s,这么长的处理时间自然难以接受。(问题)
#国此,burst往往结合nodelay一起使用(解决)
3.3、配置nodelay
server{
listen 80;
server_name localhost;
location /update_content {
content_by_lua_file /root/lua/update_content.lua;
}
location /read_content{
#使用限流配置
limit_req zone=contentRateLimit burst=50 nodelay;
content_by_lua_file /root/lua/read_content.lua;
}
}
#平均每秒允许不超过10个请求,突发不超过50个请求,并且处理突发50个请求的时候,没有延退,等到完成之后,按照正常的速率处理。
4、Nginx控制并发量(连接数)
ngx_http_limit_conn_module
提供了限制连接数的能力。主要是利用limit_conn_zone
和limit_conn
两个指令。
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
#cache
lua_shared_dict dis_cache 128m;
#限流设置
limit_req_zone $binary_remote_addr zone=contentRateLimit:10m rate=l0r/s
#根据ip地址来限制,存储内存大小10M
#【这里】
limit_conn_zone $binary_remote_addr zone=addr:10m;
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
server{
listen 80;
server_name localhost;
#【这里】所有一brand开始的请求,访问ip的微服务
location /brand{
#使用限流配置
limit_conn addr 2;
proxy_pass http://xxx.xx.xx.xx:xxx
}
location /update_content {
content_by_lua_file /root/lua/update_content.lua;
}
location /read_content{
#使用限流配置
limit_req zone=contentRateLimit;
content_by_lua_file /root/lua/read_content.lua;
}
}
}
#limit_conn_zone $binary_remote_addr zone=addr:10m;
1imit_conn_zone:是针对每个IP定义一个存储session状态的容器.这个示例中定义了一个10m的容器,按照32bytes/session,可以处理320000个session
# 1imit_conn addr 2;
“addr”与上面的对应,也可以自定义命名,表示同一个地址最大同时连接数数2次,超过这个数字的请求将被返回”Serviceunavailable”(593)代码。
评论区