这里写自定义目录标题
- 前言
- 正文
- nginx实现限流
- 并发限制
- 限制单IP并发数量
- 限制单主机服务并发数量
- 速率限制
- 限流效果
- 注意
- 疑问
- 参考链接
- 小结
前言
好久不见,还算为时不晚。最近一个月经历了工作的调整,技术栈从Java转向了Go和Python, 工作显得更忙了些,但是还是希望持续输出滴。最近做的产品,领导说要加一个限流功能,下面来看看如何实现。
正文
实现限流功能,限制并发数量,保护上游应用不被过多用户请求压垮,否则接下来的事情就会让人很emo了。
nginx实现限流
初步想法用最基本的计数来实现,后面觉得得改代码还得发版,这个时候还是尽量不要动代码了,发现nginx可以实现该功能。
并发限制
限制同一时间请求连接数量,使用ngx_http_limit_conn_module ,分为限制单IP和服务两种场景,使用limit_conn_zone和limit_conn 指令进行配置。
限制单IP并发数量
# 在http 中配置
http {
# 格式定义 limit_conn_zone key zone=name:size;
limit_conn_zone $binary_remote_addr zone=mylimit:10m;
...
server {
listen 8080;
# 在location中配置 最大连接数为5个
location /xxx{
limit_conn mylimit 5;
...
}
}
}
说明:
- limit_conn_zone 定义一个会话块,记录会话状态信息;
- zone=mylimit:10m 会话块叫做mylimit,内存容量为10M;
- $binary_remote_addr 表示请求客户端的IP地址,作为会话请求限制的key,限制同一IP地址的请求连接数;
- limit_conn mylimit 5 会话块最大连接数为5个,当超过数量限制后,对于后续请求默认返回503 response
code,也可以使用limit_conn_status 自定义返回的状态码;
限制单主机服务并发数量
http {
limit_conn_zone $server_name zone=serverlimit:10m;
...
server {
listen 8081;
server_name: xxx;
location /xxx{
limit_conn serverlimit 5;
...
}
}
}
说明:
- limit_conn_zone 定义一个会话块,记录会话状态信息;
- zone=serverlimit:10m 会话块叫做serverlimit,内存容量为10M;
- $server_name 虚拟主机作为会话请求限制的key,限制同一虚拟主机的请求连接数;
- limit_conn serverlimit 5 会话块最大连接数为5个,当超过数量限制后,对于后续请求默认返回503
response code,也可以使用limit_conn_status 自定义返回的状态码;
速率限制
限制单位时间内的请求数,使用ngx_http_limit_req_module ,采用漏桶算法,使用limit_req_zone和limit_req 指令进行配置
http {
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=2r/s;
...
server {
listen 8081;
server_name: xxx;
location /xxx {
# 格式定义 limit_req zone=name [burst=number] [nodelay];
limit_req zone=mylimit burst=5 nodelay;
...
}
}
}
说明:
- llimit_req_zone 定义一个请求会话块,记录会话状态信息;
- zone=mylimit:10m 会话块叫做serverlimit,内存容量为10M;
- $binary_remote_addr 同一客户端IP地址作为会话请求限制的key,限制同一IP地址的请求速度;
- rate=2r/s 1s允许处理2个请求,nginx实际上以ms为粒度来跟踪请求信息,所以可以理解为500毫秒内只允许通过1个请求,从501毫秒开始才允许通过第二个请求。
- limit_req zone=mylimit 应用上述http作用域的限流配置
- burst 设置缓冲区大小,当在单位时间内有超过上述速度的请求过来时(突发流量),可以先放到这个缓冲区内;此缓冲区可以支持存放5个多余请求;
- nodelay 让缓冲区的请求立即处理,如果不加此参数,缓冲区的请求还是按照原来的2r/s的速度处理,处理完缓冲区的5个请求需要2.5s,加了该配置后,缓冲区的请求可以被立即处理,这样请求数超过burst+rate之后多余的请求会立刻被拒绝处理,就不会有一些tcp连接请求等待。
限流效果
用Apifox或者ab(apachebench)测试并发超过限制的效果(也可通过nginx日志查看响应情况):
注意
- 对某个IP 设置限流时考虑Nginx location匹配的优先级,避免设置了未生效
- 并发限制的两种限制可以同时使用
- limit_conn_log_level 和 limit_req_log_level 提供了日志功能
疑问
限制了并发数量,有时候用工具测试时会出现超过并发数量测试通过的情况 ,还没有搞明白,希望路过的朋友们给些指导 Thanks♪(・ω・)ノ
参考链接
https://juejin.cn/post/7121903842102509581?share_token=fed0ddaa-bcf8-4844-b4a2-0a906c98ae38
https://www.cnblogs.com/chenpingzhao/p/4971308.html
http://nginx.org/en/docs/http/ngx_http_limit_conn_module.html
http://nginx.org/en/docs/http/ngx_http_limit_req_module.html
小结
记录工作日常,还是一个努力搬砖的大朋友~