Yii2的RateLimiter怎么自定义_修改限制规则和存储【方法】

千辰大大_1863

千辰大大_1863

2026-03-26

481人浏览

原创

ratelimiter 的限制规则在用户模型的 getratelimit() 和 loadallowance() 方法中定义,前者返回 [最大请求数, 时间窗口秒数],后者返回 [剩余配额, 上次更新时间戳]。

yii2的ratelimiter怎么自定义_修改限制规则和存储【方法】

RateLimiter 的限制规则在哪定义?

Yii2 的限流逻辑不靠配置文件或全局开关驱动,而是由用户模型(User)实现的两个方法决定:getRateLimit() 和 loadAllowance()。只要这个类实现了 RateLimitInterface,框架就会在请求进入时自动调用它们。

  • getRateLimit($request, $action) 返回数组 [最大请求数, 时间窗口秒数],比如 [10, 60] 表示“每分钟最多 10 次”
  • loadAllowance($request, $action) 返回当前剩余配额和上次检查时间戳,即 [$this->allowance, $this->allowance_updated_at]

常见错误:只改了 getRateLimit() 却没同步更新数据库字段或缓存逻辑,导致限流始终按旧值跑;或者返回了 null 或非整数,触发静默跳过限流(日志里只写 Rate limit skipped: user not logged in)

未登录用户怎么加限流?不能直接用 RateLimiter 过滤器

默认情况下,RateLimiter 过滤器依赖已登录用户对象,如果 Yii::$app->user->identity 是 null,它会直接跳过限流,不会报错,也不会限流——这是最容易被忽略的坑。

要支持未登录用户(如公开 API、注册页、登录页),必须绕开原生过滤器,手动实现:

  • 基于 IP 限流:用 $request->getUserIP() 当作 key,存到 Redis(推荐)或文件缓存
  • 全局限流:所有请求共用一个计数器,适合防御爬虫或突发流量
  • 自定义行为类:继承 yii\filters\RateLimiter 并重写 isRateLimited(),把用户判空逻辑替换成 IP 提取逻辑

注意:别在控制器里手写 if (++$count > 100) throw new TooManyRequestsHttpException() —— 缺少时间窗口滑动、配额恢复等关键逻辑,容易被绕过。

存储从数据库切到 Redis 怎么做?

原生限流默认读写用户表的 allowance 和 allowance_updated_at 字段,高并发下易成瓶颈。换成 Redis 只需两步:

Yii Framework 2.0.51
Yii Framework 2.0.51

Yii Framework 2.0.51 官方 Basic 应用模板,适合旧项目兼容、升级验证和开发测试。

下载
  • 在 User::loadAllowance() 中,用 IP 或用户 ID 为 key,从 Redis 读取 JSON:Yii::$app->cache->get("rate<em>limit</em>{$key}")
  • 在 User::saveAllowance() 中,把新值存回:Yii::$app->cache->set("rate<em>limit</em>{$key}", [$allowance, $timestamp], 3600)

关键细节:

  • Yii::$app->cache 必须配置为 Redis 缓存组件(不是 file cache)
  • key 要区分登录/未登录场景,比如登录用户用 "rate_limit<em>user</em>{$this->id}",未登录用 "rate_limit<em>ip</em>{$request->getUserIP()}"
  • 别漏掉 saveAllowance() 的调用时机——它只在配额被消耗后才触发,不是每次请求都执行

为什么 X-RateLimit-Reset 头总是不准?

这个响应头的值由 RateLimiter::calculateWaitSeconds() 计算,本质是“当前时间窗口结束还剩几秒”。但它基于服务器本地时间,且不校准客户端时钟或网络延迟。

典型问题:

  • 服务部署在多个时区服务器上,时间不同步 → 头部值混乱
  • 时间窗口设为 60 秒,但用户在第 59 秒发起请求,头部却显示 1,实际可能因处理延迟已跨窗
  • Redis 存储的时间戳用了 time(),而计算 wait 时用了 microtime(true),精度不一致

解决办法:统一用 time()(秒级)做所有时间运算;上线前用 date -s 校准所有服务器时间;不要依赖该 header 做前端倒计时,仅作服务端参考。

改限流规则不是改个数字就完事,真正卡住人的永远是存储一致性、未登录路径的兜底逻辑,还有那个看起来很准、其实常飘的 X-RateLimit-Reset。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

yii

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

2023.08.07

2135

5

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.23

3282

1

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

2023.10.13

1096

3

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

2025.09.10

3759

7

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

2023.09.22

549

3

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

2024.03.01

1678

6

counta和count的区别
counta和count的区别

Count函数用于计算指定范围内数字的个数,而CountA函数用于计算指定范围内非空单元格的个数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.11.20

3188

5

常用的数据库软件
常用的数据库软件

常用的数据库软件有MySQL、Oracle、SQL Server、PostgreSQL、MongoDB、Redis、Cassandra、Hadoop、Spark和Amazon DynamoDB。更多关于数据库软件的内容详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.02

4549

19

内存数据库有哪些
内存数据库有哪些

内存数据库有Redis、Memcached、Apache Ignite、VoltDB、TimesTen、H2 Database、Aerospike、Oracle TimesTen In-Memory Database、SAP HANA和ache Cassandra。更多关于内存数据库相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.14

4095

11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Yii Framework 2.0 API 官方文档
Yii Framework 2.0 API 官方文档

共0课时 | 0人学习

Yii2.0框架开发实战视频教程
Yii2.0框架开发实战视频教程

共22课时 | 9.3万人学习