php令牌桶算法實現接口限流

前端每次請求從令牌桶取走令牌,後端勻速向桶內投遞令牌,如果前端取到令牌,則說明這次請求有效,否則讓前端再次請求或者等待。避免了大量請求下服務器壓力過大導致的崩潰問題。

令牌桶類:

<?php

class Token
{
    private $_max;
    private $_queue;
    private $_redis;

    public function __construct()
    {
        try {
            $this->_redis = new \Redis();
            $this->_redis->connect('127.0.0.1', 6379);
            $this->_queue = 'token';
            $this->_max = 10;
        } catch (RedisException $exception) {
            throw new Exception($exception->__toString());
            return false;
        }

    }

    /**
     * 令牌初始化
     */
    public function reset()
    {
        $this->_redis->del($this->_queue);
        $this->add($this->_max);
    }

    /**
     * 添加令牌
     * @param int $number
     */
    public function add($number = 1)
    {
        $maxNumber = $this->_max;
        $currentNumber = $this->_redis->lLen($this->_queue);
        $number = $maxNumber >= ($currentNumber + $number) ? $number : ($maxNumber - $currentNumber);
        if ($number > 0) {
            $tokens = array_fill(0, $number, 1);
            foreach ($tokens as $token) {
                $this->_redis->lPush($this->_queue, $token);
            }
        }

    }

    /**
     * 獲取令牌
     */
    public function get()
    {
        return $this->_redis->rPop($this->_queue) ? true : false;
    }
}

消費類:模擬用戶請求

<?php

require 'token.php';

$token = new Token();

swoole_timer_tick(500, function () use ($token) {
    var_dump($token->get());
});

投遞類:後端向令牌桶投遞

<?php

require 'token.php';

$token = new Token();

//投遞令牌

swoole_timer_tick(800, function () use ($token) {
    $token->add(1);
});

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章