跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

ThinkPHP如何做API请求频率统计_ThinkPHP限流数据可视化详解【详解】

要准确统计请求频次,需在中间件中主动用Cache::inc()递增计数并设60秒TTL,标准化route(去query、统一大写),导出数据时单点查询避免KEYS阻塞,返回前强制(int)转换count字段确保ECharts正确渲染。 ThinkPHP 6 的
throttle
中间件怎么用才不漏统计? 默认的
throttle
中间件只做拦截,不记录原始请求频次——你看到“429 Too Many Requests”,但查不到用户过去1分钟到底发了多少次。要统计,得自己接管计数逻辑。 推荐在中间件里手动调用缓存递增,而不是依赖
throttle
的内置判断: 用
Cache::inc('api:rate:'.$ip.':'.$route, 1)
主动累加,比读-改-写更原子 配合
Cache::set($key, 0, 60)
初始化(仅首次),避免空值导致递增失败 注意
$route
要标准化:去掉 query 参数、统一大小写,否则
/user?id=1
和
/user?id=2
会被算作不同接口 如何把限流数据导出成 JSON 供 ECharts 渲染? 别直接查 Redis keys——
KEYS api:rate:*
在生产环境会阻塞主线程。应该用前缀扫描 + 分页拉取: 用
Cache::get('api:rate:'.$ip.':'.$route)
单点查,配合前端传来的
ip
和
route
查询条件 后台接口返回结构示例:
{"data":[{"ip":"192.168.1.100","route":"/api/v1/order","count":17,"expire":53}]}
前端用
setInterval
每30秒轮询一次,避免 WebSocket 增加部署复杂度 Redis 缓存键设计不当会导致统计错乱? 常见错误是把时间窗口硬编码进 key,比如
api:rate:20240520:192.168.1.100
——这会让每小时/每天生成新 key,无法滚动统计最近60秒。 PHP 8.5.5 PHP 8.5.5 是 PHP 8.5 分支的维护更新版本。该版本延续了“小步快跑”的迭代逻辑,通过深度错误修复、底层性能微调以及安全加固,旨在为开发者提供一个更健壮、更高效的运行环境。该版本严格遵守语义化版本规范,不包含破坏性变更。 下载 立即学习 “ PHP免费学习笔记(深入) ”; 正确做法:key 不含时间戳,靠缓存 TTL 控制生命周期,例如
Cache::set($key, $count, 60)
如果需要多维度(如按用户ID+IP+接口),用冒号拼接但保持层级清晰:
api:rate:user_123:192.168.1.100:/order
特别注意:Redis 的
INCR
对不存在的 key 默认设为 1,所以首次调用
Cache::inc()
就能自动初始化,无需先
set(0)
为什么 ECharts 折线图总显示“无数据”? 大概率是后端返回的
count
字段是字符串类型(Redis 返回的都是 string),而 ECharts 的
series.data
要求数值数组。 前端必须显式转换:
data: res.data.map(d => Number(d.count))
后端接口建议统一 cast:
'count' => (int) $value
,避免 PHP 自动类型转换在某些版本下行为不一致 测试时用
curl -v http://your.app/api/rate?ip=192.168.1.100
直接看原始响应,比在浏览器里调试更快 真正难的不是画图,而是确保每一行数据都来自同一时间粒度、同一聚合口径。比如你用 60 秒 TTL,但前端每 10 秒拉一次,又没做服务端去重,图表就会抖动。这种细节,文档里通常不提。

相关文章