utopia-php/balancer

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

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

平衡器支持多种算法。每个算法选择选项的方式不同,并且可能有一组不同的方法可供配置。

平衡器算法

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

平衡器组

如果平衡器过滤器导致平衡器没有选项可供选择,将返回 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