Rumah > Artikel > pembangunan bahagian belakang > Bagaimana untuk melaksanakan pengehadan arus baldi token dalam PHP
Cara melaksanakan had semasa baldi token dalam PHP: 1. Sediakan baldi token dan simpan token dalam baldi 2. Ambil satu token dari baldi untuk setiap lawatan 3. Mengikut situasi sebenar , cuma masukkan beberapa token sekali-sekala atau isikan terus baldi token.
Persekitaran pengendalian artikel ini: sistem Windows 7, PHP7.1, komputer Dell G3.
Bagaimanakah PHP melaksanakan had semasa baldi token?
php menggunakan algoritma baldi token untuk melaksanakan kawalan aliran berdasarkan redis
Artikel ini memperkenalkan PHP berdasarkan redis dan menggunakan algoritma baldi token untuk mengawal trafik akses Ia menyediakan penerangan dan contoh demonstrasi algoritma yang lengkap untuk dipelajari dan digunakan oleh semua orang.
Setiap kali ada cuti domestik yang panjang atau perayaan penting, tempat pemandangan domestik atau kereta bawah tanah akan sesak dengan orang ramai, mengakibatkan beban yang berlebihan Sesetengah akan menggunakan langkah mengehadkan aliran untuk mengehadkan bilangan orang yang masuk orang di kawasan itu dikurangkan kepada nilai tertentu, dan kemudian membenarkan kemasukan.
Contohnya:
Bilangan maksimum orang yang dibenarkan di kawasan itu ialah M
Bilangan semasa orang di kawasan itu ialah N
Setiap kali anda memasuki Satu orang, N 1, apabila N = M, tidak dibenarkan masuk
Setiap orang yang keluar, N-1, apabila Apabila N <
untuk mengurangkan tekanan pelayan mengikut jenis perniagaan. Berbeza dengan had lalu lintas di tempat yang indah, masa dari lawatan ke penghujung sistem adalah sangat singkat
, jadi kami hanya perlu mengetahui purata tempoh setiap lawatan dan tetapkan maksimum bilangan pelawat serentak .Algoritma Token Bucket
redis
sebagai bekas baldi token GunakanlPush (enqueue), rPop (dequeue) untuk melaksanakan operasi penambahan dan penggunaan token.
TrafficShaper.class.php
<?php /** * PHP基于Redis使用令牌桶算法实现流量控制 * Date: 2018-02-23 * Author: fdipzone * Version: 1.0 * * Descripton: * php基于Redis使用令牌桶算法实现流量控制,使用redis的队列作为令牌桶容器,入队(lPush)出队(rPop)作为令牌的加入与消耗操作。 * * Func: * public add 加入令牌 * public get 获取令牌 * public reset 重设令牌桶 * private connect 创建redis连接 */class TrafficShaper{ // class start private $_config; // redis设定 private $_redis; // redis对象 private $_queue; // 令牌桶 private $_max; // 最大令牌数 /** * 初始化 * @param Array $config redis连接设定 */ public function __construct($config, $queue, $max){ $this->_config = $config; $this->_queue = $queue; $this->_max = $max; $this->_redis = $this->connect(); } /** * 加入令牌 * @param Int $num 加入的令牌数量 * @return Int 加入的数量 */ public function add($num=0){ // 当前剩余令牌数 $curnum = intval($this->_redis->lSize($this->_queue)); // 最大令牌数 $maxnum = intval($this->_max); // 计算最大可加入的令牌数量,不能超过最大令牌数 $num = $maxnum>=$curnum+$num? $num : $maxnum-$curnum; // 加入令牌 if($num>0){ $token = array_fill(0, $num, 1); $this->_redis->lPush($this->_queue, ...$token); return $num; } return 0; } /** * 获取令牌 * @return Boolean */ public function get(){ return $this->_redis->rPop($this->_queue)? true : false; } /** * 重设令牌桶,填满令牌 */ public function reset(){ $this->_redis->delete($this->_queue); $this->add($this->_max); } /** * 创建redis连接 * @return Link */ private function connect(){ try{ $redis = new Redis(); $redis->connect($this->_config['host'],$this->_config['port'],$this->_config['timeout'],$this->_config['reserved'],$this->_config['retry_interval']); if(empty($this->_config['auth'])){ $redis->auth($this->_config['auth']); } $redis->select($this->_config['index']); }catch(RedisException $e){ throw new Exception($e->getMessage()); return false; } return $redis; } } // class end?>demo:
Output:
<?php /** * 演示令牌加入与消耗 */ require 'TrafficShaper.class.php'; // redis连接设定 $config = array( 'host' => 'localhost', 'port' => 6379, 'index' => 0, 'auth' => '', 'timeout' => 1, 'reserved' => NULL, 'retry_interval' => 100, ); // 令牌桶容器 $queue = 'mycontainer'; // 最大令牌数 $max = 5; // 创建TrafficShaper对象 $oTrafficShaper = new TrafficShaper($config, $queue, $max); // 重设令牌桶,填满令牌 $oTrafficShaper->reset(); // 循环获取令牌,令牌桶内只有5个令牌,因此最后3次获取失败 for($i=0; $i<8; $i++){ var_dump($oTrafficShaper->get()); } // 加入10个令牌,最大令牌为5,因此只能加入5个 $add_num = $oTrafficShaper->add(10); var_dump($add_num); // 循环获取令牌,令牌桶内只有5个令牌,因此最后1次获取失败 for($i=0; $i<6; $i++){ var_dump($oTrafficShaper->get()); } ?>
Menambah algoritma token secara kerap
boolean true boolean true boolean true boolean true boolean true boolean false boolean false boolean false int 5 boolean true boolean true boolean true boolean true boolean true boolean falseMenambah token secara kerap, kita boleh menggunakan crontab untuk melaksanakannya, dan memanggil kaedah tambah untuk sertai setiap minit Beberapa token. Selang pelaksanaan minimum crontab ialah 1 minit Jika token dalam baldi token telah digunakan dalam beberapa saat pertama, maka token tidak akan diperolehi dalam baki berpuluh-puluh saat tunggu lagi. Kami boleh mengoptimumkan algoritma untuk menambah token dan menambah beberapa token setiap beberapa saat dalam satu minit Ini boleh memastikan bahawa terdapat peluang untuk mendapatkan token setiap kali dalam masa seminit.
Program penambahan token yang dipanggil oleh crontab adalah seperti berikut, secara automatik menambah 3 token sesaat.
<?php /** * 定时任务加入令牌 */ require 'TrafficShaper.class.php'; // redis连接设定 $config = array( 'host' => 'localhost', 'port' => 6379, 'index' => 0, 'auth' => '', 'timeout' => 1, 'reserved' => NULL, 'retry_interval' => 100, ); // 令牌桶容器 $queue = 'mycontainer'; // 最大令牌数 $max = 10; // 每次时间间隔加入的令牌数 $token_num = 3; // 时间间隔,最好是能被60整除的数,保证覆盖每一分钟内所有的时间 $time_step = 1; // 执行次数 $exec_num = (int)(60/$time_step); // 创建TrafficShaper对象 $oTrafficShaper = new TrafficShaper($config, $queue, $max); for($i=0; $i<$exec_num; $i++){ $add_num = $oTrafficShaper->add($token_num); echo '['.date('Y-m-d H:i:s').'] add token num:'.$add_num.PHP_EOL; sleep($time_step); } ?>
Demo
<?php /** * 模拟用户访问消耗令牌,每段时间间隔消耗若干令牌 */ require 'TrafficShaper.class.php'; // redis连接设定 $config = array( 'host' => 'localhost', 'port' => 6379, 'index' => 0, 'auth' => '', 'timeout' => 1, 'reserved' => NULL, 'retry_interval' => 100, ); // 令牌桶容器 $queue = 'mycontainer'; // 最大令牌数 $max = 10; // 每次时间间隔随机消耗的令牌数量范围 $consume_token_range = array(2, 8); // 时间间隔 $time_step = 1; // 创建TrafficShaper对象 $oTrafficShaper = new TrafficShaper($config, $queue, $max); // 重设令牌桶,填满令牌 $oTrafficShaper->reset(); // 执行令牌消耗 while(true){ $consume_num = mt_rand($consume_token_range[0], $consume_token_range[1]); for($i=0; $i<$consume_num; $i++){ $status = $oTrafficShaper->get(); echo '['.date('Y-m-d H:i:s').'] consume token:'.($status? 'true' : 'false').PHP_EOL; } sleep($time_step); } ?>
Tetapkan tugas berjadual untuk dilaksanakan setiap minit
Laksanakan penggunaan simulasi
* * * * * php /程序的路径/cron_add.php >> /tmp/cron_add.log
Hasil pelaksanaan:
php consume_demo.php
Oleh kerana baldi token penuh pada permulaan (bilangan maksimum token ialah 10), token boleh diperolehi dalam 10 kali pertama, dan selepas 10 kali Akses dihadkan apabila token yang digunakan lebih besar daripada bilangan token yang digabungkan.
[2018-02-23 11:42:57] consume token:true [2018-02-23 11:42:57] consume token:true [2018-02-23 11:42:57] consume token:true [2018-02-23 11:42:57] consume token:true [2018-02-23 11:42:57] consume token:true [2018-02-23 11:42:57] consume token:true [2018-02-23 11:42:57] consume token:true [2018-02-23 11:42:58] consume token:true [2018-02-23 11:42:58] consume token:true [2018-02-23 11:42:58] consume token:true [2018-02-23 11:42:58] consume token:true [2018-02-23 11:42:58] consume token:true [2018-02-23 11:42:58] consume token:true [2018-02-23 11:42:58] consume token:false [2018-02-23 11:42:59] consume token:true [2018-02-23 11:42:59] consume token:true [2018-02-23 11:42:59] consume token:true [2018-02-23 11:42:59] consume token:false [2018-02-23 11:42:59] consume token:false [2018-02-23 11:42:59] consume token:false [2018-02-23 11:42:59] consume token:false [2018-02-23 11:43:00] consume token:true [2018-02-23 11:43:00] consume token:true [2018-02-23 11:43:00] consume token:true [2018-02-23 11:43:00] consume token:false [2018-02-23 11:43:00] consume token:false
Pembelajaran yang disyorkan: "
Tutorial Video PHP
Atas ialah kandungan terperinci Bagaimana untuk melaksanakan pengehadan arus baldi token dalam PHP. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!