lua并发限流代码

本文介绍了如何在Nginx中使用Lua实现并发限流,通过在nginx.conf配置lua_shared_dict,并展示了具体的Lua限流代码,以保障分布式架构下的API服务稳定性。

首先在nginx.conf 文件中的http节点添加:

lua_shared_dict limit_req_store 10m;

以下是lua并发限流代码:

local limit_req = require "resty.limit.req"

--限制请求速率为500 req/sec
local lim,err = limit_req.new("limit_req_store",5,0)
if not lim then --申请limit_req对象失败
ngx.log(ngx.ERR,"failed to instantiate a resty.limit.req object: ",err)
return ngx.exit(500)
end

-- 下面代码针对每一个单独的请求
-- 使用ip地址作为限流的key
local key = ngx.var.binary_remote_addr
local delay,err = lim:incoming(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 then
--第二参数(err)保存着超过请求速率的请求数
--例如err等于31,意味着当前速率是 531 req/sec
local excess = err

---- 当前请求超过200 req/sec 但小于 300 req/sec
-- 因此我们sleep一下,保证速率是200 req/sec,请求延迟处理
ngx.sleep(delay) --非阻塞sleep(秒)
end
ngx.say("you success!!!")

 

### 使用 Nginx 和 Lua 实现 API 请求限流 API 请求限流是一种常见的技术手段,用于保护服务器免受过载影响并优化资源分配。Nginx 结合 Lua 可以提供一种高效且灵活的方式实现这一目标。 #### 配置环境 为了使用 Nginx 和 Lua 进行限流,需安装 OpenResty 或者启用 `ngx_http_lua_module` 模块的 Nginx 版本[^1]。OpenResty 是一个基于 Nginx 的平台,集成了许多有用的模块,其中包括 Lua 支持。 --- #### 示例代码:基于 Redis 的令牌桶算法限流 以下是通过 Nginx 和 Lua 实现分布式限流的一个典型例子: ```nginx http { lua_shared_dict limit_req_store 10m; # 定义共享内存存储区 init_by_lua_block { local redis = require "resty.redis" local red = redis:new() red:set_timeout(1000) -- 设置超时时间 (毫秒) function connect_redis() local ok, err = red:connect("127.0.0.1", 6379) if not ok then ngx.log(ngx.ERR, "failed to connect: ", err) return nil end return red end } server { listen 80; server_name localhost; location /api/limited_resource { content_by_lua_block { local red = connect_redis() -- 调用初始化函数连接到 Redis if not red then ngx.exit(500) end local key = "rate_limit:" .. ngx.var.remote_addr local rate = 10 -- QPS 限制为每秒 10 个请求 local burst = 5 -- 允许突发量 local max_tokens = rate + burst -- 获取当前剩余 token 数量 local tokens = tonumber(red:get(key)) if not tokens or tokens > max_tokens then tokens = max_tokens elseif tokens < 1 then ngx.status = 429 -- Too Many Requests ngx.say("Too many requests!") ngx.exit(429) end -- 减少一个 token 并更新 Redis 中的数据 tokens = tokens - 1 local new_token_count = math.max(tokens, 0) -- 更新 Redis 数据,设置生存时间为 1 秒 local ttl = red:ttl(key) if ttl == -1 then ttl = 1 end red:set(key, new_token_count) red:expire(key, ttl) ngx.say("Request processed successfully.") } } } } ``` 此代码片段展示了如何利用 Redis 存储用户的令牌数量,并通过 Lua 计算是否允许该次请求继续处理[^3]。 --- #### 关键点解析 1. **Lua Shared Dictionary**: 如果不需要依赖外部数据库(如 Redis),可以通过 `lua_shared_dict` 来保存状态数据。这种方式适合单机部署场景下的简单限流需求。 2. **Redis 扩展能力**: 对于分布式的高并发场景,推荐使用 Redis 作为后端存储服务。它提供了原子操作支持以及持久化功能,非常适合管理动态变化的状态信息。 3. **QPS 控制逻辑**: 上述示例采用了经典的令牌桶算法来控制请求速率。每次接收到新请求时都会尝试消耗一定数量的令牌;如果不存在足够的可用令牌,则拒绝此次请求返回 HTTP 状态码 429[^4]。 4. **错误处理机制**: 在实际应用中还需要考虑网络异常情况下的健壮性设计,比如重试策略或者降级措施等[^2]。 --- #### 性能考量 - **吞吐量 vs 延迟**:合理调整缓存大小 (`lua_shared_dict`) 和 Redis 查询频率之间的平衡关系对于保持良好的性能至关重要。 - **扩展性**:随着业务规模增长可能需要引入更多节点组成集群架构从而分担负载压力。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

诸葛本不亮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值