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;
    }


}

 

 

以上为实现的全部代码了,大家可以拷贝下来试试。

 

posted @ 2022-03-14 15:05  核桃MM  阅读(188)  评论(0)    收藏  举报