30 Star 171 Fork 49

haixing / lua-limit

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
MIT

Lua 流控工具说明


如发现缺陷,或者有改进意见请联系我,mahaixing@gmail.com


文件说明

  1. limiters
    目录,包含所有限流规则,新增限流规则需要放到该目录中
  2. restry
    目录,包含 openrestry 的 cookie 处理类,我安装的环境中没有这个类
  3. limit_conf.lua.sample
    限流配置文件示例
  4. limit.lua
    限流主文件,参考下方文档
  5. nginx.conf.test
    测试的 openresty 配置文件,可以直接使用
  6. test*.lua
    测试文件,可以作为示例参考
  7. utils.lua
    工具方法文件

1. 思路

限流脚本的设计思路源于规则链,用户请求进入 nginx 后,请求会进入限流脚本配置的限流链,在链中的规则中逐个匹配处理,如果某条限流规则匹配此请求,那么将跳出规则链执行循环,返回被限流信息,除非此规则明确说明需要参考链中下一条规则。

2. 流控工具使用

需要编写限流脚本,脚本可以参考如下(some_business_limit.lua):

    local conf = {
        redis = {...}
        some_limit_rule_1 = {...}
        some_limit_rule_2 = {...}
    }

    -- 如果不传 conf 那么会在 package.path 中寻找
    -- limit_conf.lua 文件
    local limit = require "limit":new(conf)
    funciton some_who_1(limit) 
        return true, "some_limit_rule_1"
    end

    function some_who_2(limit)
        local redis = limit:get_redis()
        -- some_redis_operation
        -- target find 

        if is_target then
            return true, "some_limit_rule_2"
        else
            return false
        end 
    end

    function some_message(limit, data)
        -- 返回页面
        limit.send_redirect("limit.html")

        -- 返回json
        limit.send_redirect("xxx.html", data)
    end

    limit:who({some_who_1, some_who_2}):execute()

在 nginx 的 http 块中配置 package.path 是的 lua 解释器可以找到脚本文件,在需要限流的 location 部分增加 access_by_lua_file 指定 lua 脚本(当然也可以使用content_by_lua),如:

    http {
        lua_package_path "/some_place/limit/limit-common/?.lua;;";

        server {
            location /some_url {
                access_by_lua_file /some_place/some_business_limit.lua;
            }
        }
    } 

3.配置文件

配置文件用来配置 redis 和限流规则链,参考 limit_conf.lua.sample 文件,其中:

  1. redis 部分是固定名称,不要修改名称和结构
  2. default_rule 是默认的规则链,在没有给 who 函数时会默认使用这个规则链,如果给了 who 函数,那么可以不配置它。
  3. xxx_rule 自定义规则链
  4. 每个规则连链下的属性的 key 值是 limiters/xxx.lua 中的每个文件名(去掉.lua)。根据业务需要配置

3.1 bucket

文件 limiters/bucket.lua 使用令牌桶进行限流,配置项:

  • 需要在 nginx 配置文件中配置共享 dict,如:

        http {
            lua_shared_dict my_limit_conn_store 100m;
    
            server {
                location / {
                    ...
                }
            }
        }
  • bucket_dict_name

    共享 dict 名,字符串,需要与 nginx 配置文件中一致

  • bucket_rate

    限制请求速率,数字,比如 200 表示 200个请求每秒

  • bucket_burst = 0,

    允许的突发速率,数字,比如 100 表示 允许在 200 个请求每秒的基础上突发 100 个请求每秒的量

  • bucket_target = ”ip“

    限制的目标,字符串,只能配置为:ip 或者 uri

    ip: 表示针对客户端IP地址

    uri: 表示针对被请求的地址

3.2 cookie

文件 limiters/cookie.lua,基于 cookie 限流,配置项:

  • cookie_domain cookie 所属域名,字符串 如: "example.com"

  • cookie_path 路径,字符串,如 "/"

  • cookie_key cookie 键名,字符串,如:"example_limit",

  • cookie__value 写入的 cookie 值,字符串,如:"1",

3.3 date_range

文件 limiter/date_range.lua,基于时间范围限流,配置项:

  • start_datetime

    起始时间,固定格式 table

    如: {year=2018, month=03, day=30, hour=0, min=0, sec=0},

  • end_datetime

    截止时间,固定格式 table

    如:{year=2018, month=04, day=30, hour=0, min=0, sec=0},

  • week_day

    具体星期几

    可以是 table,如: {3,4,5}

    可以是整数,如:1(代表周一)

    无论是 table 还是整数,配置的数值必须在 1-7 之间

