123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- <?php
- namespace Yansongda\Supports\Traits;
- use Predis\Client;
- /**
- * Trait ShouldThrottle.
- *
- * @property Client $redis
- */
- trait ShouldThrottle
- {
- /**
- * _throttle.
- *
- * @var array
- */
- protected $_throttle = [
- 'limit' => 60,
- 'period' => 60,
- 'count' => 0,
- 'reset_time' => 0,
- ];
- /**
- * isThrottled.
- *
- * @author yansongda <me@yansongda.cn>
- *
- * @param string $key
- * @param int $limit
- * @param int $period
- * @param bool $auto_add
- *
- * @return bool
- */
- public function isThrottled($key, $limit = 60, $period = 60, $auto_add = false)
- {
- if (-1 === $limit) {
- return false;
- }
- $now = microtime(true) * 1000;
- $this->redis->zremrangebyscore($key, 0, $now - $period * 1000);
- $this->_throttle = [
- 'limit' => $limit,
- 'period' => $period,
- 'count' => $this->getThrottleCounts($key, $period),
- 'reset_time' => $this->getThrottleResetTime($key, $now),
- ];
- if ($this->_throttle['count'] < $limit) {
- if ($auto_add) {
- $this->throttleAdd($key, $period);
- }
- return false;
- }
- return true;
- }
- /**
- * 限流 + 1.
- *
- * @author yansongda <me@yansongda.cn>
- *
- * @param string $key
- * @param int $period
- */
- public function throttleAdd($key, $period = 60)
- {
- $now = microtime(true) * 1000;
- $this->redis->zadd($key, [$now => $now]);
- $this->redis->expire($key, $period * 2);
- }
- /**
- * getResetTime.
- *
- * @author yansongda <me@yansongda.cn>
- *
- * @param $key
- * @param $now
- *
- * @return int
- */
- public function getThrottleResetTime($key, $now)
- {
- $data = $this->redis->zrangebyscore(
- $key,
- $now - $this->_throttle['period'] * 1000,
- $now,
- ['limit' => [0, 1]]
- );
- if (0 === count($data)) {
- return $this->_throttle['reset_time'] = time() + $this->_throttle['period'];
- }
- return intval($data[0] / 1000) + $this->_throttle['period'];
- }
- /**
- * 获取限流相关信息.
- *
- * @author yansongda <me@yansongda.cn>
- *
- * @param string|null $key
- * @param mixed|null $default
- *
- * @return array|null
- */
- public function getThrottleInfo($key = null, $default = null)
- {
- if (is_null($key)) {
- return $this->_throttle;
- }
- if (isset($this->_throttle[$key])) {
- return $this->_throttle[$key];
- }
- return $default;
- }
- /**
- * 获取已使用次数.
- *
- * @author yansongda <me@yansongda.cn>
- *
- * @param string $key
- * @param int $period
- *
- * @return string
- */
- public function getThrottleCounts($key, $period = 60)
- {
- $now = microtime(true) * 1000;
- return $this->redis->zcount($key, $now - $period * 1000, $now);
- }
- }
|