当前位置: 首页 > news >正文

OpenResty 中实现限流(Rate Limiting)的实战案例

OpenResty 实战:使用 Lua 脚本实现限流(Rate Limiting)

在高并发系统中,限流是保障服务稳定性的重要手段。常见的限流场景包括:

  • API 网关防止恶意请求突发
  • 防止单个用户/接口过载影响整体服务
  • 与熔断、降级机制结合,提升系统鲁棒性

OpenResty 作为高性能 Web 平台,可以借助 Lua 脚本在 Nginx 层实现灵活的限流策略,例如 令牌桶(Token Bucket)漏桶(Leaky Bucket) 等。本文将通过一个实战案例,演示如何在 OpenResty 中实现 基于 Redis 的令牌桶限流


一、限流算法简介

常见的限流算法有两种:

  1. 固定窗口计数:在一个时间窗口内只允许 N 次请求,超出则拒绝。实现简单,但存在“突刺流量”问题。
  2. 令牌桶算法:系统按照固定速率往桶里放令牌,请求需要消耗令牌才能通过;如果桶空了,就拒绝请求。相比更平滑。

本文采用 Redis + Lua 脚本 来实现 分布式令牌桶限流,适用于集群环境。


二、环境准备

  • 已安装 OpenResty
  • 已安装并运行 Redis
  • 已安装 lua-resty-redis

安装命令(CentOS 举例):

luarocks install lua-resty-redis

三、Nginx 配置示例

编辑 nginx.conf

