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

wasm~tinygo写一个基于redis全局限流插件

Global Limit 插件

插件功能

基于白名单的全局限流插件,对指定的域名和URL路径进行全局限流控制,共享同一个限流计数器。

核心特性

  • 按域名 + URL路径进行全局限流
  • 使用 Redis Sorted Set 实现滑动时间窗口
  • 白名单机制:只对配置的域名和路径进行限流
  • 支持正则表达式匹配URL路径

实现逻辑

1. 请求处理流程

请求到达 → 检查域名白名单 → 检查路径白名单 → Redis限流判断 → 放行/拒绝

2. 核心组件

配置解析 (parseConfig)

  • 解析域名白名单 hosts
  • 解析路径白名单 paths(支持正则表达式)
  • 配置限流参数:
    • unitSecond: 统计周期,默认30秒
    • qpm: 周期内最大请求数,默认10次
    • key: Redis存储的key名称
  • 初始化 Redis 客户端连接

域名过滤 (SkipHost)

  • 只有在白名单中的域名才进行限流
  • 未在白名单中的域名直接放行

路径过滤 (SkipPath)

  • 使用路径过滤器匹配URL
  • 支持正则表达式匹配
  • 未匹配的路径直接放行

3. 限流算法 - 滑动窗口

采用 Redis Sorted Set + Lua 脚本 实现滑动窗口限流:

-- Lua 脚本执行原子操作
1. ZREMRANGEBYSCORE: 删除过期数据(分数 < now - window)
2. ZCOUNT: 获取当前窗口内的请求数
3. 判断 count >= limit,超过则返回1
4. ZADD: 添加新请求(score=时间戳,member=UUID)
5. EXPIRE: 设置key过期时间
6. 返回0表示未超限

关键特性

  • 原子性:Lua 脚本保证操作的原子性
  • 滑动窗口:基于时间戳的精确滑动窗口
  • 自动过期:过期时间设为统计周期的2倍
  • UUID去重:每个请求使用唯一ID作为成员

4. 限流响应

超过限制时返回:

HTTP 429 Too Many Requests
{"code": 429,"message": "Too Many Requests"
}

配置参数

参数 类型 必填 默认值 说明
serviceName string - Redis服务名称
servicePort int - Redis端口
domain string - Redis域名
username string - Redis用户名
password string - Redis密码
timeout int - 连接超时时间(ms)
hosts []string - 域名白名单
paths []string - URL路径白名单(支持正则)
unitSecond int 30 统计周期(秒)
qpm int 10 周期内最大请求数
key string global-limit-plugin-key Redis key名称

配置示例

serviceName: "test-redis-service"
servicePort: 6379
domain: "xxx.redis.rds.aliyuncs.com"
username: "user"
password: "password"
timeout: 50000
hosts:- "api.example.com"- "www.example.com"
paths:- "/auth/token"- "/api/sensitive/.*"
unitSecond: 60
qpm: 100
key: "my-global-limit"

与 Route Limit 的区别

特性 Global Limit Route Limit
限流维度 全局共享计数器 每个URL独立计数
配置方式 统一配置qpm 每个URL单独配置
适用场景 整体流量控制 精细化接口限流
路径过滤 白名单过滤 规则匹配

使用场景

  1. 全站流量控制:对整个站点进行统一的流量限制
  2. 核心接口保护:对重要接口进行全局访问频率控制
  3. 防止突发流量:在高并发场景下保护后端服务
  4. 白名单限流:只对特定域名和路径进行限流保护

核心代码

