Nginx实现流量控制

目录

    • 前言
    • 一、Nginx如何限流?
    • 二、Nginx限流实战
      • 2.1 实战1
      • 2.2 实战2
      • 2.3 扩展
    • 总结

前言

流量限制 (rate-limiting),我们可以用来限制用户在给定时间内HTTP请求的数量。流量限制可以用作安全目的,比如可以减慢暴力密码破解的速率,更常见的情况是该功能被用来保护上游应用服务器不被同时太多用户请求所压垮。

一、Nginx如何限流?

Nginx的流量限制使用漏桶算法(leaky bucket algorithm),就好比,一个桶口在倒水,桶底在漏水的水桶。如果桶口倒水的速率大于桶底的漏水速率,桶里面的水将会溢出;同样,在请求处理方面,水代表来自客户端的请求,水桶代表根据**先进先出调度算法(FIFO)**等待被处理的请求队列,桶底漏出的水代表离开缓冲区被服务器处理的请求,桶口溢出的水代表被丢弃和不被处理的请求。

二、Nginx限流实战

ngx_http_limit_req_module模块实现。
流量限制配置两个主要的指令,limit_req_zonelimit_req,**limit_req_zone 指令设置流量限制和内存区域的参数,但实际上并不限制请求速率。**所以需要通过添加 limit_req 指令启用流量限制,应用在特定的 location 或者 server 块。limit_req_zone指令通常在HTTP块中定义,它需要以下三个参数。

  • Key:定义应用限制的请求特性。通过 Nginx 的内置变量**$binary_remote_addr**,可以获取到访问你的客户端IP地址,即其作用就是保存客户端IP地址的二进制形式。
  • Zone: 定义用于存储每个IP地址状态以及被限制请求URL访问频率的内存区域(也就是说它是用来存储我获取的这些IP地址)。通过 zone=keyword 标识区域的名字(自定义),以及冒号后面跟区域大小。

    16000个IP地址的状态信息,大约需要1MB。

  • Rate:连接请求。速率不能超过每秒1个请求。

2.1 实战1

测试环境:三台机器,一台作为客户端进行访问、一台作为代理服务器、最后一台作为后端服务器。

(1)在代理服务器上进行配置

在实际生产中,我们一般都会在代理服务器上做流量控制,因为我们客户端的请求是都是要经过代理服务器的,如果是在后端服务器做限流,那么当有多台后端服务器的时候,就意味着每台后端服务器都得做限流配置,会浪费很多时间。

limit_req_zone $binary_remote_addr zone=mylimit:10m rate=1r/s;  #定义流量限制,每秒处理一个请求limit_req_zone在此,只用作定义和分配存储空间,并不做限流,限流需要limit_req 指令来启用
upstream test {
       server 192.168.0.102:80 weight=1 max_fails=1 fail_timeout=1;
}
server {
       listen 80;
       server_name localhost;

       location / {
                limit_req zone=mylimit;  #启用流量限制
                proxy_pass http://test;
                proxy_set_header Host $host:$server_port;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
}

(2)后端服务器配置测试页面

server {
       listen 80;
       server_name localhost;
       location / {
                root    /var/www/nginx;
                index   index.html index.html;
                }
}

在这里插入图片描述
(3)客户端访问(压力测试)

客户端安装压力测试工具

[root@nginx-yum ~]# yum install httpd-tools
[root@nginx-yum ~]# ab -n1000 -c2 http://192.168.0.103/
-n 请求数
-c 并发数

Nginx实现流量控制_第1张图片
(4)查看代理服务器错误日志

[root@nginx-server ~]# tail -f /var/log/nginx/error.log 

Nginx实现流量控制_第2张图片

日志字段解释

  • limiting requests:表明日志条目记录的是被流量限制请求;
  • excess:每毫秒超过对应“流量限制”配置的请求数量;
  • zone:定义实施“流量限制”的区域;
  • client:发起请求的客户端IP地址;
  • server:服务器IP地址或主机名;
  • request:客户端发起的实际HTTP请求;
  • host:HTTP报头中host的值。

(5)查看代理服务器访问日志

查看访问日志出现503

[root@nginx-server nginx]# tail -f /var/log/nginx/access.log 

Nginx实现流量控制_第3张图片

2.2 实战2

(1)在代理服务器上进行配置

limit_req_zone $binary_remote_addr zone=mylimit:10m rate=1r/s;
upstream myweb {
         server 192.168.0.102:80 weight=1 max_fails=1 fail_timeout=1;
}
server {
       listen 80;
       server_name localhost;

       location / {
                #limit_req zone=mylimit;
			    limit_req zone=mylimit burst=5;
                proxy_pass http://myweb;
                proxy_set_header Host $host:$server_port;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
}
# burst=5 表示最大延迟请求数量不大于5。超出的请求返回503状态码。
# 客户端测试--burst

(2)客户端访问(压力测试)

[root@zrs ~]# ab -n1000 -c50 http://192.168.0.103/

Nginx实现流量控制_第4张图片
(3)查看代理服务器访问日志

[root@nginx-proxy ~]# tail -f /var/log/nginx/access.log 

Nginx实现流量控制_第5张图片
(4)当我加上nodelay参数时

nodelay:不延迟转发请求,速度变快。

limit_req_zone $binary_remote_addr zone=mylimit:10m rate=1r/s;
upstream myweb {
         server 192.168.0.102:80 weight=1 max_fails=1 fail_timeout=1;
}
server {
       listen 80;
       server_name localhost;

       location / {
                #limit_req zone=mylimit;
			    #limit_req zone=mylimit burst=5;
			    limit_req zone=mylimit burst=5 nodelay;
                proxy_pass http://myweb;
                proxy_set_header Host $host:$server_port;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
}

(5)客户端访问(压力测试)

[root@zrs ~]# ab -n1000 -c50 http://192.168.0.103/

Nginx实现流量控制_第6张图片

2.3 扩展

发送到客户端的错误代码

一般情况下,客户端超过配置的流量限制时,Nginx响应状态码为503(Service Temporarily Unavailable)。可以使用limit_req_status指令来设置为其它状态码(例如下面的404状态码)。

(1)在代理服务器上进行配置

limit_req_zone $binary_remote_addr zone=mylimit:10m rate=1r/s;
upstream test {
         server 192.168.0.102:80 weight=1 max_fails=1 fail_timeout=1;
}
server {
      listen 80;
      server_name localhost;
		
      location / {
	          limit_req zone=mylimit;
	          limit_req_status 404;
              proxy_pass http://test;
              proxy_set_header Host $host:$server_port;
	          proxy_set_header X-Real-IP $remote_addr;
              proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      }
}

(2)查看代理服务器访问日志状态码

Nginx实现流量控制_第7张图片

总结

  • 如果不加nodelay只有burst的时候只会延迟转发请求超过限制的请求出现503错误;
  • 如果nodelay和burst参数都有不会延迟转发请求并且超出规定的请求次数会返回503状态码。

你可能感兴趣的:(Nginx,nginx)