1. 程式人生 > 其它 >php 平滑加權輪循演算法實現

php 平滑加權輪循演算法實現

在做專案的過程中,特別是做abTest會用到輪循演算法,有順序輪循、平滑加權輪循:

廢話不多說上程式碼吧:

比較好理解。我用的是laravel框架實現的

1、簡單實現順序迴圈

        //簡單輪巡  方法呼叫方
        $arr = ['a', 'b'];
        $simple = new SimpleCyclic($arr);
        for ($i = 0; $i < 10; $i++) {
            $a = $simple->next();
            echo $a;
        }

 

 

//SimpleCyclic.php 程式碼 具體實現類方法 
<?php

namespace App\common;

use App\common\RobinInterface;

//簡單輪巡

class SimpleCyclic
{
    //輪巡陣列
    protected $params;
    protected $total;//輪巡數量

    //初始化當前指標所在位置
    protected $currentPosition = -1;

    /**
     * SimpleCyclic constructor.
     * @param array $params 輪巡陣列
     */
    public function
__construct(array $services) { $this->params = $services; $this->total = count($services); } public function next() { // 已排程完一圈,重置currentPos值為第一個例項位置 $this->currentPosition = ($this->currentPosition + 1) % $this->total; return $this
->params[$this->currentPosition]; } }

 

 

2、實現平滑加權輪循

        //平滑輪巡
        //需要注意的是,在配置services服務列表時,同樣需要指定其權重:
        $services = [
            '192.168.10.1:2202' => 5,
            '192.168.10.2:2202' => 1,
            '192.168.10.3:2202' => 1,
        ];
        $smooth = new SmoothWeight($services);
        $a = $smooth->next();
        echo "<pre>";
        echo $a . "\n";

 

//SmoothWeight.php 實現類

<?php

/**
 * 加權平滑輪巡
 * Created by PhpStorm.
 */

namespace App\common;

class SmoothWeight
{
    private $services = [];

    private $currentPos = -1;

    public function __construct(array $services)
    {
        foreach ($services as $ip => $weight) {
            $this->services[] = [
                'ip' => $ip,
                'weight' => $weight,
                'current_weight' => $weight,
            ];
        }
    }

    /**
     * 獲取指標
     * @return mixed
     */
    public function next()
    {
        // 獲取最大當前有效權重例項的位置
        $this->currentPos = $this->getMaxCurrentWeightPos();

        // 當前權重減去權重和
        $currentWeight = $this->getCurrentWeight($this->currentPos) - $this->getSumWeight();
        $this->setCurrentWeight($this->currentPos, $currentWeight);

        // 每個例項的當前有效權重加上配置權重
        $this->recoverCurrentWeight();

        return $this->services[$this->currentPos]['ip'];
    }

    /**
     * 獲取當前動態權重最大值 所在指標 也就是陣列得下標值
     * @return int|string
     */
    public function getMaxCurrentWeightPos()
    {
        $currentWeight = $pos = 0;
        foreach ($this->services as $index => $service) {
            if ($service['current_weight'] > $currentWeight) {
                $currentWeight = $service['current_weight'];
                $pos = $index;
            }
        }

        return $pos;
    }

    /**
     * 調整當前配置動態權重值 當前權重+配置權重值
     */
    public function recoverCurrentWeight()
    {
        foreach ($this->services as $index => &$service) {
            $service['current_weight'] += $service['weight'];
        }
    }

    /**
     * 獲取當前指標動態權重值
     * @param $currentPos
     * @return mixed
     */
    public function getCurrentWeight($currentPos)
    {
        return $this->services[$currentPos]['current_weight'];
    }

    /**
     * 設定當前指標動態權重值
     * @param $currentPos
     * @param $currentWeight
     */
    public function setCurrentWeight($currentPos, $currentWeight)
    {
        $this->services[$currentPos]['current_weight'] = $currentWeight;
    }

    /**
     * 獲取配置陣列權重數量總和
     * @return int|mixed
     */
    public function getSumWeight()
    {
        $num = 0;
        foreach ($this->services as $key => $value) {
            $num += $value['weight'];
        }
        return $num;
    }


}

 

 

以上為實現的全部程式碼了,大家可以拷貝下來試試。