nginxのツアー(パートIV):nginxの速度制限の原則、nginxの速度制限のシナリオでは、制限速度を達成nginxの

A、nginxの制限速度

本番環境では、WEBサーバの安全性を保護するために、我々は、サーバーのリソースを安全かつ合理的な配分を確保するために、ユーザーのアクセスにはいくつかの制限を行います。

(レート制限)を制限することで、最も有用なnginxの多くの機能は、しばしば誤解や間違って設定されたアクセス要求の律速特徴の一つです。この機能は、HTTP要求が番号を生成することができ、所与の時間期間中にユーザを制限することができます。シンプルなGETリクエストは、ページまたは着陸フォームのPOSTリクエストのためにあるよう要求とすることができます。そのようなスローダウンブルートフォースパスワードクラッキング攻撃などのセキュリティ目的のために。、および(ログと一緒に)入ってくる要求のレートを制限することにより、ヘルプへの標識ターゲットURLは、DDoS攻撃から守ります。多数のユーザーで失われていないのと同じ一般的時間を要求し、流量制限は、保護におけるアプリケーションサーバの上流にあります

非常に広い、実際には、多くの速度制限速度制限法に分かれている速度制限:

1)ダウンロード速度の制限速度

2)単位時間あたりの要求の数を制限

3)同時クライアント接続の速度に基づいて

nginxの高速モジュール

nginxの公式バージョンは、同時IP接続に制限され、2つのモジュールがあります。

limit_req_zoneは、単位時間当たりの要求、すなわち、速度制限、リーキーバケットアルゴリズム「リーキーバケット」の数を制限するために使用されます。

接続の数、すなわち、同時実行の制限を制限すると同時にlimit_req_conn。

 

第二に、アプリケーションのシナリオ

ダウンロード速度制限:今制限速度と帯域幅とサーバーを保護するために、同時接続数、アプリケーションダウンロードサーバIOリソース。

要求速度:、悪意のある攻撃を防ぐために、サーバーの保護と資源のセキュリティを単位時間あたりの利用者のアクセス要求を制限します。

 

第三に、速度制限の原則

二つの一般的なネットワーク送信フロー制御アルゴリズム:リーキーバケットアルゴリズムトークンバケットアルゴリズムnginxのは、モジュール漏出バケットレート制限を使用してレートを要求しました

リーキーバケットアルゴリズム(リーキーバケット)

図に示したリーキーバケットアルゴリズム(リーキーバケット)アルゴリズム:

 

1つの説明はイメージです。

  • 水(リクエスト)上記バケットに注ぎから、浴槽の底からの流出(処理されます)。

  • 来不及流出的水存在水桶中(缓冲),以固定速率流出;

  • 水桶满后水溢出(丢弃)。

这个算法的核心是:缓存请求、匀速处理、多余的请求直接丢弃。

 

令牌桶算法(token bucket)

 

 

算法思想是:

  • 令牌以固定速率产生,并缓存到令牌桶中;

  • 令牌桶放满时,多余的令牌被丢弃;

  • 请求要消耗等比例的令牌才能被处理;

  • 令牌不够时,请求被缓存。

相比漏桶算法,令牌桶算法不同之处在于它不但有一只“桶”,还有个队列,这个桶是用来存放令牌的,队列才是用来存放请求的。

从作用上来说,漏桶和令牌桶算法最明显的区别就是是否允许突发流量(burst)的处理,漏桶算法能够强行限制数据的实时传输(处理)速率,对突发流量不做额外处理;而令牌桶算法能够在限制数据的平均传输速率的同时允许某种程度的突发传输

Nginx按请求速率限速模块使用的是漏桶算法,即能够强行保证请求的实时处理速度不会超过设置的阈值。

 

四、限速实现

 

nginx限速可以通过 ngx_http_limit_conn_module 和 ngx_http_limit_req_module 模块来实现限速的功能。

(一)限制并发数ngx_http_limit_conn_module

 这个模块可以设置每个定义的变量(比如客户端ip)的并发连接数,比如:某个客户端ip在同一时间内的连接数不能超过某个值。

语法:

定义限制链接区域

(nginx 1.18以后用 limit_conn_zone 取代了 limit_conn)

Syntax: limit_conn_zone key zone=name:size;
Default:    —
Context:    http

  

设置连接数限制

Syntax: limit_conn zone number;
Default:    —
Context:    http, server, location

  

示例:

 

http
{
    ...
    # 根据客户端ip进行限制,区域名称为perip,总容量为10m
    limit_conn_zone $binary_remote_addr zone=perip:10m;
    limit_conn_zone $server_name zone=perserver:10m;
    ...
    server
    {
        ...
        ...
        # 使用perip区域名称(zone name),同一时间并发数不得超过10
        limit_conn perip 10;
        limit_conn perserver 100;
        ...   
    }
}

  

