Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Bagaimana untuk melaksanakan pengehadan arus baldi token dalam PHP

Bagaimana untuk melaksanakan pengehadan arus baldi token dalam PHP

藏色散人
藏色散人asal
2021-11-23 10:06:412852semak imbas

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.

Bagaimana untuk melaksanakan pengehadan arus baldi token dalam PHP

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 <

Sudah tentu kita boleh menambah pelayan untuk berkongsi tekanan Pertama sekali, menambah pelayan juga mengambil masa tertentu untuk mengkonfigurasi, dan jika pelayan ditambah kerana aktiviti tertentu, sumber pelayan ini akan sia-sia. selepas aktiviti tamat.

Oleh itu, kita boleh menggunakan kaedah

current limiting

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

1. Pertama, terdapat baldi token, dan token disimpan dalam baldi Pada mulanya, token dalam baldi token penuh ( baldi Bilangan token boleh ditetapkan mengikut keadaan pelayan).

2. Setiap lawatan mengambil token daripada baldi Apabila token dalam baldi adalah 0, tiada lagi lawatan dibenarkan.

3. Tambah token sekali-sekala sehingga baldi penuh dengan token. (Anda boleh memasukkan beberapa token secara berkala atau terus mengisi baldi token mengikut situasi sebenar)

Kita boleh menggunakan barisan

redis

sebagai bekas baldi token Gunakan

lPush (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[&#39;host&#39;],$this->_config[&#39;port&#39;],$this->_config[&#39;timeout&#39;],$this->_config[&#39;reserved&#39;],$this->_config[&#39;retry_interval&#39;]);            if(empty($this->_config[&#39;auth&#39;])){                $redis->auth($this->_config[&#39;auth&#39;]);
            }            $redis->select($this->_config[&#39;index&#39;]);
        }catch(RedisException $e){            throw new Exception($e->getMessage());            return false;
        }        return $redis;
    }


} // class end?>
demo:

Output:
<?php
/**
 * 演示令牌加入与消耗
 */
require &#39;TrafficShaper.class.php&#39;;

// redis连接设定
$config = array(
    &#39;host&#39; => &#39;localhost&#39;,
    &#39;port&#39; => 6379,
    &#39;index&#39; => 0,
    &#39;auth&#39; => &#39;&#39;,
    &#39;timeout&#39; => 1,
    &#39;reserved&#39; => NULL,
    &#39;retry_interval&#39; => 100,
);

// 令牌桶容器
$queue = &#39;mycontainer&#39;;

// 最大令牌数
$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 false
Menambah 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.

Prosedur penggunaan simulasi adalah seperti berikut, menggunakan 2-8 token sesaat.
<?php
/**
 * 定时任务加入令牌
 */
require &#39;TrafficShaper.class.php&#39;;

// redis连接设定
$config = array(
    &#39;host&#39; => &#39;localhost&#39;,
    &#39;port&#39; => 6379,
    &#39;index&#39; => 0,
    &#39;auth&#39; => &#39;&#39;,
    &#39;timeout&#39; => 1,
    &#39;reserved&#39; => NULL,
    &#39;retry_interval&#39; => 100,
);

// 令牌桶容器
$queue = &#39;mycontainer&#39;;

// 最大令牌数
$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 &#39;[&#39;.date(&#39;Y-m-d H:i:s&#39;).&#39;] add token num:&#39;.$add_num.PHP_EOL;
    sleep($time_step);
}

?>

Demo
<?php
/**
 * 模拟用户访问消耗令牌,每段时间间隔消耗若干令牌
 */
require &#39;TrafficShaper.class.php&#39;;

// redis连接设定
$config = array(
    &#39;host&#39; => &#39;localhost&#39;,
    &#39;port&#39; => 6379,
    &#39;index&#39; => 0,
    &#39;auth&#39; => &#39;&#39;,
    &#39;timeout&#39; => 1,
    &#39;reserved&#39; => NULL,
    &#39;retry_interval&#39; => 100,
);

// 令牌桶容器
$queue = &#39;mycontainer&#39;;

// 最大令牌数
$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 &#39;[&#39;.date(&#39;Y-m-d H:i:s&#39;).&#39;] consume token:&#39;.($status? &#39;true&#39; : &#39;false&#39;).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!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn