1. 程式人生 > 其它 >令牌桶實現伺服器限流

令牌桶實現伺服器限流

啥是令牌桶演算法限流:

  回到了改革開放吃集體飯的時代(生產力不足),有布票才能買到布,才能做成衣服。

回到伺服器來說,就是伺服器每秒併發只有200,但是超過200以上的訪問,持續一段時間,就可能導致‘巖機’。如果伺服器被ddos攻擊了,用到令牌桶演算法限流,可以解決伺服器宕機不響應問題。

如何實現呢,我簡單寫了一個令牌桶類,大概能描述這個意思:  

<?php
/**
 *User:jiangsheng
 *Date:2021/11/29
 *Email:<[email protected]>
 */
## 令牌桶功能
### 請求令牌|生成令牌|初始化臨牌桶
### 邏輯:每秒根據給生成100個令牌,用完就不給訪問(提示沒有訪問間隔),每秒往令牌桶插入100條,如果存在未使用完令牌就補充多少個
class TokenBucket{ private static $_maxNum = 100; private static $_redis=null; private static $_link; private static $_config = [ 'host'=>'127.0.0.1', 'port'=>'6379' ]; # 建立一個redis單例物件,初始化 public static function initialization(array $config=[]){
if ( count($config) > 0 ) self::$_config = $config; if ( self::$_redis == null ) self::$_redis = new redis(); try{ self::$_link = self::$_redis->connect( self::$_config['host'] , self::$_config['port'] ); }catch (Exception $e){
die($e->getMessage()); } return self::$_redis; } # 初始化令牌 public static function set(string $key='k'){ // self::$_redis->flushAll(); $currNum = self::$_redis->lLen( $key ); do{ self::$_redis->lPush($key, $key.$currNum); $currNum++; }while( $currNum < self::$_maxNum ); return self::$_redis->lRange($key, 0, self::$_maxNum); } public static function get(string $key='k'){ return self::$_redis->rPop($key); } private function __construct(){ // TODO: Implement __wakeup() method. } final function __destruct(){ // TODO: Implement __wakeup() method. } final function __clone(){ // TODO: Implement __wakeup() method. } final function __wakeup(){ // TODO: Implement __wakeup() method. } } $config = ['host'=>'localhost','port'=>'6379']; $link = TokenBucket::initialization($config); $k1Arr = TokenBucket::set(); // 模擬客戶端1s請求102次 $i=0; $requestNum = 102; while($i<$requestNum){ $key = TokenBucket::get(); if(empty($key)){ echo "<br>使用者".$i."無法訪問"; }else{ echo "<br>使用者".$i.",獲取到key=》".$key; } $i++; }
分享技術,方便你我他。