news 2026/7/4 12:34:33

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
wasm~tinygo写一个基于redis的全局限流的插件

基于白名单的全局限流插件,对指定的域名和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" }

配置参数

参数类型必填默认值说明
serviceNamestring-Redis服务名称
servicePortint-Redis端口
domainstring-Redis域名
usernamestring-Redis用户名
passwordstring-Redis密码
timeoutint-连接超时时间(ms)
hosts[]string-域名白名单
paths[]string-URL路径白名单(支持正则)
unitSecondint30统计周期(秒)
qpmint10周期内最大请求数
keystringglobal-limit-plugin-keyRedis 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 LimitRoute 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 then return 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
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/4 1:00:00

Redis 慢查询问题诊断方法

Redis作为高性能的内存数据库&#xff0c;广泛应用于缓存、消息队列等场景。当Redis出现慢查询时&#xff0c;可能导致服务响应延迟甚至超时&#xff0c;影响用户体验。本文将介绍几种实用的Redis慢查询问题诊断方法&#xff0c;帮助开发者快速定位和解决性能瓶颈。 慢查询日志…

作者头像 李华
网站建设 2026/7/4 4:16:15

Python 正则表达式性能分析

Python正则表达式性能分析&#xff1a;优化与实战指南 正则表达式是文本处理的利器&#xff0c;但在处理大规模数据时&#xff0c;性能问题常成为瓶颈。Python作为广泛使用的语言&#xff0c;其re模块虽功能强大&#xff0c;但不同写法可能导致效率差异显著。本文将从实际场景…

作者头像 李华
网站建设 2026/7/4 1:26:12

Week6:深度神经网络训练技巧与Keras进阶实战专题

摘要本周继续学习李宏毅《机器学习》课程&#xff0c;主要学习深度网络的训练调优方法与深度学习框架进阶实战。课程系统介绍了神经网络训练中常见的欠拟合、过拟合问题&#xff0c;讲解了正则化、参数初始化、学习率调整、早停等常用优化策略。同时结合 Keras 与 TensorFlow 完…

作者头像 李华
网站建设 2026/7/4 1:33:13

高效Python代码的五个实用技巧

昨天&#xff0c;朋友满脸沮丧地找到我&#xff1a;他写了一个数据处理脚本&#xff0c;跑了两小时还没跑完。我扫了一眼代码&#xff0c;发现他用三层for循环逐行读取了十万行CSV&#xff0c;每个单元格还去调了一次正则匹配。改了几行之后&#xff0c;原本两小时的脚本压缩到…

作者头像 李华
网站建设 2026/7/4 6:17:30

高效解决文档访问难题:Google Drive PDF下载器完全指南

高效解决文档访问难题&#xff1a;Google Drive PDF下载器完全指南 【免费下载链接】Google-Drive-PDF-Downloader 项目地址: https://gitcode.com/gh_mirrors/go/Google-Drive-PDF-Downloader 还在为Google Drive中"仅查看"权限的PDF文件而烦恼吗&#xff1…

作者头像 李华