在中间件中实现接口限流
主要实现两个功能
- 单位时间内,限制所有用户的访问次数
- 单位时间内,限制一个用户[ip]的访问次数
// 已Laravel框架为例
namespace App\Http\Middleware;
use Closure,redis;
use Illuminate\Http\Request;
use Illuminate\Http\Response as SymfonyResponse;
use Illuminate\Support\Facades\Response;
/**
* 流量限制器
* 实现两个功能
* 1. 单位时间内,限制所有用户的访问次数
* 2. 单位时间内,限制一个用户[ip]的访问次数
*/
class LimitFlowMiddleware
{
private $oneITime = 60; // 单位时间 一分钟
private $oneIMax = 50; // 一个用户Ip一分钟最多仅允许访问访问10次
private $platITime = 60; // 针对所有用户,单位时间内允许访问的最大次数
private $platIMax = 10; // 针对所有的用户,该接口最多仅允许访问N次
public function handle(Request $request, Closure $next)
{
$redis = new redis();
$userid = 12;
$redis->connect("127.0.0.1");
$redis->auth("");
$redis->select(0);
//.... 针对平台全局锁,用于限制单位时间内所有用户访问的次数
$platKey = md5($request->path());
$platFlowCount = $redis->get($platKey);// 平台访问次数
if($platFlowCount){
if($platFlowCount >= $this->platIMax){
return Response::json("平台超过限制",SymfonyResponse::HTTP_LOCKED,[],256);
}
}
$redis->incr($platKey);// ++1 次访问次数
!$platFlowCount && $redis->expire($platKey,$this->platITime); // 设置锁的有效时间
// ... 针对单个用户实现的访问锁
$key = md5($request->getClientIp().":".$userid);
// 实现一个用户一分钟最多允许访问10次
$userFlowCount = $redis->get($key); // 单个用户访问次数
if($userFlowCount){
if($userFlowCount >= $this->oneIMax){
return Response::json("用户访问超过限制",SymfonyResponse::HTTP_LOCKED,[],256);
}
}
$redis->incr($key);// ++1 次访问次数
!$userFlowCount && $redis->expire($key,$this->oneITime);// 设置锁的有效时间
return $next($request);
}
}
网友评论