http://blog.donatas.net/blog/2017/07/25/limit-bandwidth-openresty/
Nginx 有两个非常棒的模块用来限制响应(responses)的速度
limit_rate 对一个客户端限制速率 bytes/每秒limit_rate_after一般情况没问题,但是视频流传输就不好用了
location / { limit_rate_after 500k; limit_rate 50k; ... }上面的配置意味着,你可以缓冲500k然后开始限速(me:有点类似视频开头不限速,后面才开始限速), 如果你使用 browser/player/whatever 来播放,就会发现每次缓冲都会使用新建一个请求,相当于限速的作用被削弱了。
如果我想把这些限制只用于视频流,而不是简单的wget这种模式呢(视频流是chunk的)? 我的意思是 - 以反向指数方式,相同URI限制下一个请求,如反向TCP拥塞行为。(me:同一个客户端的并发请求能全局限速, 可以感知并发)
尽可能使用简单的方式实现,但不是越简单越好
为每个 uri 创建SHA256 的hash,并且设置5分钟的有效期,这期间对每个请求进行计数。计数器是用来指数级的加大限速
26214400 6553600 1638400 409600 102400 25600 6400 ...router.conf:
location / { set $limit_rate ''; set $limit_rate_after ''; access_by_lua_file conf/router.lua; proxy_buffering on; ... }router.lua:
ocal request_count = function () local resty_sha256 = require "resty.sha256" local str = require "resty.string" local sha256 = resty_sha256:new() sha256:update(ngx.var.http_host .. ngx.var.request) local digest = sha256:final() local key = "request:" .. str.to_hex(digest) local ok, err = redis:connect("127.0.0.1") if not ok then return nil, err end local ok, err = redis:auth("something") if not ok then return nil, err end local data, _ = redis:get(key) redis:incr(key) redis:expire(key, 300) return data end local bw_limit = 104857600 if request_count() ~= ngx.null then bw_limit = math.max(10240, math.floor(bw_limit / 2 ^ request_count())) end ngx.var.limit_rate = bw_limit ngx.var.limit_rate_after = 8388608这样在一段时间里,就无法通过并发方式来突破限速了。