Laravel 限流中间件 throttle 简析
1. 在Laravel 中配置
在 app\Http\Kernel.php 中,默认添加到中间件组 api 下,1分钟60次。

2. 限流原理
- 获取唯一请求来源,进行唯一标识(key)
- 获取该请求请求次数 (hits)
- 判断是否超过最大限制
- 若达到上限,进入5。未达到,则进入6
- 丢出访问次数限制异常,结束请求。
- 首先判断hits 是否达到限制,若未达到,进入7。若达到,进入8。
- hits 进行计数 + 1,更新到缓存中。 若是第一次,则需要 hits = 1(次数), 并添加访问标识 key (1分钟)到缓存中,以标记请求周期。
- 请求次数已达到上限(hits >= 60),此时需要判断是否在周期范围内(1分钟),若在周期内,进入9;不在周期内,进入10.
- 此时请求处在 “1分钟内请求次数达到60次”,即达到限制,返回 false 。
- 此时请求处在 “不在1分钟内请求次数达到60次”,即不在周期内,需要重新计算周期。
3. 代码实现
3.1 业务逻辑在 ThrottleRequests -> handle 中实现。

public function handle($request, Closure $next, $maxAttempts = 60, $decayMinutes = 1)
{
// 获取唯一请求来源 2.1
$key = $this->resolveRequestSignature($request);
// 获取实际请求次数 2.2
$maxAttempts = $this->resolveMaxAttempts($request, $maxAttempts);
// 判断是否达到上限 2.3
if ($this->limiter->tooManyAttempts($key, $maxAttempts)) {
// 禁止请求 2.5
throw $this->buildException($key, $maxAttempts);
}
// 2.7 计数
$this->limiter->hit($key, $decayMinutes); $response = $next($request); return $this->addHeaders(
$response, $maxAttempts,
$this->calculateRemainingAttempts($key, $maxAttempts)
);
}
3.2 限流方法 在 Illuminate\Cache\RateLimiter 中
<?php namespace Illuminate\Cache; use Illuminate\Support\InteractsWithTime;
use Illuminate\Contracts\Cache\Repository as Cache; class RateLimiter
{
use InteractsWithTime; /**
* The cache store implementation.
*
* @var \Illuminate\Contracts\Cache\Repository
*/
protected $cache; /**
* Create a new rate limiter instance.
*
* @param \Illuminate\Contracts\Cache\Repository $cache
* @return void
*/ // 初始化缓存
public function __construct(Cache $cache)
{
$this->cache = $cache;
} /**
* Determine if the given key has been "accessed" too many times.
*
* @param string $key
* @param int $maxAttempts
* @return bool
*/ // 判断是否达到上限
public function tooManyAttempts($key, $maxAttempts)
{
// 判断次数,是否达到限制(60次)
if ($this->attempts($key) >= $maxAttempts) {
// 判断是否在限制周期内(1分钟内)
if ($this->cache->has($key.':timer')) {
return true;
}
// 2.10 重新计算周期
$this->resetAttempts($key);
} return false;
} /**
* Increment the counter for a given key for a given decay time.
*
* @param string $key
* @param float|int $decayMinutes
* @return int
*/
public function hit($key, $decayMinutes = 1)
{
// 对应2.7 ,添加周期缓存
$this->cache->add(
$key.':timer', $this->availableAt($decayMinutes * 60), $decayMinutes
);
// 对应2.7 ,添加请求次数缓存
$added = $this->cache->add($key, 0, $decayMinutes);
// 请求次数 + 1
$hits = (int) $this->cache->increment($key);
// 更新次数
if (! $added && $hits == 1) {
$this->cache->put($key, 1, $decayMinutes);
}
// 返回次数
return $hits;
} /**
* Get the number of attempts for the given key.
*
* @param string $key
* @return mixed
*/ // 获取请求次数,默认0
public function attempts($key)
{
return $this->cache->get($key, 0);
} /**
* Reset the number of attempts for the given key.
*
* @param string $key
* @return mixed
*/ // 重置请求周期
public function resetAttempts($key)
{
return $this->cache->forget($key);
} /**
* Get the number of retries left for the given key.
*
* @param string $key
* @param int $maxAttempts
* @return int
*/ // 获取剩余次数
public function retriesLeft($key, $maxAttempts)
{
$attempts = $this->attempts($key); return $maxAttempts - $attempts;
} /**
* Clear the hits and lockout timer for the given key.
*
* @param string $key
* @return void
*/ // 清除请求计数和周期
public function clear($key)
{
$this->resetAttempts($key); $this->cache->forget($key.':timer');
} /**
* Get the number of seconds until the "key" is accessible again.
*
* @param string $key
* @return int
*/ // 判断是否在周期内
public function availableIn($key)
{
return $this->cache->get($key.':timer') - $this->currentTime();
}
}
PS: ThrottleRequestsWithRedis 和 ThrottleRequests 是相同的,区别在于前者指定 Redis 作为缓存,后者无限制(使用Laravel配置缓存)
Laravel 限流中间件 throttle 简析的更多相关文章
- Asp.Net Core 7 preview 4 重磅新特性--限流中间件
前言 限流是应对流量暴增或某些用户恶意攻击等场景的重要手段之一,然而微软官方从未支持这一重要特性,AspNetCoreRateLimit这一第三方库限流库一般作为首选使用,然而其配置参数过于繁多,对使 ...
- 从-99打造Sentinel高可用集群限流中间件
接上篇Sentinel集群限流探索,上次简单提到了集群限流的原理,然后用官方给的 demo 简单修改了一下,可以正常运行生效. 这一次需要更进一步,基于 Sentinel 实现内嵌式集群限流的高可用方 ...
- ASP.NET Core WebApi AspNetCoreRateLimit 限流中间件学习
AspNetCoreRateLimit介绍: AspNetCoreRateLimit是ASP.NET核心速率限制框架,能够对WebApi,Mvc中控制限流,AspNetCoreRateLimit包包含 ...
- AspNetCore 限流中间件IpRateLimitMiddleware 介绍
IpRateLimitMiddleware(Github: AspNetCoreRateLimit) 是ASPNETCore的一个限流的中间件,用于控制客户端调用API的频次, 如果客户端频繁访问服务 ...
- .NET服务治理之限流中间件-FireflySoft.RateLimit
概述 FireflySoft.RateLimit自2021年1月发布第一个版本以来,经历了多次升级迭代,目前已经十分稳定,被很多开发者应用到了生产系统中,最新发布的版本是3.0.0. Github:h ...
- 【.NET Core项目实战-统一认证平台】第七章 网关篇-自定义客户端限流
[.NET Core项目实战-统一认证平台]开篇及目录索引 上篇文章我介绍了如何在网关上增加自定义客户端授权功能,从设计到编码实现,一步一步详细讲解,相信大家也掌握了自定义中间件的开发技巧了,本篇我们 ...
- 漏桶、令牌桶限流的Go语言实现
限流 限流又称为流量控制(流控),通常是指限制到达系统的并发请求数. 我们生活中也会经常遇到限流的场景,比如:某景区限制每日进入景区的游客数量为8万人:沙河地铁站早高峰通过站外排队逐一放行的方式限制同 ...
- AspNetCore添加API限流
最近发现有客户在大量的请求我们的接口,出于性能考虑遂添加了请求频率限制. 由于我们接口请求的是.Net Core写的API网关,所以可以直接添加一个中间件,中间件中使用请求的地址当key,通过配置中心 ...
- 【Dnc.Api.Throttle】适用于.Net Core WebApi接口限流框架
Dnc.Api.Throttle 适用于Dot Net Core的WebApi接口限流框架 使用Dnc.Api.Throttle可以使您轻松实现WebApi接口的限流管理.Dnc.Api.Thr ...
随机推荐
- 自定义UIView怎么注册销毁NSNotification通知
问题描述:在使用天猫tangram框架后.部分组件自定义后会用到通知,但是在iOS 8 系统中,会崩溃? 原因分析:当对象挂掉后,要对应移除注册的通知. 否则当你重复执行发送通知的时候,在iOS8 系 ...
- Bing词典vs有道词典比对测试报告——功能篇之辅助功能,差异化功能及软件的效能
1.辅助功能: 和有道相比,必应的词典加入了换肤功能,用户可以选择喜欢的颜色,而且必应的皮肤也比较多,这一点设计给必应增色不少. 相对而言,有道则加入了调节客户端字体的大小,如下,也比较人性化 2.差 ...
- fcn模型训练及测试
1.模型下载 1)下载新版caffe: https://github.com/BVLC/caffe 2)下载fcn代码: https://github.com/shelhamer/fcn.berkel ...
- Codeforces Round #157 (Div. 1) B. Little Elephant and Elections 数位dp+搜索
题目链接: http://codeforces.com/problemset/problem/258/B B. Little Elephant and Elections time limit per ...
- python learning2.py
L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack'] # 取前3个元素的笨方法 r = [] n = 3 for i in range(n): r.appe ...
- Maya学习笔记
软件: Maya 2016 : 参考教材: Maya 2016 中文版标准教程 ; 改变视图颜色 [窗口]|[设置/首项选择]|[颜色设置]|[3D视图]: 观察视图 旋转视图 Alt + 鼠标左键 ...
- diliucizuoye
NABCD N(Need 需求) 互联网的高速发展,造就了二十一世纪这个追求高品质.高体验的信息时代,随其发展改变的是信息记录与分享方式,从传统的面对面交流.手机通话.写日记本,到现如今的社交平台.信 ...
- Swift-KVC构造函数中数据类型和私有属性
- Profibus基础知识学习——报文
转自:http://bbs.ednchina.com/BLOG_ARTICLE_3031246.HTM Profibus DP通讯协议简单介绍 一. 首先,Profibus DP通讯协议是一种单一的. ...
- Redis有序集内部实现原理分析
Redis技术交流群481804090 Redis:https://github.com/zwjlpeng/Redis_Deep_Read Redis中支持的数据结构比Memcached要多的多啦,如 ...