当前位置: 首页 > 知识库问答 >
问题:

不使用库的会话PHP限制速率

王昆
2023-03-14

我正在使用PHP作为我的webservice的后端,我需要webservice能够设置一个速率限制,在过去24小时内,基于用户的PHP会话,最多1000个请求。这是不是可以做到这一点,而不使用数据库和只是速率限制,只使用PHP。我目前已经为每个会话每秒1个请求设置了速率限制器,但我希望在过去24小时内为每个会话设置1000个请求的速率限制。因为我是PHP的新手,任何帮助都会很好。

这里是我为每秒1速率限制所做的代码

class gaqsession {

        public $lastrequest;

        public function __construct() {
            $this->lastrequest = time();
        }
        public function ratelimited() {
            if($this->lastrequest == time()) {
                $this->lastrequest = time();
                return true;
            } else {
                $this->lastrequest = time();
            return false;
            } 
        }
    }

共有1个答案

司空福
2023-03-14

只要将会话设置为至少持续24小时,您就可以执行此操作。唯一真正的诀窍是在会话中保存速率计数,使您能够在24小时内保持它们。您可以通过一个使用时间作为键的简单数组来实现这一点。下面是一个类,它在这样的数组周围添加了一些特性,以便轻松地管理数据,同时还有一些示例代码来运行它的速度。

/**
 * Class RateLimitCounter
 * Track number of events by time. Intended to be set on a session.
 */
class RateLimitCounter
{
    // The time -> request count data
    private $timeline = [];

    /**
     * Log an event in the timeline
     */
    public function increment()
    {
        $now = time();
        if (!array_key_exists($now, $this->timeline))
        {
            $this->timeline[$now] = 0;
        }

        $this->timeline[$now]++;
    }

    /**
     * Return the total number of events logged in the counter
     * @return int
     */
    public function getTotal()
    {
        return array_sum($this->timeline);
    }

    /**
     * Remove any timeline data older than 24 hours
     */
    private function trim()
    {
        // Get the current time
        $now = time();

        // Time is in seconds, so subtract 1 day worth of seconds
        $timeFloor = $now - 86400;

        // Filter out all timeline entries more than 24 hours old
        $this->timeline = array_filter($this->timeline, function ($key) use ($timeFloor) {
            return $key > $timeFloor;
        }, ARRAY_FILTER_USE_KEY);
    }

    public function __serialize(): array
    {
        return [
            'timeline' => $this->timeline
        ];
    }

    /**
     * Wake up! Set the timeline data and trim data older than 24 hours
     * @param array $data
     */
    public function __unserialize(array $data): void
    {
        $this->timeline = $data['timeline'];

        $this->trim();
    }
}

/**
 * Verify that the rate limit has not been exceeded. Bail out if it has been.
 * @param $counter
 * @return bool
 */
function rateLimit($counter)
{
    $limit = 1000;
    if ($counter->getTotal() > $limit)
    {
        // Do whatever you need to here, throw an exception, redirect to an error page, etc.
        exit('Rate limit exceeded' . PHP_EOL);
    }

    return true;
}

/*
 * Instantiate a counter - this is what you would do if you do not already have one on the session
 */
$counter = new RateLimitCounter();

/*
 * Simulate some prior activity
 * Let's get close to the limit then save to the "session"
 */
for ($i = 0; $i <= 995; $i++)
{
    $counter->increment();
}

// Mock session
$dummySession = ['counter' => $counter];

// Serialize the session
$serializedSession = serialize($dummySession);

// Unserialize the session
$session = unserialize($serializedSession);

$counter = $session['counter'];

// Do API calls until we hit our limit. There should be 5 remaining.
while (rateLimit($counter))
{
    apiCall();

    // Don't forget to increment the counter for each call
    $counter->increment();
}

// Dummy function to simulate your API call
function apiCall()
{
    echo 'Doing something interesting' . PHP_EOL;
}
 类似资料:
  • 是否可以限制siteminder SP上受保护资源上的活动用户数?我想确保受保护的资源被有限数量的活动用户使用,比如说n。 谢谢Andrea

  • 我正在使用ProjectReactor使用rest从web服务加载数据。这是与多个线程并行完成的。我开始达到web服务的速率限制,因此我希望每秒最多发送10个请求,以避免出现这些错误。用Reactor我该怎么做? 使用zipWith(Mono.delayMillis(100))?还是有更好的办法? 非常感谢。

  • 我想了解限速器是怎么工作的。 我在博客中看到的是: 到现在为止,我忽略了删除旧的钥匙。我不明白这个索伦是怎么工作的?正如上面所说,在多线程环境中,代码将在一秒钟内完成10个以上的api调用。它只能通过将redisclient.get(key)同步到callApi()代码来解决。 我从 假设在当前的第二个中已经服务了9个请求,现在同时出现了5个新的请求,所有这些新的线程在这5个线程中的任何一个执行“

  • 是否可以限制会话和与之相关的请求可以使用的内存量? 例如,我希望将每个用户会话限制为一兆字节。此限制应适用于处理请求时创建的任何对象。有可能吗?

  • 问题内容: 如标题所述,会话变量是否有限制(如果有),或者它们被视为 常规 变量并且可以存储相等数量的数据? 我在寻找是否存在除最大长度,最大值等变量类型之外的其他限制。 附注:如果问题不清楚,请告诉我。 提前致谢! 问题答案: 正如@Thariama所说,变量的数量没有限制。此外,会话中可以存储的数据量没有限制(我看到会话的大小为几十MB)。 随着会话的大小变大,您会遇到各种奇怪的问题:PHP

  • 问题内容: 解决的更新: 经过所有这些工作,我发现我正在更新ajax中调用代码的旧版本。“ boardControl.php”而不是“ boardUpdate.php”这些是使编程变得有趣的错误类型。 我正在写一个浏览器gomoku游戏。我有ajax声明,允许播放器演奏一曲。 值=木板面积位置 出价=木板ID 在创建用于标识玩家身份的用户登录名之前,服务器端php有一个临时解决方案。单击时会旋转方