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

基于 lua_shared_dict 的本地内存限流实现

OpenResty 实战:基于 lua_shared_dict 的本地内存限流实现

在高并发环境下,限流是保护系统的关键手段。前面我们用 Redis 实现了分布式令牌桶,但对于单机限流场景,还可以使用 OpenResty 自带的 lua_shared_dict

这种方案的优点是:

  • 高性能:直接存储在 Nginx 共享内存中,读写速度远高于 Redis。
  • 低延迟:不依赖外部存储,不存在网络开销。
  • 简单易用:配置简洁,部署方便。

本文将介绍如何用 lua_shared_dict + Lua 脚本 在 OpenResty 中实现一个高效的本地限流器。


一、原理说明

lua_shared_dict 是 OpenResty 提供的共享内存字典,所有 worker 进程可读写。我们可以在里面保存限流计数或令牌桶状态。

常见限流算法:

  1. 固定窗口:统计某个时间段内的请求数,超出则拒绝。
  2. 滑动窗口:更细粒度,适合平滑限流。
  3. 令牌桶(推荐):系统按速率往桶里放令牌,请求消耗一个令牌才能通过。

本文用 令牌桶 实现。


二、Nginx 配置

编辑 nginx.conf

worker_processes 1;events {worker_connections 1024;
}http {lua_shared_dict limit_store 10m;  # 共享内存 10MB,用于存放令牌桶server {listen 8080;location /api/local_limit {content_by_lua_file conf/lua/local_rate_limit.lua;}}
}

三、Lua 脚本实现

conf/lua/local_rate_limit.lua

-- 获取共享字典
local limit_store = ngx.shared.limit_store-- 限流参数
local key = "api:local:limit"
local rate = 5        -- 每秒生成令牌数
local capacity = 10   -- 桶容量
local now = ngx.now()-- 获取上次访问时间和令牌数
local last_time = limit_store:get(key .. ":last_time")
local tokens = limit_store:get(key .. ":tokens")if not last_time thenlast_time = nowtokens = capacity
end-- 补充令牌
local delta = now - last_time
local add_tokens = math.floor(delta * rate)
tokens = math.min(capacity, tokens + add_tokens)-- 更新最后访问时间
limit_store:set(key .. ":last_time", now)-- 判断是否还有令牌
if tokens > 0 thentokens = tokens - 1limit_store:set(key .. ":tokens", tokens)ngx.say("请求成功,剩余令牌:", tokens)
elselimit_store:set(key .. ":tokens", tokens)ngx.status = 429ngx.say("请求过多,请稍后再试!")
end

四、测试效果

  1. 启动 OpenResty:

    openresty -p `pwd`/ -c conf/nginx.conf
    
  2. ab 模拟请求:

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

    • 前 10 次(桶满 + 新令牌)会返回:

      请求成功,剩余令牌:X
      
    • 超过速率时返回:

      429 Too Many Requests
      请求过多,请稍后再试!
      

五、优化方向

  1. 针对用户或 IP 限流

    local client_ip = ngx.var.remote_addr
    local key = "limit:" .. client_ip
    
  2. 封装为模块
    可以写成 rate_limit.lua 工具库,供多个接口复用。

  3. 使用 OpenResty 自带模块
    OpenResty 提供了 resty.limit.req 库(基于 lua_shared_dict),功能更完善,还支持平滑限速。

    使用示例:

    local limit_req = require "resty.limit.req"
    local lim, err = limit_req.new("limit_store", 5, 10)
    local key = ngx.var.remote_addrlocal delay, err = lim:incoming(key, true)
    if not delay thenngx.exit(429)
    end
    ngx.say("请求成功")
    

六、总结

通过 lua_shared_dict,我们实现了一个本地高性能的 令牌桶限流器

  • 优点:速度快、延迟低、实现简单。
  • 缺点:仅限单机,无法跨节点共享限流状态。

如果是 单机 API 限流,推荐 lua_shared_dict
如果是 集群分布式限流,则建议用 Redis 或 etcd。



文章转载自:

http://nHJcSbcg.xswrb.cn
http://WpLkDVgS.xswrb.cn
http://sTdU57sd.xswrb.cn
http://bEsAYBRS.xswrb.cn
http://v8Cox1hY.xswrb.cn
http://XJxTpyvq.xswrb.cn
http://LtWEJGgj.xswrb.cn
http://mUwyZy57.xswrb.cn
http://MmhRBKzQ.xswrb.cn
http://3fcUvqcW.xswrb.cn
http://knd4AALb.xswrb.cn
http://LItmAZnf.xswrb.cn
http://wsuIlPe2.xswrb.cn
http://OumVKyDL.xswrb.cn
http://sbaT0Cg5.xswrb.cn
http://0QYiZcj8.xswrb.cn
http://1UhE0AWL.xswrb.cn
http://728QJkFQ.xswrb.cn
http://ggJPz5C0.xswrb.cn
http://6fpmqEmQ.xswrb.cn
http://Prx94VwC.xswrb.cn
http://9EWZMzSb.xswrb.cn
http://78dDbcql.xswrb.cn
http://wjYQr0IZ.xswrb.cn
http://ne8R2bLh.xswrb.cn
http://2IwKQOKH.xswrb.cn
http://Um4Nqs9U.xswrb.cn
http://m1JMbI4Z.xswrb.cn
http://eNOa0ghJ.xswrb.cn
http://qAdffDCM.xswrb.cn
http://www.dtcms.com/a/376555.html

相关文章:

  • 基于场景的自动驾驶汽车技术安全需求制定方法
  • 【lucene】pointDimensionCount` vs `pointIndexDimensionCount`:
  • 大语言模型入门指南:从原理到实践应用
  • 旧设备新智慧:耐达讯自动化RS232转Profibus连接流量泵工业4.0通关秘籍
  • 扭蛋机小程序有哪些好玩的创新功能?
  • 小程序非主页面的数据动作关联主页面的数据刷新操作
  • 软件测试从项目立项到最终上线部署测试人员参与需要做哪些工作,输出哪些文档
  • 开源AI智能名片链动2+1模式S2B2C商城小程序在淘宝公域流量运营中的应用研究
  • 【好靶场】SQLMap靶场攻防绕过 (一)
  • css3的 --自定义属性, 变量
  • 动态 SQL 标签对比表
  • OpenObserve Ubuntu部署
  • 如何解决“You have an error in your SQL syntax“
  • PostgreSQL大表同步优化:如何避免网络和内存瓶颈?
  • vue3 的痛点
  • 在 Ubuntu 22.04 系统(CUDA 12.9)中,通过本地DEB 包安装 cuDNN 9.13.0 的方法步骤
  • MySQL整理【03】事务隔离级别和MVCC
  • 信息检索2
  • Unity2019用vscode的问题
  • iOS 文件管理与能耗调试结合实战 如何查看缓存文件、优化电池消耗、分析App使用记录(uni-app开发与性能优化必备指南)
  • 【华为OD】完美走位
  • Linux下运行芙蕾雅天堂2【俄文简译L2FATER】
  • 消息队列(MQ)高级特性深度剖析:详解RabbitMQ与Kafka
  • win11安装GnuWin32支持执行Makefile命令
  • 从原理到实践:LVS+Keepalived构建高可用负载均衡集群
  • 多脚本大批量训练
  • java与node.js对比
  • tailwindcss 究竟比 unocss 快多少?
  • 排序---希尔排序(Shell Sort)
  • Windows系统下,配置VScode的git以及git终端