使用Redis-Cell漏桶算法,实现api限流

     分类:     有: 0 条评论

漏桶(Leaky Bucket)算法思路

水(请求)先进入到漏桶里,漏桶以一定的速度出水(接口有响应速率),当水流入速度过大会直接溢出(访问频率超过接口响应速率),然后就拒绝请求,可以看出漏桶算法能强行限制数据的传输速率.示意图如下:

安装Redis-Cell

1.下载安装包 https://github.com/brandur/redis-cell/releases
2.找到redis的目录,新建一个文件夹extend
3.解压刚下载的文件;把libredis_cell.d和libredis_cell.so 复制到extend目录
4.给extend目录添加权限

sudo chmod 755 ./extend

5.修改redis配置文件

vim redis.conf

//增加一行配置来挂载redis-cell扩展
loadmodule /www/server/redis/extend/libredis_cell.so(扩展的路径,不同的环境路径不同)

6.打开redis-cli

//输入

CL.THROTTLE test 100 400 60 3

//执行成功则代表安装成功

cl.throttle 命令

Redis-Cell只提供一个命令

cl.throttle test 90 30 60 1

参数说明

1.test:key
2.初始化桶容量
3.30 漏斗的速率 60秒能漏出30个
4.60 时间
5.1 每次漏出数量

返回值说明

1.(integer) 0 #0表示允许,1表示拒绝
2.(integer) 16
3.(integer) 15 #漏斗容量
4.(integer) -1 #-1表示正常能放入,0表示已满,正数表示几秒后可放入数据
5.(integer) 2 #几秒后漏斗数据完全漏完

基于thinkphp5.2 实现对ip-api限流

LeakyBucket实现类

<?php
/**
 * Created by PhpStorm.
 * User: kun
 * Date: 19-7-31
 * Time: 下午2:16
 */

namespace app\common\server;

/**
 * 基于redis-cell实现的一个漏桶操作类
 * Class LeakyBucket
 * @package 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 constructor.
     * @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->redis_connect = redis_connect(8);

        $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];
    }
}

LeakyBucket 中间件

<?php
/**
 * Created by PhpStorm.
 * User: kun
 * Date: 19-7-31
 * Time: 下午4:18
 */

namespace app\http\middleware;


use app\common\Traits\ApiResponse;

/**
 * ip限流中间件
 * Class LeakyBucket
 * @package app\http\middleware
 */
class LeakyBucket
{
    use ApiResponse;



    public function handle($request, \Closure $next)
    {

        $ip = $request->ip(0,false);

        $leakyBucketConfig = config('leaky_bucket.');

        $server = new \app\common\server\LeakyBucket($ip,$leakyBucketConfig['max_burst'],$leakyBucketConfig['tokens'],$leakyBucketConfig['seconds']);

        if ($server->isPass()){
            $this->notFond('操作频繁,请稍后再试');
        }

        return $next($request);
    }

}
(●゚ω゚●)