OpenResty 限制下载速度

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

这样在一段时间里,就无法通过并发方式来突破限速了。

你可能感兴趣的:(openresty)