utopia-php/balancing

一个简单用于在多个选项之间进行平衡的库。

0.4.0 2023-08-07 10:26 UTC

README

Build Status Total Downloads Discord

Utopia Balancer库是一个简单轻量级的库,用于在多个选项之间进行平衡。该库旨在尽可能简单、易于学习和使用。该库由Appwrite团队维护。

尽管这个库是Utopia框架项目的一部分,但它不依赖于其他库,可以独立于任何其他PHP项目或框架使用。

入门

使用composer安装

composer require utopia-php/balancer

Balancer支持多种算法。每个算法选择选项的方式不同,并且可能提供不同的配置方法。

Balancer算法

  1. 随机

Random算法随机选择选项。相同的选项可能会连续多次被选中。示例

<?php

require_once '../vendor/autoload.php';

use Utopia\Balancer\Algorithm\Random;
use Utopia\Balancer\Balancer;
use Utopia\Balancer\Option;

$balancer = new Balancer(new Random());

$balancer->addFilter(fn (Option $option) => $option->getState('online', false) === true);

$balancer
    ->addOption(new Option([ 'hostname' => 'proxy-1', 'online' => true ]))
    ->addOption(new Option([ 'hostname' => 'proxy-2', 'online' => false ]))
    ->addOption(new Option([ 'hostname' => 'proxy-3', 'online' => true ]));

var_dump($balancer->run());
var_dump($balancer->run());
var_dump($balancer->run());
  1. 第一个和最后一个

First算法始终选择第一个选项。类似地,Last算法始终选择最后一个选项。示例

<?php

require_once '../vendor/autoload.php';

use Utopia\Balancer\Algorithm\First;
use Utopia\Balancer\Algorithm\Last;
use Utopia\Balancer\Balancer;
use Utopia\Balancer\Option;

$balancer = new Balancer(new First());

$balancer
    ->addOption(new Option([ 'runtime' => 'PHP' ]))
    ->addOption(new Option([ 'runtime' => 'JavaScript' ]))
    ->addOption(new Option([ 'runtime' => 'Java' ]));

var_dump($balancer->run());

$balancer = new Balancer(new Last());

$balancer
    ->addOption(new Option([ 'runtime' => 'PHP' ]))
    ->addOption(new Option([ 'runtime' => 'JavaScript' ]))
    ->addOption(new Option([ 'runtime' => 'Java' ]));

var_dump($balancer->run());
  1. 轮询

RoundRobin算法从第一个选项开始循环。一旦算法遍历了所有选项,它将重置回开始位置。示例

<?php

require_once '../vendor/autoload.php';

use Utopia\Balancer\Algorithm\RoundRobin;
use Utopia\Balancer\Balancer;
use Utopia\Balancer\Option;

$balancer = new Balancer(new RoundRobin(-1));

$balancer->addFilter(fn (Option $option) => $option->getState('online', false) === true);

$balancer
    ->addOption(new Option([ 'dataCenter' => 'fra-1' ]))
    ->addOption(new Option([ 'dataCenter' => 'fra-2' ]))
    ->addOption(new Option([ 'dataCenter' => 'lon-1' ]));

var_dump($balancer->run()); // fra-1
var_dump($balancer->run()); // fra-2
var_dump($balancer->run()); // lon-1
var_dump($balancer->run()); // fra-1
var_dump($balancer->run()); // fra-2

在并发模型中使用RoundRobin时,请确保以原子方式存储索引。示例

<?php

require_once '../vendor/autoload.php';

use Utopia\Balancer\Algorithm\RoundRobin;
use Utopia\Balancer\Balancer;
use Utopia\Balancer\Option;

$atomic = new Atomic(-1); // Some atomic implementation, for example: https://openswoole.com/docs/modules/swoole-atomic

function onRequest() {
    $lastIndex = $atomic->get();
    $algo = new RoundRobin($lastIndex);
    $balancer = new Balancer();

    $balancer->addFilter(fn (Option $option) => $option->getState('online', false) === true);

    $balancer
        ->addOption(new Option([ 'dataCenter' => 'fra-1' ]))
        ->addOption(new Option([ 'dataCenter' => 'fra-2' ]))
        ->addOption(new Option([ 'dataCenter' => 'lon-1' ]));

    var_dump($balancer->run());

    $atomic->cmpset($lastIndex, $algo->getIndex());
}

Balancer组

如果平衡器过滤器导致平衡器没有任何选项可供选择,将返回null。在大多数情况下,您将需要一个备份逻辑来处理这种情况。您可以使用Group创建多个平衡器的组,如果其中一个失败,下一个可以用于回退。请注意,Group将按照您添加的顺序进行平衡。

<?php

require_once '../vendor/autoload.php';

use Utopia\Balancer\Algorithm\First;
use Utopia\Balancer\Balancer;
use Utopia\Balancer\Group;
use Utopia\Balancer\Option;

// Prepare options where each has high CPU load
$options = [
    new Option([ 'dataCenter' => 'fra-1', 'cpu' => 91 ]),
    new Option([ 'dataCenter' => 'fra-2', 'cpu' => 95 ]),
    new Option([ 'dataCenter' => 'lon-1', 'cpu' => 87 ]),
];

// Prepare balancer that allows only low CPU load options
$balancer1 = new Balancer(new First());
$balancer1->addFilter(fn ($option) => $option->getState('cpu') < 80);

// Prepare balancer that allows all options
$balancer2 = new Balancer(new First());

// Add options to both balancers
foreach ($options as $option) {
    $balancer1->addOption($option);
    $balancer2->addOption($option);
}

// Prepare group with both balancers
$group = new Group();
$group
    ->add($balancer1)
    ->add($balancer2);

// Run group to get option
$option = $group->run() ?? new Option([]);

\var_dump($option);
// We got fra-1 option. First balancer filtered out all options, but second balancer allowed any, and First algorithm picked first option

系统要求

Utopia框架需要PHP 8.0或更高版本。我们建议尽可能使用最新的PHP版本。

版权和许可

MIT许可(MIT) https://open-source.org.cn/licenses/mit-license.php