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; } }
以上为实现的全部代码了,大家可以拷贝下来试试。