原文: lua-resty-limit-traffic/lib/resty/limit/count.md

1. 示例

  1. http {
  2. lua_shared_dict my_limit_count_store 100m;
  3. init_by_lua_block {
  4. require "resty.core"
  5. }
  6. server {
  7. location / {
  8. access_by_lua_block {
  9. local limit_count = require "resty.limit.count"
  10. -- rate: 5000 requests per 3600s
  11. local lim, err = limit_count.new("my_limit_count_store", 5000, 3600)
  12. if not lim then
  13. ngx.log(ngx.ERR, "failed to instantiate a resty.limit.coutn object: ", err)
  14. return ngx.exit(500)
  15. end
  16. -- use the Authorization header as the limiting key
  17. local key = ngx.req.get_headers()["Authorization"] or "public"
  18. local delay, err = lim:incoming(key, true)
  19. if not delay then
  20. if err == "rejected" then
  21. ngx.header["X-RateLimit-Limit"] = "5000"
  22. ngx.header["X-RateLimit-Remaining"] = 0
  23. return ngx.exit(503)
  24. end
  25. ngx.log(ngx.ERR, "failed to limit count: ", err)
  26. return ngx.exit(500)
  27. end
  28. -- the 2nd return value holds the current remaing number
  29. -- of requests for the specified key.
  30. local remaining = err
  31. ngx.header["X-RateLimit-Limit"] = "5000"
  32. ngx.header["X-RateLimit-Remaining"] = remaining
  33. }
  34. }
  35. }
  36. }

注: 该模块依赖 lua-resty-core,因此需要:

  1. init_by_lua_block {
  2. require "resty.core"
  3. }

2. 方法

2.1 new

  1. syntax: obj, err = class.new(shdict_name, count, time_window)

实例化 class 的对象,该 class 通过 require "resty.limit.count" 返回。

该 new 方法携带的参数如下:

  • shdict_name: lua_shared_dict 声明的共享内存的名称。建议对不同的限制使用独立的共享内存。
  • count:指定的请求阈值。
  • time_window: 请求个数复位前的窗口时间,以秒为单位。

new 实现如下

  1. local ngx_shared = ngx.shared
  2. local setmetatable = setmetatable
  3. local assert = assert
  4. local _M = {
  5. _VERSION = '0.05'
  6. }
  7. local mt = {
  8. __index = _M
  9. }
  10. -- the "limit" argument controls number of request allowed in a time window.
  11. -- time "window" argument controls the time window in seconds.
  12. function _M.new(dict_name, limit, window)
  13. local dict = ngx_shared[dict_name]
  14. if not dict then
  15. return nil, "shared dict not found"
  16. end
  17. assert(limit> 0 and window > 0)
  18. local self = {
  19. dict = dict,
  20. limit = limit,
  21. window = window,
  22. }
  23. return setmetatable(self, mt)
  24. end

2.2 incoming

  1. syntax: delay, err = obj:incoming(key, commit)

触发新请求传入事件并计算当前请求对指定 key 所需的 delay(如果有的话),或者是否立即拒绝该请求。

该方法接受如下参数:

  • key: 是用户指定限制速率的 key。

    例如,可以使用 host 或 server zone 作为 key,以便限制每个 host 的速率。此外,也可以使用 Authorization 头部值作为 key,以便可以为个人用户限制速率。

    注意该模块没有为该 key 加前缀或后缀来标志该 key,因此用户需要确保该 key 在 lua_shared_dict 共享内存中是唯一的。
  • commit:布尔值。如果设置为 true,则 obj 将会在支持该 obj 的共享内存中记录该事件;否则仅仅是 "dry run"。

该 incoming 方法的放回值依赖如下情况:

  1. 如果请求数没有超过在 new 方法中设置的 count 值,那么该 incoming 返回 0 作为 delay,并将当前时间内余下允许请求的个数作为第二个值返回。
  2. 如果请求数超过了 count 限制,则返回 nil 和错误字符串 "rejected"。
  3. 如果发生错误(如访问共享内存失败),则该方法返回 nil 和错误描述字符串。

incoming 实现如下

  1. function _M.incoming(self, key, commit)
  2. local dict = self.dict
  3. local limit = self.limit
  4. local window = self.window
  5. local remaining, ok, err
  6. if commit then
  7. remaining, err = dict:incr(key, -1, limit)
  8. if not remaining then
  9. return nil, err
  10. end
  11. if remaining == limit - 1 then
  12. ok, err = dict:expire(key, window)
  13. if not ok then
  14. if err == "not found" then
  15. remaining, err = dict:incr(key, -1, limit)
  16. if not remaining then
  17. return nil, err
  18. end
  19. ok, err = dict:expire(key, window)
  20. if not ok then
  21. return nil, err
  22. end
  23. else
  24. return nil, err
  25. end
  26. end
  27. end
  28. else
  29. remaining = (dict:get(key) or limit) - 1
  30. end
  31. if remaining < 0 then
  32. return nil, "rejected"
  33. end
  34. return 0, remaining
  35. end