now := time.Now()nowTimestamp := now.Unix() //秒数intervalTime := int64(config.unitSecond)// 使用 Lua 脚本实现:清理过期数据 + 计数 + 添加新记录 + 设置过期时间// 返回值:0 表示未超限,1 表示已超限luaScript := `local key = KEYS[1]local now = tonumber(ARGV[1])local window = tonumber(ARGV[2])local limit = tonumber(ARGV[3])local member = ARGV[4]local expire_time = tonumber(ARGV[5])-- 删除过期数据(分数小于 now - window 的成员)redis.call('ZREMRANGEBYSCORE', key, '-inf', now - window)-- 获取当前窗口内的请求数local count = redis.call('ZCOUNT', key, now - window, now)if count >= limit thenreturn 1  -- 超过限制end-- 添加新请求redis.call('ZADD', key, now, member)-- 设置key的过期时间,防止key永久存在redis.call('EXPIRE', key, expire_time)return 0  -- 未超过限制`// 准备参数var keyArr []interface{}keyArr = append(keyArr, config.key)var valueArr []interface{}uuid := uuid.New()expireTime := config.unitSecond * 2 // 过期时间设为统计周期的2倍valueArr = append(valueArr, nowTimestamp, intervalTime, config.qpm, uuid.String(), expireTime)// 执行 Lua 脚本err := config.Client.Eval(luaScript, 1, keyArr, valueArr, func(response resp.Value) {if response.Integer() == 1 {// 超过限制fmt.Println("TOO_MANY_REQUESTS 429 ,path:", ctx.Path(), ",ipAddress:", util.GetClientIP())headers := [][2]string{{"Content-Type", "application/json"}}proxywasm.SendHttpResponse(429, headers, []byte("{\"code\":429,\"message\":\"Too Many Requests\"}"), -1)} else {// 未超过限制,继续请求proxywasm.ResumeHttpRequest()}})if err != nil {log.Errorf("rate limit error while calling redis: %v", err)proxywasm.ResumeHttpRequest()}return types.ActionPause
http://www.rkmt.cn/news/147360.html

相关文章:

  • 2025年铁路地铁电力电缆生产厂家推荐:铁路地铁电力厂家名单TOP榜单(12月新) - 品牌2026
  • Open-AutoGLM语音唤醒实战指南(从零搭建高准确率唤醒系统)
  • 2025南京留学中介权威榜单:高口碑机构实力揭晓 - 留学品牌推荐官
  • Open-AutoGLM与Python 3.14兼容性问题全记录(专家级排错指南)
  • 还在为AutoGLM环境配置发愁?,资深架构师亲授高效部署方案
  • 2025南京留学中介权威榜单:优质服务机构TOP10揭晓 - 留学品牌推荐官
  • Open-AutoGLM是一条很陡:为什么只有1%的项目能走到推理部署阶段?
  • Flink SQL / Table API 自定义函数(UDF)全家桶从 Scalar 到 PTF,一篇搞懂设计、实现与坑点
  • 2025年天津阻燃电缆生产厂家推荐:阻燃、阻燃B1级、矿物质防火等电缆生产厂家盘点(12月榜单) - 品牌2026
  • 【AI语音交互新纪元】:Open-AutoGLM如何重新定义语音唤醒体验?
  • 2025南京留学中介权威榜单:这十家机构口碑实力双优 - 留学品牌推荐官
  • 2025年实木桌椅制造商权威推荐榜单:实木床头柜/实木衣柜/实木电视柜源头生产工厂精选 - 品牌推荐官
  • Simulink 二次调频:融合风电机组的双区域 AGC 调频探索
  • 从零到一:企业级Web项目完整部署指南
  • 2025年高温合金GH4169个性化定制/综合服务商/知名制造商排行榜 - myqiye
  • 学习通每个班级创建的试卷库不可以共享,但是里面可以导出试卷库.ti格式,导入即可实现“共享”试卷库了,
  • 【n8n学习笔记】本地安装n8n并实现完美汉化
  • 你还在用ChatGLM做自动推理?:Open-AutoGLM的三大革命性突破揭晓
  • pikacu暴力破解第二关验证码绕过(on server)
  • 2025诚信AI拓客品牌企业TOP5权威推荐:信誉好的AI拓客公司深度测评 - 工业品牌热点
  • java基于互联网+的个人健康管理系统设计
  • 语音唤醒准确率提升80%?Open-AutoGLM+ASR融合方案全解析
  • 集成RabbitMQ+MQ常用操作 - 实践
  • 网安如何防御DDoS攻击?
  • 智谱清言AutoGLM黑科技揭秘:如何实现低代码大模型训练?
  • 基于微信小程序的快递代领系统的设计与实现开题报告
  • ssm基于Vue.js的在线购物系统的设计与实现
  • Ubuntu22.04 外接显示屏显示异常
  • 基于微信小程序的快递代领系统的设计与实现任务书
  • 基于微信小程序的快递代领系统的设计与实现外文