nginx篇12-限速三剑客之limit_rate

本文最后更新于:July 12, 2021 pm

本文主要是对nginx官方limit_rate相关指令的用法解释和一些个人理解,limit_rate主要用于限制用户和服务器之间传输的字节数,最常用的场景可能就是下载/上传限速,在如今用户网速普遍大幅提升的情况下,对于一些文件传输、视频流媒体传输等服务还是有着一定的应用场景的。

和我们前面提过的limit_req模块和limit_conn模块不一样的是,limit_rate并没有单独的一个模块,而是在ngx_http_core_module中,同时它的相关指令也比较少,只有limit_ratelimit_rate_after这两个指令。

1、limit_rate

1
2
3
4
5
6
7
# 语法配置
Syntax: limit_rate rate;
Default: limit_rate 0;
Context: http, server, location, if in location

# 示例
limit_rate 4k;
  • limit_rate的用法非常简单,后面跟随的rate就是具体限速的阈值
  • 注意默认的单位是bytes/s,也就是每秒传输的字节数Bytes而不是比特数bits
  • rate可以设置为变量,从而可以实现动态限速,后面我们再详细介绍
  • 限速指令的生效范围是根据每个连接确定的,例如上面限定每个连接的速率为4k,也就是当客户端发起两个连接的时候,速率就可以变为8k

2、limit_rate_after

1
2
3
4
5
6
7
8
9
10
11
12
# 语法配置
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.

# 示例
location /flv/ {
flv;
limit_rate_after 500k;
limit_rate 50k;
}

limit_rate_after允许在传输了一部分数据之后再进行限速,例如上面的配置中就是传输的前500kbyte数据不限速,500k之后再进行限速。比较常见的应用场景如分段下载限速,超过指定大小的部分再进行限速;又或者是流媒体视频网站一般为了保证用户体验而不会对第一个画面进行限速,确保其能够尽快加载出来,等用户开始观看视频之后,再把带宽限制在合理的范围内,从而降低因客户端网速过快导致提前加载过多内容带来的额外成本。

3、proxy_limit_rate

proxy_limit_rate的基本原理和用法与limit_rate几乎一样,唯一不同的是proxy_limit_rate限制nginx和后端upstream服务器之间的连接速率而limit_rate限制的是nginx和客户端之间的连接速率。需要注意的是proxy_limit_rate需要开启了proxy_buffering这个指令才会生效。

1
2
3
4
Syntax:	proxy_limit_rate rate;
Default: proxy_limit_rate 0;
Context: http, server, location
This directive appeared in version 1.7.7.

4、动态限速

limit_rate的一大特点就是能够使用变量,这就意味着和map指令之类的进行组合就可以实现动态限速功能,这里只列几个简单的示范

4.1 基于时间动态限速

这里引入了nginx内置的一个ssi模块,这个模块有两个比较有意思的时间变量:$date_local$date_gmt,分别对应当前时间和GMT时间

Module ngx_http_ssi_module (nginx.org)

Embedded Variables

The ngx_http_ssi_module module supports two embedded variables:

  • $date_local

    current time in the local time zone. The format is set by the config command with the timefmt parameter.

  • $date_gmt

    current time in GMT. The format is set by the config command with the timefmt parameter.

这里使用变量和map指令组合的方式,利用正则表达式匹配不同的时间段,再结合map变量将不同时间段和不同的限速对应起来。

1
2
3
4
5
6
7
8
map $date_local $limit_rate_time {
default 4K;
~(00:|01:|02:|03:|04:|05:|06:|07:).*:.* 16K;
~(08:|12:|13:|18:).*:.* 8K;
~(19:|20:|21:|22:|23:).*:.* 16K;
}

limit_rate $limit_rate_time

4.2 基于变量动态限速

有些服务可能会对不用的用户进行不同的限速,例如VIP用户的速度要更快一些等,例如下面可以针对不同的cookie进行限速

1
2
3
4
5
6
7
8
map $cookie_User $limit_rate_cookie {
gold 64K;
silver 32K;
copper 16K;
iron 8K;
}

limit_rate $limit_rate_cookie

当然还可以使用GeoIP模块等其他模块针对如不同的IP进行限速等操作,用法和配置基本上都是大同小异,这里就不再赘述。