• ngxlua实现高级限流方式一 白


    基于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. 限连接数
  • 相关阅读:
    Single Image Dehazing via Conditional Generative Adversarial Network(CVPR2018-图像去雾)
    STF-GAN:Recovering Realistic Texture in Image Super-resolution by Deep Spatial Feature Transform (CVPR2018)
    os 模块
    Pytorch-get ready with me
    Python学习(第七章)
    Python学习(第六章)
    pytorch与opencv 安装(Linux)
    Python学习(第五章)
    Python学习(第四章)
    Python学习(第三章)
  • 原文地址:https://www.cnblogs.com/chaizhenhua/p/16244176.html
Copyright © 2020-2023  润新知