前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >nginx结合lua实现策略性限流量控制

nginx结合lua实现策略性限流量控制

作者头像
友儿
发布2022-09-13 15:57:19
1.1K0
发布2022-09-13 15:57:19
举报
文章被收录于专栏:友儿
简介
  • 依据预定义的参数或者初始化配置文件的参数,获取请求参数与之对应,实行策略性限制流量达到可控的目的。
  • 使用openresty的lua-resty-limit-traffic模块进行限流。 准备工作
  • 需要使用到以下两个模块可以移步到此文章查看详细介绍(字符串分割strsplit模块nginx 共享缓存get以及set的ngxshare模块)

lua常用的工具类封装汇总

Lua引用模块与包点击查看菜鸟教程简单配置如下#LUA_PATH # 文件路径以 ";" 号分...

nginx.conf 配置
代码语言:javascript
复制
worker_processes  1;
error_log logs/error.log;
events {
    worker_connections 1024;
}
http {
    # 设置纯 Lua 扩展库的搜寻路径(';;' 是默认路径)
    lua_package_path "/data/www/code/nginx+lua/config/lua_p/?.lua;;";
    # 设置 C 编写的 Lua 扩展模块的搜寻路径(也可以用 ';;')
    lua_package_cpath "/data/www/code/nginx+lua/config/lua_p_c/?.so;;";
    #共享缓存
    lua_shared_dict my_limit_store 5m;
    lua_shared_dict my_limit_req_store 5m;
    #初始化限流
    init_by_lua_file config/lua/limit_init.lua;

    server {
       listen 8080;
       location /limiter_reset {
            lua_code_cache off;
            content_by_lua_file ./config/lua/limit_reset.lua;
            charset utf-8;
       }

       location /limiter {
            lua_code_cache off;
            content_by_lua_file ./config/lua/limiter.lua;
            charset utf-8;
       }
    }
}
limit_init.lua(初始化lua脚本内容)
代码语言:javascript
复制
local limit_table = ngx.shared.my_limit_store;
local strsplit = require("strsplit");
file = io.open("config/init/limit.txt", "r");
if nil == file then
    ngx.log(ngx.INFO, "文件读取失败,将采用默认值进行赋值");
    local suc, err = limit_table:set("default", "15-15");
else
    for line in file:lines() do
        local splitTable = strsplit.split(line, "-");
        local sysFlag = splitTable[1];
        local limitRate = splitTable[2];
        local bursts = splitTable[3];
        local tableVal = string.format("%s-%s", limitRate, bursts);
        ngx.log(ngx.INFO, "sysFlag = ", sysFlag, "限流阀值:流速-桶容量:", tableVal);
        limit_table:set(sysFlag, tableVal);
    end
    file:close();
end
limit_reset.lua文件(依据GET请求参数重置策略值)
代码语言:javascript
复制
local strsplit = require("strsplit");
local ngxshare = require("resty.ngxshare");
-- get request param
local args, err = ngx.req.get_uri_args();
local limitvalue = args["limitvalue"];
ngx.say("-----------limitvalue-----------", limitvalue);
local limitParam = strsplit.split(limitvalue, "-");
local sysFlag = limitParam[1];
ngx.say(ngxshare.shared_dic_get(ngx.shared.my_limit_store, sysFlag));
local rateBurst = string.format("%s-%s", limitParam[2], limitParam[3]);
ngx.say("-------------rateBurst:", rateBurst);
ngxshare.shared_dic_set(ngx.shared.my_limit_store, sysFlag, rateBurst, 0);
ngx.say("---------------", ngxshare.shared_dic_get(ngx.shared.my_limit_store, sysFlag));
limit.txt文件 (限流策略配置文件)
代码语言:javascript
复制
test-10-200  # 其中test为请求渠道标识,10 为流速, 200为桶容量
test1-1-1
limit.lua文件 (策略性限流主文件)
代码语言:javascript
复制
-- 获取请求参数
local strsplit = require("strsplit");
ngx.req.read_body();
local args, err = ngx.req.get_uri_args();
local sysFlag = args["sys"];
local limit_table = ngx.shared.my_limit_store;
local limitRate = limit_table:get(sysFlag);
if not limitRate then
    ngx.log(ngx.INFO, "sysFlag can not found so set defalut value");
    limitRate = limit_table:get("default");
end
-- 获取到的值进行拆分并限流
local limitValue = strsplit.split(limitRate, "-");
local rate = tonumber(limitValue[1]);
local burst = tonumber(limitValue[2]);
local limit_req = require "resty.limit.req";
ngx.say("rate====", rate, "---burst=====", burst);
-- 根据配置项创建一个限流的table。
local lim, err = limit_req.new("my_limit_req_store", rate, burst);
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(sysFlag, true);
if not delay then
    if err == "rejected" then
        ngx.say("rejected access service..............");
        ngx.log(ngx.INFO, "rejected access service..............", err);
        return ngx.exit(503);
    end
    ngx.log(ngx.INFO, "failed to limit req: ", err);
    return ngx.exit(500);
end
ngx.log(ngx.INFO, "access received..............");
ngx.say("access received..............");
测试
代码语言:javascript
复制
# 测试一: http://192.168.56.2:8080/limiter?sys=t  
#未定义的策略性标识给其默认值    
rate====15---burst=====15
access received..............
# 测试二: http://192.168.56.2:8080/limiter?sys=test
#定义的策略性标识解析
rate====10---burst=====200
access received..............
# 测试三:http://192.168.56.2:8080/limiter?sys=test1  
#一秒内请求第一次通过
rate====1---burst=====1
access received..............
#一秒内请求第二次被限制
rate====1---burst=====1
rejected access service..............
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
  • nginx.conf 配置
  • limit_init.lua(初始化lua脚本内容)
  • limit_reset.lua文件(依据GET请求参数重置策略值)
  • limit.txt文件 (限流策略配置文件)
  • limit.lua文件 (策略性限流主文件)
  • 测试
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档