thinkphp5 + redis 实现接口高并发限流

基于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 <[email protected]>
// +----------------------------------------------------------------------

// +----------------------------------------------------------------------
// | 中间件配置
// +----------------------------------------------------------------------
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
];

喜欢的朋友记得点赞收藏哦。

猜你喜欢

转载自blog.csdn.net/liuxl57805678/article/details/108849044