Lavavel5.5源代码 - 限流工具

Posted xiaoyaogege

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Lavavel5.5源代码 - 限流工具相关的知识,希望对你有一定的参考价值。

 

app(‘redis‘)->connection(‘default‘)->throttle(‘key000‘)
               // 每60秒,只能有10个资源被获取,在3秒内获取不到锁抛出异常
               ->allow(10)->every(60)->block(3)
               ->then(function () {
                    // 获取锁成功,执行业务
               }, function () {
                   // 获取锁失败
                   return false;
               });

 

<?php

namespace IlluminateRedisLimiters;

use IlluminateContractsRedisLimiterTimeoutException;

class DurationLimiter
{
    /**
     * The Redis factory implementation.
     *
     * @var IlluminateRedisConnectionsConnection
     */
    private $redis;

    /**
     * The unique name of the lock.
     *
     * @var string
     */
    private $name;

    /**
     * The allowed number of concurrent tasks.
     *
     * @var int
     */
    private $maxLocks;

    /**
     * The number of seconds a slot should be maintained.
     *
     * @var int
     */
    private $decay;

    /**
     * The timestamp of the end of the current duration.
     *
     * @var int
     */
    public $decaysAt;

    /**
     * The number of remaining slots.
     *
     * @var int
     */
    public $remaining;

    /**
     * Create a new duration limiter instance.
     *
     * @param  IlluminateRedisConnectionsConnection $redis
     * @param  string $name
     * @param  int $maxLocks
     * @param  int $decay
     * @return void
     */
    public function __construct($redis, $name, $maxLocks, $decay)
    {
        $this->name = $name;
        $this->decay = $decay;
        $this->redis = $redis;
        $this->maxLocks = $maxLocks;
    }

    /**
     * Attempt to acquire the lock for the given number of seconds.
     *
     * @param  int $timeout
     * @param  callable|null $callback
     * @return bool
     * @throws IlluminateContractsRedisLimiterTimeoutException
     */
    public function block($timeout, $callback = null)
    {
        $starting = time();

        while (! $this->acquire()) {
            if (time() - $timeout >= $starting) {
                throw new LimiterTimeoutException;
            }

            usleep(750 * 1000);
        }

        if (is_callable($callback)) {
            $callback();
        }

        return true;
    }

    /**
     * Attempt to acquire the lock.
     *
     * @return bool
     */
    public function acquire()
    {
        $results = $this->redis->eval($this->luaScript(), 1,
            $this->name, microtime(true), time(), $this->decay, $this->maxLocks
        );

        $this->decaysAt = $results[1];

        $this->remaining = max(0, $results[2]);

        return (bool) $results[0];
    }

    /**
     * Get the Lua script for acquiring a lock.
     *
     * KEYS[1] - The limiter name
     * ARGV[1] - Current time in microseconds
     * ARGV[2] - Current time in seconds
     * ARGV[3] - Duration of the bucket
     * ARGV[4] - Allowed number of tasks
     *
     * @return string
     */
    protected function luaScript()
    {
        return <<<‘LUA‘
local function reset()
    redis.call(‘HMSET‘, KEYS[1], ‘start‘, ARGV[2], ‘end‘, ARGV[2] + ARGV[3], ‘count‘, 1)
    return redis.call(‘EXPIRE‘, KEYS[1], ARGV[3] * 2)
end

if redis.call(‘EXISTS‘, KEYS[1]) == 0 then
    return {reset(), ARGV[2] + ARGV[3], ARGV[4] - 1}
end

if ARGV[1] >= redis.call(‘HGET‘, KEYS[1], ‘start‘) and ARGV[1] <= redis.call(‘HGET‘, KEYS[1], ‘end‘) then
    return {
        tonumber(redis.call(‘HINCRBY‘, KEYS[1], ‘count‘, 1)) <= tonumber(ARGV[4]),
        redis.call(‘HGET‘, KEYS[1], ‘end‘),
        ARGV[4] - redis.call(‘HGET‘, KEYS[1], ‘count‘)
    }
end

return {reset(), ARGV[2] + ARGV[3], ARGV[4] - 1}
LUA;
    }
}

  

  

以上是关于Lavavel5.5源代码 - 限流工具的主要内容,如果未能解决你的问题,请参考以下文章

Lavavel5.5源代码 - 并发数控制

Lavavel5.5源代码 - RedisQueue是怎么实现

Lavavel5.5源代码 - RedisQueue是怎么实现

如何利用redis来进行分布式集群系统的限流设计

java限流工具类

PHP代码-psysh调试代码片段工具