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; # 指定项目根目录
}
}
核心解读
获取请求体
- POST请求
- JSON格式
- 获取不到不能影响其他阶段继续执行
解析请求体获取目标参数
- cjson.decode()
- 操作map获取目标数据(限流的指标)
- 获取不到不能影响其他阶段继续执行
确定限流方式
- 限请求速率
- 限连接数
ngx-lua实现高级限流方式一的更多相关文章
- Lua学习高级篇
Lua学习高级篇 之前已经说了很多,我目前的观点还是那样,在嵌入式脚本中,Lua是最优秀.最高效的,如果您有不同的观点,欢迎指正并讨论,切勿吐槽.这个系列完全来自于<Programming in ...
- ngx.lua中遇到的小问题2
用lua+drizzle在数据库中插入数据失败(不能访问数据库) 后面发现原来是nginx配置文件中的drizzle模块部分最后多了一行 content_by_lua 'ngx.say(" ...
- ngx.lua中遇到的小问题
作者: 胡 志伟 分类: ngx_lua, 开发代码 发布时间: 2013-09-26 08:40 ė 6评论关闭 在使用ngx.redirect 到一个新的地址时,错误日志提示: lua entry ...
- java并发系列 - 第29天:高并发中常见的限流方式
这是java高并发系列第29篇. 环境:jdk1.8. 本文内容 介绍常见的限流算法 通过控制最大并发数来进行限流 通过漏桶算法来进行限流 通过令牌桶算法来进行限流 限流工具类RateLimiter ...
- ngx lua获取时间戳的几种方式
原创自由de单车 最后发布于2017-02-14 14:58:43 阅读数 18218 收藏 在ngx_lua里,获取时间相关信息的方式大概有4种(见下面代码): print(string.forma ...
- Spring Cloud Alibaba | Sentinel: 服务限流高级篇
目录 Spring Cloud Alibaba | Sentinel: 服务限流高级篇 1. 熔断降级 1.1 降级策略 2. 热点参数限流 2.1 项目依赖 2.2 热点参数规则 3. 系统自适应限 ...
- 从SpringBoot构建十万博文聊聊限流特技
前言 在开发十万博客系统的的过程中,前面主要分享了爬虫.缓存穿透以及文章阅读量计数等等.爬虫的目的就是解决十万+问题:缓存穿透是为了保护后端数据库查询服务:计数服务解决了接近真实阅读数以及数据库服务的 ...
- 高可用服务设计之二:Rate limiting 限流与降级
<高可用服务设计之二:Rate limiting 限流与降级> <nginx限制请求之一:(ngx_http_limit_conn_module)模块> <nginx限制 ...
- spring cloud gateway 之限流篇
转载请标明出处: https://www.fangzhipeng.com 本文出自方志朋的博客 在高并发的系统中,往往需要在系统中做限流,一方面是为了防止大量的请求使服务器过载,导致服务不可用,另一方 ...
随机推荐
- JS字符串格式化
//字符串格式化String.prototype.format = function () { var values = arguments; return this.replace(/\{(\d+) ...
- MM32F0020 UART1硬件自动波特率的使用
目录: 1.MM32F0020简介 2.UART自动波特率校准应用场景 3.MM32F0020 UART自动波特率校准原理简介 4.MM32F0020 UART1 NVIC硬件自动波特率配置以及初始化 ...
- 16_伯德图_手绘技巧与应用_Bode Plot_Part2
- char向wchar的转换-MultiByteToWideChar
问题产生 使用CreateFile函数,如下: CreateFile(lpcTheFile, GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NO ...
- 使用jquery-webcam插件,实现人脸采集并转base64
项目需求:在ie或chrome浏览器下,调用电脑摄像头(确保使用的是笔记本电脑,或者摄像头功能正常使用的台式机),进行人脸图像采集预览,并将图片的base64码传入到后台进行后续操作.该demo适用于 ...
- 纯CSS实现扁平化风格开关按钮
开关样式预览图 前言 最近在基于bootstrap框架开发一个网站,在填写表单一项需要用户填写是否选择某一选项,本来想引用bootstrap框架自带的一个按钮插件,结果在引用js的时候总是出错,就找了 ...
- 原型模式故事链--new一个对象的过程
上一个总标题:https://segmentfault.com/a/11...提问:你有对象了吗?答:没有.笨!new一个不就好了吗! 问题点:为什么我要理解new一个对象的过程?答:不理解这个过程, ...
- ES6-11学习笔记--Symbol
Symbol:一种新的原始数据类型 声明方式: let s1 = Symbol() let s2 = Symbol() console.log(s1); // Symbol() console.l ...
- 【vue 开发】Vue中splice的使用
splice(index,len,[item])它也可以用来替换/删除/添加数组内某一个或者几个值(该方法会改变原始数组) index:数组开始下标 len: 替换/删除的长度 item:替换的值,删 ...
- 93. 复原 IP 地址
做题思路or感想 这种字符串切割的问题都可以用回溯法来解决 递归三部曲: 递归参数 因为要切割字符串,所以要用一个startIndex来控制子串的开头位置,即是会切割出一个范围是[startIndex ...