thinkphp5 + redis 实现接口高并发限流
程序员文章站
2022-03-23 18:59:50
thinkphp5实现接口高并发限流基于redis实现接口限流,主要使用Redis的一个模块:Redis-Cellredis-cell如何使用,请你参考上一篇文章,传送门:https://blog.csdn.net/liuxl57805678/article/details/108824411话不多述直接上代码:先看下我项目目录:LeakyBucket实现类
基于redis实现接口限流,主要使用Redis的一个模块:Redis-Cell
redis-cell如何使用,请你参考上一篇文章,传送门:https://blog.csdn.net/liuxl57805678/article/details/108824411
话不多述直接上代码:
先看下我项目目录:
LeakyBucket实现类
<?php
namespace app\common\server;
class LeakyBucket
{
protected $key = null;
protected $max_burst = null;
protected $tokens = null;
protected $seconds = null;
protected $apply = 1;
protected $redis_connect;
/**
* LeakyBucket construct
* @param $key string
* @param $max_burst int 初始桶数量
* @param $tokens int 速率
* @param $seconds int 时间
* @param int $apply 每次漏水数量
*/
public function __construct($key, $max_burst, $tokens, $seconds, $apply = 1)
{
$this->initRedis();
$this->key = $key;
$this->max_burst = $max_burst;
$this->tokens = $tokens;
$this->seconds = $seconds;
$this->apply = $apply;
}
/**
* 是否放行
* @return int 0 or 1 0:放行 1:拒绝
*/
public function isPass()
{
$rs = $this->redis_connect->rawCommand('CL.THROTTLE', $this->key, $this->max_burst, $this->tokens, $this->seconds, $this->apply);
return $rs[0];
}
//初始化redis
public function initRedis($conf = [])
{
if (empty($conf)) {
if (!empty(config('redis.'))) {
$conf = config('redis.');
}
}
$this->redis_connect = $this->init($conf);
}
protected function init($redisCfg)
{
if (extension_loaded('redis')) {
if (empty($redisCfg)) {
return '请配置redis信息!';
}
return $this->setupServer($redisCfg);
} else {
exit('缺少redis扩展!');
}
}
public function setupServer($config)
{
$this->redis_connect = new \Redis();
if ($config['socket_type'] === 'unix') {
$success = $this->redis_connect->connect($config['socket']);
} else {
$success = $this->redis_connect->connect($config['host'], $config['port'], $config['timeout']);
}
if (!$success) {
return false;
} else {
if (isset($config['password'])) {
$this->redis_connect->auth($config['password']);
}
if (isset($config['db']) && !empty($config['db'])) {
$this->redis_connect->select(intval($config['db']));
}
}
return $this->redis_connect;
}
}
中间件
<?php
namespace app\http\middleware;
use app\common\server\LeakyBucket;
use think\Request;
class CheckParam
{
public function handle(Request $request, \Closure $next)
{
$ip = $request->ip(0, 1);
$leakyBucketConfig = config('leaky_bucket.');
$server = new LeakyBucket($ip, $leakyBucketConfig['max_burst'], $leakyBucketConfig['tokens'], $leakyBucketConfig['seconds']);
if ($server->isPass()){
$res['code'] = 1001;
$res['msg'] = '操作频繁,请稍后再试';
return json($res);
}
return $next($request);
}
}
}
中间件配置 config 目录下找到:middleware.php
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// +----------------------------------------------------------------------
// | 中间件配置
// +----------------------------------------------------------------------
return [
// 默认中间件命名空间
'check' => app\http\middleware\CheckParam::class
];
调用中间件:(后面所有的控制器集成Common即可)其他调用中间件方式,请参考官方手册。
<?php
namespace app\index\controller;
use think\Controller;
class Common extends Controller
{
protected $middleware = ['check'];
}
相关配置文件:配置文件放在config目录下
leaky_bucket.php
<?php
// +----------------------------------------------------------------------
// | LeakyBucket设置
// +----------------------------------------------------------------------
return [
'max_burst' => 60, //初始化桶容量
'tokens' => 20, //漏斗的速率
'seconds' => 60, //时间
];
redis.php
<?php
// +----------------------------------------------------------------------
// | Redis设置
// +----------------------------------------------------------------------
return [
'socket_type' => 'tcp',
'host' => '127.0.0.1',
'port' => '6379',
'timeout' => 10,
'password' => '',
'db' => 0
];
喜欢的朋友记得点赞收藏哦。
本文地址:https://blog.csdn.net/liuxl57805678/article/details/108849044