worker_processes 1;events {worker_connections 1024;
}http {server {listen 8080;# 限流接口location /api/limit {content_by_lua_file conf/lua/rate_limit.lua;}}
}

conf/lua/rate_limit.lua 中编写限流逻辑。


四、Lua 脚本实现限流

conf/lua/rate_limit.lua

local redis = require "resty.redis"
local red = redis:new()-- Redis 连接
red:set_timeout(1000)
local ok, err = red:connect("127.0.0.1", 6379)
if not ok thenngx.say("failed to connect: ", err)return
end-- 限流参数
local key = "limit:api"        -- 限流 key
local rate = 5                 -- 每秒生成令牌数
local capacity = 10            -- 桶容量
local now = ngx.now()          -- 当前时间戳(秒.毫秒)-- 获取上次请求时间和剩余令牌数
local last_time, tokens = red:hmget(key, "last_time", "tokens")if not last_time or last_time == ngx.null thenlast_time = nowtokens = capacity
elselast_time = tonumber(last_time)tokens = tonumber(tokens)
end-- 计算时间差,生成新令牌
local delta = now - last_time
local add_tokens = math.floor(delta * rate)
tokens = math.min(capacity, tokens + add_tokens)-- 更新最后访问时间
last_time = now-- 判断是否有令牌
if tokens > 0 thentokens = tokens - 1red:hmset(key, "last_time", last_time, "tokens", tokens)ngx.say("请求成功,剩余令牌:", tokens)
elsered:hmset(key, "last_time", last_time, "tokens", tokens)ngx.status = 429ngx.say("请求过多,请稍后再试!")
end-- 释放 Redis 连接
red:set_keepalive(10000, 100)

五、测试效果

  1. 在 Redis 中初始化限流桶(可选):

    redis-cli hset limit:api last_time 0 tokens 10
    
  2. 使用 ab 压测工具模拟请求:

    ab -n 20 -c 5 http://127.0.0.1:8080/api/limit
    
  3. 结果:

    • 前几次请求返回 请求成功,剩余令牌:X
    • 超过令牌桶容量后,返回 429 Too Many Requests

这样就实现了 基于令牌桶的限流


六、优化方向

  1. 不同用户限流:将 key 动态拼接用户 ID 或 IP,实现精细化控制。

    local client_ip = ngx.var.remote_addr
    local key = "limit:" .. client_ip
    
  2. Lua 脚本原子化:为了避免并发条件竞争,可以将逻辑写成 Redis Lua 脚本,用 EVAL 保证原子性。

  3. 本地共享内存限流:如果不需要分布式,可以用 lua_shared_dict(如 resty.limit.req 模块),性能更高。


七、总结

通过 OpenResty + Lua + Redis,我们实现了一个简单高效的 令牌桶限流机制,可用于 API 网关、登录接口、支付接口等关键场景。相比传统 Nginx 模块,Lua 提供了更高的灵活性,开发者可以根据业务需求随时扩展。


文章转载自:

http://9J90wvZc.mgwdp.cn
http://YrmW2wKe.mgwdp.cn
http://IpvA3C7V.mgwdp.cn
http://JX2O6gON.mgwdp.cn
http://HtEfGAnV.mgwdp.cn
http://gN12RMFm.mgwdp.cn
http://lgGpOgVI.mgwdp.cn
http://YRq3hUe5.mgwdp.cn
http://Cxc7zb4A.mgwdp.cn
http://z8AWDVCR.mgwdp.cn
http://yfnUrvN7.mgwdp.cn
http://8xrBOW5q.mgwdp.cn
http://kn6MwIiD.mgwdp.cn
http://7yyoGHRb.mgwdp.cn
http://H6OhwBaz.mgwdp.cn
http://FlplT48c.mgwdp.cn
http://ftQYAhg6.mgwdp.cn
http://mDbP466N.mgwdp.cn
http://bHpoR6gh.mgwdp.cn
http://blMfj6Pj.mgwdp.cn
http://tM9saZtp.mgwdp.cn
http://J50wZune.mgwdp.cn
http://LbkRg30B.mgwdp.cn
http://T7FbYvX8.mgwdp.cn
http://uU9SCb6P.mgwdp.cn
http://Qr5kMtaZ.mgwdp.cn
http://Zt4bEhH2.mgwdp.cn
http://wEC0jhDA.mgwdp.cn
http://WicCDRrt.mgwdp.cn
http://YGO7dmw1.mgwdp.cn
http://www.dtcms.com/a/377037.html

相关文章:

  • 告别“人肉API”时代:AI智能体如何重构人机协同新范式
  • Centos7部署ceph存储
  • 【Pywinauto库】10.1 pywinauto.base_wrapper控件
  • 机器人/人形机器人无法商业化落地的原因
  • 十一旅游气象的关键影响与“用大模型拿到更好天气数据”的落地路线
  • 软考系统架构设计师之软件测试篇
  • 【竞赛系列】机器学习实操项目04——客户信用评估模型开发全流程(baseline)
  • 爆破mysql登录密码
  • PG-210-HI 山洪预警系统呼叫端:筑牢山区应急预警 “安全防线”
  • 工业 CT 检测服务公司转型:扫描图像 AI 重构系统与客户检测需求智能匹配中台
  • 【CVPR2021】《Unbiased mean teacher for cross-domain object detection》译读笔记
  • AI时代技术面试重构:谷歌如何用Vibe Coding与抗作弊革命重塑招聘
  • 【Python/Pytorch】-- 贝叶斯定理
  • .NET Framework 和 .NET 的核心差异
  • Spring组件注解详解:@Component、@Service、@Repository、@Controller
  • STM32初始化串口重定向后printf调试信息不输出的问题
  • Monorepo 全面解析:优势、挑战与适用场景
  • 领码方案|Linux 下 PLT → PDF 转换服务超级完整版:异步、权限、进度(一气呵成)
  • TCP内网穿透:将局域网内部的TCP/HTTP服务暴露在公网上
  • day40 SQLite3单词查询程序设计与实现
  • 华为FreeBuds 7i其他手机能用空间音频吗?如何开启?
  • Java — Lambda 表达式与函数式接口解析
  • Apache Commons Math3 使用指南:强大的Java数学库
  • 数据结构中的 二叉树
  • SoC分区
  • 先买实现烦过
  • Qt C++ 图形绘制完全指南:从基础到进阶实战
  • 我在嘉顺达蓝海的安全坚守
  • fastadmin安装后后台提示putenv()报错,不显示验证码
  • macOS苹果电脑运行向日葵远程控制软件闪退