resty-limit-multiple-strategy.lua
--[[
执行过载限流策略
--]] -- 当执行限流时,Nginx 返回的状态码
err_code = local limit_config = {
user_limit = {rate = , brust = }, --用户限流维度桶设置
priority_uri_limit = { --指定 URI 限流维度桶设置
['/elis_smp_portal_dmz/do/cms/getLittleRedDotInfo'] = {rate = , brust = },
['/elis_smp_portal_dmz/do/esa/portal.msgcenter.unreadv2'] = {rate = , brust = },
['/elis_smp_portal_dmz/do/home/getUpgradeReminder'] = {rate = , brust = },
['/elis_smp_portal_dmz/do/userLogin/checkPluginVersion'] = {rate = , brust = },
['/elis_smp_portal_dmz/do/createRYMSession'] = {rate = , brust = },
['/elis_smp_portal_dmz/do/zone/queryZoneConfig'] = {rate = , brust = }
},
error_status = err_code, --请求被限流时返回状态码
nodelay = no --是否需要不延迟处理
} --定义限流策略方法名称
local limit_user_method = "limit_by_user"
local limit_uri_method = "limit_by_priority_uri" local limit_req = require "resty.limit.req" ngx.req.read_body() --过载保护策略总开关,若开关关闭,则全部策略失效
local limit_req_store = ngx.shared.limit_req_store
local overload_protection_switch = limit_req_store:get("overload_protection_switch")
if (overload_protection_switch ~= nil and overload_protection_switch == "N") then
ngx.log(ngx.INFO, "nginx limit strategy has been shutdown.")
return
end -- 获取当前请求 URI
local cur_uri = ngx.var.uri -- 执行过载操作
local is_in_black_list = limit_req_store:get("black_list:"..cur_uri)
local is_rejected_uri = reject_uri_tab["rejected"..cur_uri]
if (is_in_black_list ~= nil or is_rejected_uri ~= nil) then
-- 拦截比例,默认全部拦截
local request_limit_percent = limit_req_store:get("reject_request_percent")
if request_limit_percent == nil then
request_limit_percent =
end
local random_num = math.random()
if random_num <= tonumber(request_limit_percent) then
ngx.log(ngx.ERR,"nginx limit strategy current uri=",cur_uri," has been rejected.")
ngx.exit(ngx.HTTP_FORBIDDEN)
end
end -- 执行限流策略,入参:key 和 commit,commit 默认为 true
local function execute_limit_strategy(lim, key, commit, method)
-- 请求流入,如果你的请求需要被延迟则返回delay>0
local delay, err = lim:incoming(key, commit)
if (not delay and err == "rejected") then
ngx.log(ngx.ERR, "nginx limit strategy: ",method,", key: ", key, " request rate was exceeded, current request was rejected.")
ngx.exit(limit_config.error_status)
end -- 根据需要决定延迟或者不延迟处理
if delay > then
if limit_config.nodelay then
-- 直接突发处理
-- ngx.log(ngx.ERR, "nginx limit strategy: ", method, ", key: ", key, " request rate was exceeded, current request was rejected. delay")
-- ngx.exit(error_status)
else
--延迟处理
ngx.sleep(delay)
end
end
end -- 获取限流策略的共享内存
local function get_shared_dict(shared_dict_name, rate, burst)
local limit_shared_dict, err = limit_req.new(shared_dict_name, rate, burst)
if not limit_shared_dict then --没定义共享字典
ngx.log(ngx.ERR, "Nginx limit shared dict:", shared_dict_name, " has not been set.")
ngx.exit(error_status)
end
return limit_shared_dict
end -- 初始化 URL 限流策略 table
local uri_limit_tab = {} local user_lim if limit_config == nil then
ngx.log(ngx.ERR, "nginx request limit has no config info.")
return
else
local user_limit_config = limit_config.user_limit
ngx.log(ngx.DEBUG,"limit config user rate:", user_limit_config.rate, ", brust:", user_limit_config.brust)
user_lim = get_shared_dict("limit_req_store",user_limit_config.rate, user_limit_config.brust)
local priority_uri_limit_config = limit_config.priority_uri_limit
for key, value in pairs(priority_uri_limit_config) do
local rate = value.rate
local brust = value.brust
ngx.log(ngx.DEBUG,"limit config uri:", key, ", rate:", rate,", brust:",brust)
local lim = get_shared_dict("limit_req_store",rate,brust)
uri_limit_tab[key]=lim
end
end -- 执行指定 URI 限流策略
if uri_limit_tab[cur_uri] ~= nil then
execute_limit_strategy(uri_limit_tab[cur_uri], cur_uri , true , limit_uri_method)
end -- 获取客户端请求 IP
local remote_ip = ngx.var.remote_addr
local user_id
local device_id
local key_by_user -- 获取用户ID 或 设备号
local request_method = ngx.var.request_method
if "GET" == request_method then
user_id = ngx.req.get_uri_args()["uid"]
device_id = ngx.req.get_uri_args()["deviceId"]
ngx.log(ngx.DEBUG, "nginx request limit module GET parameter user_id: ",user_id, " header:",device_id)
elseif "POST" == request_method then
-- 获取请求头信息,如果缺少请求头信息判断,遇到上传文件操作时,会引起ngx.req.get_post_args()操作异常。
local receive_headers = ngx.req.get_headers()
local body_data = ngx.req.get_body_data()
if not body_data or (receive_headers["content-type"] ~= nil and string.sub(receive_headers["content-type"],,) == "multipart/form-data;") then
ngx.log(ngx.WARN,"nginx request limit module uri: ",cur_uri, " header:",receive_headers["content-type"],", body data:",body_data)
return
end
user_id = ngx.req.get_post_args()['uid'];
device_id = ngx.req.get_post_args()['deviceId'];
ngx.log(ngx.DEBUG, "nginx request limit module POST parameter user_id: ",user_id, " device_id:",device_id)
end -- 调试日志
ngx.log(ngx.ERR, "nginx request limit module cur_uri:",cur_uri, ", user_id: ",user_id) if (user_id ~= nil or device_id ~= nil) then
if user_id ~= nil then
key_by_user = user_id
else
key_by_user = device_id
end
execute_limit_strategy(user_lim,key_by_user..":"..remote_ip, true, limit_user_method)
end
resty-limit-multiple-strategy.lua的更多相关文章
- nginx安装lua模块实现高并发
nginx安装lua扩展模块 1.下载安装LuaJIT-2.0.4.tar.gz wget -c http://luajit.org/download/LuaJIT-2.0.4.tar.gz tar ...
- nginx + lua 限制ip地址访问
实验环境:docker + openresty 我限制的5秒钟内允许访问两次效果图: default.conf 代码如下: lua_shared_dict my_limit_count_store ...
- OpenResty之 limit.count 模块
原文: lua-resty-limit-traffic/lib/resty/limit/count.md 1. 示例 http { lua_shared_dict my_limit_count_sto ...
- Openresty+Lua+Kafka实现日志实时采集
简介 在很多数据采集场景下,Flume作为一个高性能采集日志的工具,相信大家都知道它.许多人想起Flume这个组件能联想到的大多数都是Flume跟Kafka相结合进行日志的采集,这种方案有很多他的优点 ...
- 线程池Executors探究
线程池用到的类在java.util.concurrent包下,核心类是Executors,通过其不同的几个方法可产生不同的线程池. 1.生成固定大小的线程池 public static Executo ...
- Nginx执行阶段
Nginx 介绍 Nginx (engine x) 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器. Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮 ...
- 又拍云张聪:OpenResty 动态流控的几种姿势
2019 年 1 月 12 日,由又拍云.OpenResty 中国社区主办的 OpenResty × Open Talk 全国巡回沙龙·深圳站圆满结束,又拍云首席架构师张聪在活动上做了< Ope ...
- 《用OpenResty搭建高性能服务端》笔记
概要 <用OpenResty搭建高性能服务端>是OpenResty系列课程中的入门课程,主讲人:温铭老师.课程分为10个章节,侧重于OpenResty的基本概念和主要特点的介绍,包括它的指 ...
- 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 ...
随机推荐
- Monkey进行压力测试定位问题分析
Monkey测试的log分析,我们可以通过几个关键词来判断测试是否通过. 分析log方法一(粗糙一点): 1)Monkey finished打开LOG,查看log的最下端,是否有类似以下字段:## ...
- HDU 3368 Reversi (暴力,DFS)
题意:给定一个8*8的棋盘,然后要懂黑白棋,现在是黑棋走了,问你放一个黑子,最多能翻白子多少个. 析:我是这么想的,反正才是8*8的棋盘,那么就暴吧,反正不会超时,把每一个格能暴力的都暴力,无非是上, ...
- 三分题两道:lightoj1146 Closest Distance、lightoj1240 Point Segment Distance (3D)
lightoj1146 Two men are moving concurrently, one man is moving from A to B and other man is moving f ...
- jeecms如何迭代list集合
[@cms_channel_list][#list tag_list as a ]${a.name} [/#list][/@cms_channel_list]使用[XXX_list] 参数为 tag_ ...
- 排序算法汇总(java实现,附源代码)
整理系统的时候发现了原来写的各种算法的总结,看了一下,大吃一惊,那时候的我还如此用心,具体的算法,有的已经模糊甚至忘记了,看的时候就把内容整理出来,顺便在熟悉一下,以后需要的时候就可以直接过来摘抄了. ...
- [.net 多线程 ]ReaderWriterLock
ReaderWriterLock 用于同步对资源的访问.在任一特定时刻,它允许多个线程同时进行读访问,或者允许单个线程进行写访问.在资源不经常发生更改的情况下,ReaderWriterLock 所提供 ...
- [.net 多线程]Barrier
当需要[一组任务]并行地运行一连串的阶段,但是每一个阶段都要等待所有他任务完成前一阶段之后才能开始,可以通过Barrier实例来同步这一类协同工作.Barrier初始化后,将等待特定数量的信号到来,这 ...
- githup上传文件
GitHub是基于git实现的代码托管.git是目前最好用的版本控制系统了,非常受欢迎,比之svn更好. GitHub可以免费使用,并且快速稳定.即使是付费帐户,每个月不超过10美刀的费用也非常便宜. ...
- OC字符串与C语言字符串之间的相互转换
1.C转OC字符串 const char *cString = "This is a C string"; // 动态方法 NSString *ocString1 = [[NSSt ...
- Jenkins忘记密码
当Jenkins密码忘记时,可以去Jenkins的安装目录下的users\用户名_xxxxx\config.conf文件下找下找到<passwordHash></passwordHa ...