分析:

limit_conn perip 10 定义针对perip这个zone,并发连接为10个。在这需要注意一下,这个10指的是单个IP的并发最多为10个。

 

(二)速度限制limit_rate、limit_rate_after

limit_rate语法

Syntax: limit_rate rate;
Default:    
limit_rate 0;
Context:    http, server, location, if in location

  

limit_rate_after语法,在下载完成x文件大小时开始限速

Syntax: limit_rate_after size;
Default:    
limit_rate_after 0;
Context:    http, server, location, if in location
This directive appeared in version 0.8.0.

  

示例

http
{
    ...
    # 根据客户端ip进行限制,区域名称为perip,总容量为10m
    limit_conn_zone $binary_remote_addr zone=perip:10m;
    limit_conn_zone $server_name zone=perserver:10m;
    ...
    server
    {
        ...
        limit_rate_after 512k;
        limit_rate 150k;
        ...   
    }
}

  

分析:说明:limit_rate_after定义当一个文件下载到指定大小(本例中为512k)之后开始限速; limit_rate 定义下载速度为150k/s。

注意:这两个参数针对每个请求限速,意思表示每个连接的传输速度不能超过 150k。

(三)ngx_http_limit_req_module

1、limit_req_zone、limit_req:

limit_req_zone语法

Syntax: limit_req_zone key zone=name:size rate=rate [sync];
Default:    —
Context:    http

  

示例

limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;

 

分析:在 http 配置段中定义限制的参照标准和状态缓存区大小。比如上面的配置就是定义了使用客户端的 IP 作为参照依据,并使用一个 10M 大小的状态缓存区。结尾的 rate=1r/s 表示针对每个 IP 的请求每秒只接受一次。NAME 是自定义的缓存区名称,可以随意命名,比如 per_ipone 等。在 server 配置段中会用到。10M 的状态缓存空间够不够用呢?官方给出的答案是 1M 的缓存空间可以在 32 位的系统中服务 3.2 万 IP 地址,在 64 位的系统中可以服务 1.6 万 IP 地址,所以需要自己看情况调整。如果状态缓存耗光,后面所有的请求都会收到 503(Service Temporarily Unavailable) 错误。

limit_req语法

Syntax: limit_req zone=name [burst=number] [nodelay | delay=number];
Default:    —
Context:    http, server, location

  

示例

limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
server {
    location /search/ {
        limit_req zone=one burst=5;
    }

  

分析:

第一段配置

limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;

第一个参数:$binary_remote_addr 表示通过remote_addr这个标识来做限制,“binary_”的目的是缩写内存占用量,是限制同一客户端ip地址 第二个参数:zone=one:10m表示生成一个大小为10M,名字为one的内存区域,用来存储访问的频次信息 第三个参数:rate=1r/s表示允许相同标识的客户端的访问频次,这里限制的是每秒1次,还可以有比如30r/m的

第二段配置

limit_req zone=one burst=5;

第一个参数:zone=one 设置使用哪个配置区域来做限制,与上面limit_req_zone 里的name对应 第二个参数:burst=5,重点说明一下这个配置,burst爆发的意思,如果单个 IP 有每秒有超过 1 个请求限制的时候,设置一个大小为5的缓冲区当有大量请求(爆发)过来时,5是最多接受5个超出的配额。超过了访问频次限制的请求可以先放到这个缓冲区内 第三个参数:nodelay,如果设置,超过访问频次而且缓冲区也满了的时候就会直接返回503,如果没有设置,则所有请求会等待排队

限制平均每秒不超过一个请求,同时允许超过频率限制的请求数不多于5个。

如果不希望超过的请求被延迟,可以用nodelay参数,如:

limit_req zone=one burst=5 nodelay;

 

应用示例

示例1

需求:基于IP对下载速率做限制, 限制每秒处理1次请求,对突发超过5个以后的请求放入缓存区,

过程:

/usr/local/nginx/html 目录下创建目录,写入index.html文件

[root@localhost nginx]# mkdir html/abc
[root@localhost nginx]# ls html/
50x.html  abc  index.html
[root@localhost nginx]# echo hello word! >html/abc/index.html
[root@localhost nginx]# cat html/abc/index.html 
hello word!
[root@localhost nginx]# 

  


配置虚拟主机

修改 /usr/local/nginx 目录下的 nginx.conf 配置文件:

...
http{
...
   limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
   
    server {
        listen     80;
        location /abc {
            limit_req zone=one burst=5 nodelay;
        }
    }
      
    
}
 

  

重启nginx,测试效果

[root@localhost nginx]# killall -s HUP nginx
[root@localhost nginx]# elinks http://192.168.199.228/abc --dump
   hello word!
[root@localhost nginx]# elinks http://192.168.199.228/abc --dump
   hello word!
[root@localhost nginx]# elinks http://192.168.199.228/abc --dump
   hello word!
[root@localhost nginx]# elinks http://192.168.199.228/abc --dump
   hello word!
[root@localhost nginx]# elinks http://192.168.199.228/abc --dump
   hello word!
[root@localhost nginx]# elinks http://192.168.199.228/abc --dump
                      503 Service Temporarily Unavailable
   --------------------------------------------------------------------------
                                  nginx/1.15.5
[root@localhost nginx]# 

  

 

示例2

需求:基于IP做连接限制, 限制同一IP并发为1 下载速度为限制为100K

过程:

VM1 的ip192.168.199.228

/usr/local/nginx/html 目录下创建目录,生成300m大文件做测试用


[root@localhost nginx]# ls html/abc
index.html
[root@localhost nginx]# dd if=/dev/zero of=html/abc/bigfile bs=1M count=300
300+0 records in
300+0 records out
314572800 bytes (315 MB) copied, 3.21417 s, 97.9 MB/s
[root@localhost nginx]# ls html/abc
bigfile  index.html

  

未做任何限制的情况下,在另外一台vm2192.168.199.229下载上面生成的大文件

[root@localhost ~]# cd /tmp
[root@localhost tmp]# ls
ks-script-LAqqiN  vmware-root  yum.log
[root@localhost tmp]# wget http://192.168.199.228/abc/bigfile
--2019-10-16 17:28:57--  http://192.168.199.228/abc/bigfile
正在连接 192.168.199.228:80... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度:314572800 (300M) [application/octet-stream]
正在保存至: “bigfile”
100%[====================================>] 314,572,800 53.2MB/s 用时 5.3s   
2019-10-16 17:29:03 (56.3 MB/s) - 已保存 “bigfile” [314572800/314572800])
[root@localhost tmp]# 

  


