ngx-lua实现高级限流方式一

博客 动态
0 222
羽尘
羽尘 2022-05-07 21:58:56
悬赏:0 积分 收藏

ngx-lua实现高级限流方式一

基于POST请求体中的某个参数限流

背景

电商平台有活动,活动涉及优惠券的抢券,优惠券系统对大并发支持略差,为了保护整体系统平稳,因此在入口Nginx层对抢券接口做了一层限流。

完整实现如下:

lua_shared_dict my_limit_req_store 100m;server {    listen 80;    server_name test.abc.com;    # 抢券接口    location = /api/v1/test {        lua_need_request_body on;        access_by_lua_block {            local cjson = require("cjson")            -- 获取POST请求体            if ngx.var.request_method == "POST" then                ngx.req.read_body()                local data = ngx.req.get_body_data()                -- 获取限流字段 appName, 获取不到则跳出lua                if data then                    params = cjson.decode(data)                    if params["appName"] then                        limit_key = params["appName"]                    else                        ngx.log(ngx.ERR, "未获取到appName,不做限流")                        -- 退出access_by_lua阶段,继续执行其他阶段。                        ngx.exit(0)                    end                else                    ngx.log(ngx.ERR, "获取请求体失败,跳过限流配置")                    ngx.exit(0)                end            else                ngx.log(ngx.ERR, "不对非POST请求进行处理")                ngx.exit(0)            end            -- 限流逻辑            local limit_req = require "resty.limit.req"            local lim, err = limit_req.new("my_limit_req_store", 200, 100)            if not lim then                    ngx.log(ngx.ERR, "failed to instantiate a resty.limit.req object: ", err)                    return ngx.exit(500)            end            local delay, err = lim:incoming(limit_key, true)            if not delay then                if err == "rejected" then                    return ngx.exit(503)                end                ngx.log(ngx.ERR, "failed to limit req: ", err)                return ngx.exit(500)            end            if delay >= 0.001 then                local excess = err                ngx.sleep(delay)            end        }        try_files $uri $uri/ /index.php?$query_string;    }    location / {        try_files $uri $uri/ /index.php?$query_string;    }    location  ~ \.php$ {        # 设置项目根目录        set $PROJECT_NAME "/data/www/test.abc.com/public";        # 设置upstream_name        set $fastcgi_name test;        index index.php index.html index.htm;        include  fastcgi_params;        fastcgi_pass   $fastcgi_name;        fastcgi_index  index.php;        fastcgi_param  SCRIPT_FILENAME  $PROJECT_NAME$fastcgi_script_name;     # 指定项目根目录    }}

核心解读

  1. 获取请求体

    1. POST请求
    2. JSON格式
    3. 获取不到不能影响其他阶段继续执行
  2. 解析请求体获取目标参数

    1. cjson.decode()
    2. 操作map获取目标数据(限流的指标)
    3. 获取不到不能影响其他阶段继续执行
  3. 确定限流方式

    1. 限请求速率
    2. 限连接数
posted @ 2022-05-07 21:19 白--茶 阅读(5) 评论(1) 编辑 收藏 举报
回帖
    羽尘

    羽尘 (王者 段位)

    2335 积分 (2)粉丝 (11)源码

     

    温馨提示

    亦奇源码

    最新会员