注册 登陆

    2020-12-22 20:20:29php接口限流总结

    您现在的位置是: 首页 >  php >  php接口限流总结

        限流算法在分布式领域是一个经常被提到的话题,当系统的处理能力有限时,如何阻止计划外的请求继续对系统试压,这是一个需要重视的问题。除了流量控制,限流还有一个应用目的是控制用户行为,避免垃圾请求。比如UGC社区、回复、点赞等行为都要严格受控,一般要严格限定某行为在规定内被允许的次数,超过了次数就是非法行为。对非法行为,业务必须适当的惩处策略。

        首先我们来看一个常见的、简单的限流策略。系统限定用户的某个行为在限定时间内只能允许发生N次,如何来实现这个限流功能?
    1.) 写入cookie,通过cookie值来判断,当然用户可以通过客户端来修改,不严谨
    2.) 写入session
    几种redis实现的限流,也是今天的重点:

    3.) redis-计数器

    说明:在一段时间间隔内,处理请求的数量固定的,超的就不做处理。 比如每分钟限制操作10,如果在每分钟的59s来操作接口,那限制在第十分钟的时候才生效,因为每次操作设置存活时间会重置存活时间。可以用于预防别人刷接口。如果想再过去一段时间内限制多少次,可以看4.)

    public function SpeedCounter()
    {
    $redis = ZFactory::getRedis('public');

    // 最大请求数量
    $maxCount = 10;

    $redis_key = 'zcont';

    // 每分钟内,一个用户只能访问10次
    $interval = 60;
    // 请求总数量
    $zcount = $redis->get($redis_key);

    // 判断是否超过最大值
    if ($zcount <= $maxCount) {
    //业务处理

    $redis->incr($redis_key);
    $redis->Expire($redis_key, $interval);

    } else {
    // 记录错误日志

    // 返回错误提示
    }
    }

    4.) 时间窗口算法
        通过redis的zSet属性做滑动窗口,可以将请求打造成一个zset数组,当每一次请求进来的时候,value保持唯一,可以用UUID生成,value相同则是更新score,而score可以用当前时间戳表示,因为score我们可以用来计算当前时间戳之内有多少的请求数量。而zset数据结构也提供了range方法让我们可以很轻易的获取到2个时间戳内有多少请求


    其中每一小个表示 10s,被红色虚线包围的时间段则为需要判断的时间间隔,比如 60s 秒允许 100 次请求,那么红色虚线部分则为 60s 。

    tp5 Demo 

    public function getShortLink()
    {
    $key = 'key';

    $binding_time = 60 * 10;
    // 十分钟内十次请求
    $end_time = time();
    $start_time = $end_time - $binding_time;
    // redis句柄
    $header = Cache::init()->handler();
    // 获取一段时间内的请求数
    $array_num = $header->zRangebyscore($key, $start_time, $end_time);
    // 删除时间范围外的缓存,减少内存暂用
    $header->zremrangeByScore($key, 1, $start_time - 1);
    if (count($array_num) >= 10) {
    // 记录错误日志
    // 返回错误提示
    }

    // 业务处理

    // 增加一次操作记录
    $header->zAdd($key, time(), create_uuid()); # value不重要,需要保持唯一,用uuid
    }

    5.) 漏桶算法


    说明:漏斗算法是最常见的限流方法之一。如果将漏嘴堵住,然后一直灌水,它就会变满,直至再也装不下了。 如果将漏嘴放开,水就会往下流,流走一部分,就又可以继续往里面灌水。如果漏嘴灌水的速度大于灌水的速度,那么漏斗永远装不满。 反之漏斗水满了,灌水就要暂停,并等待一段时间。
        redis 4.0提供了一个限流redis模块,它叫Redis-Cell。该模块也是用漏斗算法,并提供了原子的限流命令。该模块只有一个命令,cl.throttle
    6.)令牌算法


        在令牌桶算法中有一个程序以某种恒定的速度生成令牌,并存入令牌桶中,而每个请求需要先获取令牌才能执行,如果没有获取到令牌的请求可以选择等待或者放弃执行。

        Google 开源的 guava 包,提供思路,可以百度了解

关键字词: php接口限流总结

0
Name::

Email:


留言内容: