基于thinkphp5.2 实现对ip-api限流:Redis-Cell漏桶算法

5 篇文章 0 订阅
1 篇文章 0 订阅

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

 

漏桶(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);
    }

}

转载自http://heroflower.top/index.php/archives/33/ 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是ThinkPHP6实现Redis连接池以及Redis队列的详细代码实现。 首先,在ThinkPHP6中使用Redis需要安装`topthink/think-redis`扩展,可以通过以下命令进行安装: ``` composer require topthink/think-redis ``` 接下来,我们需要在项目的配置文件中配置Redis连接信息,可以在`config/database.php`文件中添加以下代码: ```php 'redis' => [ 'type' => 'redis', 'hostname' => '127.0.0.1', 'password' => '', 'port' => 6379, 'select' => 0, 'timeout' => 0, 'prefix' => '', 'persistent' => true, 'pool' => [ 'min_connections' => 1, 'max_connections' => 10, 'wait_timeout' => 3, 'max_idle_time' => 60, ], ], ``` 配置项说明: - `type`:数据库类型,这里填写`redis`。 - `hostname`:Redis主机地址。 - `password`:Redis密码,如果没有设置密码可以不填写。 - `port`:Redis端口号,默认为6379。 - `select`:选择的数据库,默认为0。 - `timeout`:连接Redis的超时时间,默认为0表示不限制。 - `prefix`:设置的键名前缀,默认为空。 - `persistent`:是否使用持久化连接,默认为true。 - `pool`:配置连接池信息,包括最小连接数、最大连接数、等待超时时间和最大空闲时间。 接下来,我们可以通过以下代码获取Redis连接并进行操作: ```php use think\facade\Cache; // 获取Redis连接 $redis = Cache::store('redis')->handler(); // 设置键值对 $redis->set('name', 'Tom'); // 获取键值对 $name = $redis->get('name'); echo $name; ``` 以上代码中,我们使用了ThinkPHP6的缓存门面`think\facade\Cache`来获取Redis连接,通过`store`方法指定使用`redis`缓存驱动,再通过`handler`方法获取Redis连接。 接下来,我们来实现Redis队列功能,具体的代码如下: ```php use think\queue\Job; use think\facade\Cache; // 定义任务处理类 class TestJob { public function fire(Job $job, $data) { // 获取Redis连接 $redis = Cache::store('redis')->handler(); // 从队列中取出任务数据 $name = $data['name']; // 进行任务处理 // ... // 任务处理完成后删除任务 $job->delete(); } } // 将任务加入队列 $jobHandlerClassName = 'TestJob'; // 任务处理类名 $jobData = ['name' => 'Tom']; // 任务数据 $queueName = 'test_queue'; // 队列名称 $delay = 0; // 延迟时间,默认为0 \think\Queue::later($delay, $jobHandlerClassName, $jobData, $queueName); ``` 以上代码中,我们首先定义了一个任务处理类`TestJob`,它实现了`fire`方法来处理任务。在`fire`方法中,我们首先获取Redis连接,然后从队列中取出任务数据,进行任务处理,并最终删除任务。 接下来,我们将任务加入队列。在代码中,我们使用了`think\Queue`门面的`later`方法来将任务加入队列,指定了任务处理类名、任务数据、队列名称和延迟时间(默认为0表示不延迟)。 以上就是ThinkPHP6实现Redis连接池和Redis队列的详细代码实现

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值