3.4 limiter

文件 limiters/limiter,无条件限流,所有目标请求均被限制,无配置项,给个空 table 即可,如:

    default_rule = {
        limiter = {}
    }

3.5 probablity

文件 limiters/probability.lua,概率限流,配置项:

  • probability_rate

    限流概率,整数,如:80 代表 80% 流量将被限制掉

4. 关键函数

4.1 限流目标,who 函数

在 nginx 的 location 块配置中,限流是针对 URL 配置的。但是具体限流的目标由于应用的不同各不相同,需要针对参数确定限流对象,比如:

  1. 有些业务限流是基本匹配同一个URL,但是会根据请求的参数来匹配限流目标。
  2. 有些是根据 redis 中保存的目标用户,再匹配请求中传递的目标客户来确定限流目标
  3. 有些是根据保存在 redis 中的黑白名单进行限流

因此,在限流脚本中,需要具体业务实现 who 函数,who 函数用来确定当前请求是否是限流的目标请求。

  • 比如根据 url 参数(或者 cookie),从 redis 中查找是否是黑名单
  • 比如根据 url 参数(或者 cookie),从 redis 中找到是否属于限流地址
  • 比如根据 url 参数(或者 cookie),确定是否为某个具体业务

who 函数的原型是:

    function some_who_func(limit) 

返回值最多 2 个,返回 true 时至少返回两个返回值,返回 false 时则无需返回另一个返回值,返回值说明:

  1. boolean,当前请求是否是限流目标
  2. table 包含以下数据
    1. rule: 字符串类型,适用此目标的规则名

      比如:"xxx_rule",如果为 nil 那么使用默认规则名 "default_rule"

    2. message: function 类型,适用此目标的返回 message 函数

      如果为nil,则使用默认的 message 函数 default_message,参考 limit.lua

    3. data: table 类型,可选的,需要传递给 message 处理的数据

      可以为 nil ,说明无数据需要 message 处理

who 函数可以有多个,作为 table 传给 limit ,比如:

    limit:who({who_func1, who_func2, who_func3})

也可以只有一个,比如:

    limit:who(who_func_single)

who 函数匹配到目标后,脚本会停止调用后续 who 函数。匹配到目标的 who 函数必须返回 true 以及 目标适用的限流链、适用的 message 函数、额外需要传递的数据,如果 who 函数返回 false ,那么限流脚本会调用下一个 who 函数寻找。

如果不配置 who 函数,那么 limit 会使用默认的 who 函数,返回默认的 defualt_rule 以及默认的 default_message

4.2 message 函数

message 函数用于在请求限流后,返回响应数据给浏览器,message 函数的原型是:

    function some_message(limit, data)

其中:

  1. limit 是主控类,可以从 limit 类或者配置信息,以及请求参数信息(GET 和 POST 传递的参数),参考 limit.lua
  2. data 是匹配的 who 函数返回的,根据需要使用。

在 message 函数中可以根据业务需要输出 mime 头以及其他 http 控制头。

可以根据需要返回 json 数据、xml 数据或者其他形式的数据

可以仅仅跳转到指定页面。

可以针对每个限流目标,指定一个 message 函数,参考 who 函数说明

5. 扩展

如果有新的限流规则,可以扩展此脚本,在 limiters 目录下新建规则文件 some_new_rule.lua,文件需要参考以下模板:

    local assert = assert
    local utils = require "utils"

    local _M = require("limiters.limiter"):new()

    function _M:process_config() 

    end

    function _M:execute()

        -- 如果不需要限流当前请求
        return false

        -- 如果限流当前请求,不需要参考下一条规则
        return true, false

        -- 如果限流当前请求,需要参考下一条规则
        return true, true

    end

    return _M
MIT License Copyright (c) 2019 haixing Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

简介

OpenRestry Lua 限流工具,支持 令牌桶限流、cookie 限流、日期范围限流、概率限流 展开 收起
Lua
MIT
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
Lua
1
https://gitee.com/mahaixing/lua-limit.git
git@gitee.com:mahaixing/lua-limit.git
mahaixing
lua-limit
lua-limit
master

搜索帮助