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 ...
随机推荐
- threading学习
多线程类似于同时执行多个不同程序,多线程运行有如下优点: 使用线程可以把占据长时间的程序中的任务放到后台去处理. 用户界面可以更加吸引人,这样比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进 ...
- 如何处理与开发有争议的Bug?
工作中,测试人员有时会遇到类似的问题:提交了一份软件缺陷报告,可由于某种原因,无论是开发人员还是开发经理就是不愿修改程序.应如何处理这类问题呢?我认为,当对报告出现分歧意见后,测试工程师应首先做如下 ...
- Java 起名规范
注重代码编写规范: 1)都得遵循标识号的规范 2)不能以关键字,数字开头.也不要以拼音起名,最好用英文单词,单词组合来起名. 3)采用驼峰表示法,使用英文单词组合,单词首字母要大些,起到分割作用. - ...
- 探索Asp.net mvc 的文件上传(由浅入深)
代码下载:http://files.cnblogs.com/n-pei/mvcfileupload.zip 最近因为TeamVideo需要用到视频和图片上传功能,所以试着Google了很多资料,和大家 ...
- telerik 值得学习 web mvc 桌面 控件大全
http://www.telerik.com http://www.dxper.net/forum-70-1.html http://www.dxper.net/forum.php
- Oracle Cannot Update TOP N Issue, 请专家解答
大家好 上周写了匿名方法一文,很多读者,很高兴,相信我们已经从大伙的回复中,对.NET又有了更深刻的认识. 好,现在说主题,各类数据库都有相应更新本表top n的方案.现在我一一举例 首先看表结构如下 ...
- 【转】开源视频录制库LandscapeVideoCamera
非常强大的android 视频录制库,可以选择视频尺寸以及视频质量,只允许横屏录制. 使用Android自带的Camera应用可以录制视频,只需发送MediaStore.ACTION_VIDEO_CA ...
- Redis 一个很诡异的问题(部署)
使用Redis并用window服务的方式 运行时.突然报错 在启动进程意外中止 解决方案: 调试了很久 发现居然是在 Logfile的配置中的问题. 错误的logfile logfile " ...
- Time - Time-interval Measurements
public class TimeHelper { private long _start, _stop, _elapsed; /// <summary> /// 获取初始时间戳 /// ...
- EF Power Tools使用
转载:http://blog.csdn.net/planisnothing/article/details/8532316 1.可以很方便根据数据库生成Code First模式的代码,如果是已有项目转 ...