可以看到速度还是很快的

限制方式一,用limit_rate做限制

    server {
        location /abc {
        limit_rate 100k;#通过这个限制单个连接数的带宽
        }
    }

  

效果

[root@localhost tmp]# wget http://192.168.199.228/abc/bigfile
--2019-10-16 17:34:48--  http://192.168.199.228/abc/bigfile
正在连接 192.168.199.228:80... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度:314572800 (300M) [application/octet-stream]
正在保存至: “bigfile.2”
 1% [                                     ] 5,120,000   99.7KB/s 剩余 50m 25s

  

可以看到速度就被限制住了

方式二:在限制单个链接速度的同时,为了防止开大量链接分段下载,然后进行合并文件的情况提速,对并发的链接也做限制

http {
   limit_conn_zone $binary_remote_addr zone=addr:10m;
   ...
   server {
  ...
  location /download/ {
      limit_conn addr 1; #通过这个限制链接数,单个ip最多的可连接数
      limit_rate 100k;
  }
   }
}

  

效果,如果单个ip超过了最多可连接数则返回503

[root@localhost tmp]# wget http://192.168.199.228/abc/bigfile
--2019-10-16 17:51:27--  http://192.168.199.228/abc/bigfile
正在连接 192.168.199.228:80... 已连接。
已发出 HTTP 请求,正在等待回应... 503 Service Temporarily Unavailable
2019-10-16 17:51:27 错误 503:Service Temporarily Unavailable。
[root@localhost tmp]# 

  


方式三,也可以针对某个文件下载到固定的大小后再进行限速

 

http {
   limit_conn_zone $binary_remote_addr zone=addr:10m;
   ...
   server {
  ...
  location /download/ {
      limit_conn addr 1; #通过这个限制链接数,单个ip最多的可连接数
      limit_rate 100k;
      limit_rate_after 200M;
  }
   }
}

  

这样下载文件时,就会对这个文件的前200m不限速,200m之后的开始限速。

 

总结一下:

  • 要想实现限速,单个连接带宽限制是必须的。

  • 在生产环境中,建议不要使用连接数限制

  • 单个连接的带宽限制不易过低

     

 

参考资料

[1]https://www.cnblogs.com/CarpenterLee/p/8084533.html

[2]https://www.cnblogs.com/yyxianren/p/10837424.html

[3]https://www.cnblogs.com/liushijie/p/5376372.html

[4]http://nginx.org/en/docs/http/ngx_http_core_module.html#limit_rate

おすすめ

転載: www.cnblogs.com/Nicholas0707/p/12093173.html