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 ...
随机推荐
- 升级Xcode 10 后报错问题记录([CP] Copy Pods Resources)
1.升级Xcode到Version 10.0 (10A255)后,运行已有项目,报如下错误: error: Multiple commands produce '/Users/galahad/Libr ...
- IntelliJ 10.0.1设置系统的JDK
IntelliJ 10.0.1设置JDK: File-->Project Structure: project SDK--New a jsdk.
- TeamWork#3,Week5,Performance Test of Crawlers
爬虫总体性能不错,能完成基本的网络数据爬取,没有功能上的缺陷.下图为饿了么网站商户信息爬取结果及原网站信息. 大部分信息是正确的,但也有一些错误.比如下图,小渝馆家常菜和渝码头川菜位置爬取错了. 再比 ...
- Scrum Meeting 10.24
成员 已完成任务 下一阶段任务 用时 徐越 阅读后端代码,了解服务器的概念,以及服务器和终端间的通信机制 学习服务器配置 4h 赵庶宏 阅读后端代码,了解服务器的概念,以及服务器和终端间的通信机制 阅 ...
- 第二阶段Sprint冲刺会议1
进展:总结第一阶段冲刺成就,讨论第二阶段任务,要实现的主要功能,分工及任务认领.
- IT职业道路的苦与甜
每当有人问起你学的是什么专业啊?学的怎么样啊?好不好学啊?等等一些类似的问题.我都会默默的说一句,会者不难,难者不会.当然现在的我还处于菜鸟级别,不过我相信在不久后的一天我一定会脱离菜鸟的行列,然后挺 ...
- Beta 冲刺 (6/7)
队名:Boy Next Door 燃尽图 代码写入 https://github.com/mangoqiqi/paybook/tree/master/Desktop/Web%E8%B4%A6%E5%8 ...
- Python库moviepy
目录 介绍和下载安装 视频截取和拼接 视频加水印
- 车牌识别算法库EasyPR的使用
主要参考以下两个博客: http://blog.csdn.net/junmuzi/article/details/49888123 http://blog.csdn.net/Lucas66666/ar ...
- Tuscany glossary of terms
SOA(service-oriented architecture) 面向服务的架构 解决问题:面向服务.多语言.多种数据格式.多协议 SCA(Service Component Architectu ...