OpenResty之 limit.count 模块的更多相关文章

  1. nginx_tcp模块集成到openresty(安装ngx_tcp_lua_module模块)

    git地址:https://github.com/bigplum/nginx-tcp-lua-module openresty 本身是使用http协议进行通讯的, 但是项目中经常有要求输入是使用tcp ...

  2. 又拍云张聪:OpenResty 动态流控的几种姿势

    2019 年 1 月 12 日,由又拍云.OpenResty 中国社区主办的 OpenResty × Open Talk 全国巡回沙龙·深圳站圆满结束,又拍云首席架构师张聪在活动上做了< Ope ...

  3. 从SpringBoot构建十万博文聊聊限流特技

    前言 在开发十万博客系统的的过程中,前面主要分享了爬虫.缓存穿透以及文章阅读量计数等等.爬虫的目的就是解决十万+问题:缓存穿透是为了保护后端数据库查询服务:计数服务解决了接近真实阅读数以及数据库服务的 ...

  4. SpringBoot项目的限流

    开发访问量比较大的系统是,爬虫的目的就是解决访问量大的问题:缓存穿透是为了保护后端数据库查询服务:计数服务解决了接近真实访问量以及数据库服务的压力. 架构图 限流 就拿十万博客来说,如果存在热点文章, ...

  5. 高并发 Nginx+Lua OpenResty系列(4)——Lua 模块开发

    在实际开发中,不可能把所有代码写到一个大而全的lua文件中,需要进行分模块开发:而且模块化是高性能Lua应用的关键.使用require第一次导入模块后,所有Nginx 进程全局共享模块的数据和代码,每 ...

  6. 浏览器给openresty连接发送参数请求,查询数据库,并返回json数据

    nginx.conf配置文件 #user nobody; worker_processes 1; error_log logs/error.log; #error_log logs/error.log ...

  7. OpenResty实现限流的几种方式

      在开发 api 网关的时,做过一些简单的限流,比如说静态拦截和动态拦截:静态拦截说白了就是限流某一个接口在一定时间窗口的请求数.用户可以在系统上给他们的接口配置一个每秒最大调用量,如果超过这个限制 ...

  8. openresty/1.11.2.1性能测试

    测试数据 ab -n -c -k http://127.0.0.1/get_cache_value nginx.conf lua_shared_dict cache_ngx 128m; server ...

  9. 【源码】openresty 限流

    小结: 1.在连接环节计数,有清零环节 有3个参量 maxburst unit_delay https://github.com/openresty/lua-resty-limit-traffic/b ...

随机推荐

  1. MM-自制件改外购件

    自制件改外购件 https://wenku.baidu.com/view/fbb182c6bb4cf7ec4afed081.html

  2. active port

    2510099 - SSL Port XXXXX Not Active - message on NWA even though SSL works Resolution Open the defau ...

  3. Wireshark解密HTTPS数据流

    如果是chrome浏览器的数据流 直接配置”SSLKEYLOGFILE“就可以解密了. 实现过程: 1.配置系统环境变量 变量名:SSLKEYLOGFILE 变量值:随意指定一个存储路径,以便chro ...

  4. Vue指令之`v-text`和`v-html`

    v-text: 没有加载闪烁问题,它会覆盖元素中原本的内容,但是插值表达式,只会替换自己的这个占位符,不会把 整个元素的内容清空. v-html: 使用v-html可以把标签元素也能显示在元素上 &l ...

  5. Zabbix MySQL percona 模板部署

    Zabbix MySQL percona服务端执行以下操作https://www.zabbix.com/download?zabbix=4.0&os_distribution=centos&a ...

  6. JAVA笔记整理(五),JAVA中的继承

    1.继承的概念 继承是类与类的一种关系,是一种“is a”的关系 2.继承的好处 子类拥有父类的所有属性和方法,从而实现代码复用 4.方法的重写(Overridding) 如果子类对于继承自父类的方法 ...

  7. Socket的一些疑惑整理

    关于listen的问题请看steven<tcp/ip详解1>18章18.11.4 呼入连接请求队列一节,说的很清楚

  8. selenium xpath定位方式整理

    #xpath定位元素方法: /html/body/div[2] #绝对路径定位 #相对路径定位元素 //* #找到所有的元素 //input #找到input元素 //*[@*] #表示有属性的所有元 ...

  9. 小技巧:with用法 pycharm控制台输出带颜色的文字 打印进度条的

    with用法 with用法在python中是一个很独特的用法,因为别的语言的中没有这个用法.所以针对这个特点我们来做一次总结,什么样的情况下可以同with  我们学到的有文件的操作,和acquire  ...

  10. window.frameElement

    地址:MDN web docs 比如有一个iframe的src是xxx.htmframeElement的作用就是在xxx.htm中获得这个引用它的iframe objet这样你就可以在xxx.htm改 ...