Взвешенный алгоритм балансировки нагрузки в приложении PHP

1

Я хочу разрешить взвешенный адаптер с завода, который может быть настроен пользователем (включить/отключить и вес%).

Пример:

  • AdapterW ≃ 20% транзакции
  • AdapterX ≃ 30% транзакции
  • АдаптерY ≃ 40% транзакции
  • AdapterZ ≃ 10% транзакции

Я могу предоставить, что все предметы никогда не будут суммировать более ста (100%), но иногда любой адаптер может быть деактивирован.

У меня есть следующие параметры:

public function handleAdapter()
{
    $isWActive = (boolean)$this->_config[self::W];
    $isXActive = (boolean)$this->_config[self::X];
    $isYActive = (boolean)$this->_config[self::Y];
    $isZActive = (boolean)$this->_config[self::Z];
    $WPercentage = (int)$this->_config[self::LOAD_BALANCE_W];
    $XPercentage = (int)$this->_config[self::LOAD_BALANCE_X];
    $YPercentage = (int)$this->_config[self::LOAD_BALANCE_Y];
    $ZPercentage = (int)$this->_config[self::LOAD_BALANCE_Z];
    .
    .
    .
    return (self::W | self::X | self::Y | self::Z); 
}

Как я могу сбалансировать взвешенные между этими адаптерами динамически?

редактировать

создал сущность для исполняемого кода: https://gist.github.com/markomafs/5d892d06d6670909f9b4

  • 0
    Это поможет вам составить вопрос, который даст эффективный ответ: stackoverflow.com/help/mcve
  • 0
    извините, но по этой ссылке мой вопрос является минимальным, полным и проверяемым. Можете ли вы помочь мне и отправить предложение по редактированию?
Показать ещё 4 комментария
Теги:
algorithm
factory

3 ответа

2

Это может быть не лучший подход, но вы можете попробовать что-то вроде этого:

public function handleAdapter()
{
    //an array to return the balanced entries
    $balancedEntries[] = false;

    //verifies which of the options are active
    $isWActive = (boolean)$this->_config[self::W];
    $isXActive = (boolean)$this->_config[self::X];
    $isYActive = (boolean)$this->_config[self::Y];
    $isZActive = (boolean)$this->_config[self::Z];

    //get configured percentage of each
    $WPercentage = (int)$this->_config[self::LOAD_BALANCE_W];
    $XPercentage = (int)$this->_config[self::LOAD_BALANCE_X];
    $YPercentage = (int)$this->_config[self::LOAD_BALANCE_Y];
    $ZPercentage = (int)$this->_config[self::LOAD_BALANCE_Z];

    //here you fill the array according to the proportion defined by the percentages
    if ($isWActive) {
            for ($i = 0; $i < $WPercentage; $i++) {
                $balancedEntries[] = self::W;
            }
        }

        if ($isXActive) {
            for ($i = 0; $i < $XPercentage; $i++) {
                $balancedEntries[] = self::X;
            }
        }

        if ($isYActive) {
            for ($i = 0; $i < $YPercentage; $i++) {
                $balancedEntries[] = self::Y;
            }
        }

        if ($isZActive) {
            for ($i = 0; $i < $ZPercentage; $i++) {
                $balancedEntries[] = self::Z;
            }
        }

        return $balancedEntries;
}

И тогда, если вы хотите долю от 1 до 100 (как в процентах):

$balancedResult = $balancedEntries[array_rand($balancedEntries, 1)];

Поскольку array_rand возвращает 1 ключ из исходного массива, вы используете его для получения значения.

1

Другая попытка, это должно работать на ваш случай. Но это работает только в том случае, если у вас есть адаптер как одна строка символов, это не видно по вашему вопросу.

public function handleAdapter()
{
    # a map with all adapters
    $map = array(
        self::W => self::LOAD_BALANCE_W,
        self::X => self::LOAD_BALANCE_X,
        self::Y => self::LOAD_BALANCE_Y,
        self::Z => self::LOAD_BALANCE_Z
    );
    # generate a string map with one char per percentage point
    $stringMap = "";
    foreach($map as $key => $value){
        # skip if disabled
        if(!$this->_config[$key]) continue;
        # repeat the key for each percentage point
        $stringMap .= str_repeat($key, (int)$this->_config[$value]);
    }
    # return a random string char from the map
    return $stringMap[rand(0, strlen($stringMap) - 1)];
}
  • 0
    В вашем решении, если имя адаптера имеет более 1 буквы, оно не будет работать
  • 0
    @Markomafs, если это уже упоминалось в ответе.
Показать ещё 1 комментарий
0

Редактировать: я неправильно понял вопрос, ответ неправильный.

Я понимаю ваш вопрос, так что вы всегда хотите вернуть адаптер с наименьшей нагрузкой для принудительного трафика на этот адаптер.

public function handleAdapter()
{
    $isWActive = (boolean)$this->_config[self::W];
    $isXActive = (boolean)$this->_config[self::X];
    $isYActive = (boolean)$this->_config[self::Y];
    $isZActive = (boolean)$this->_config[self::Z];
    $WPercentage = (int)$this->_config[self::LOAD_BALANCE_W];
    $XPercentage = (int)$this->_config[self::LOAD_BALANCE_X];
    $YPercentage = (int)$this->_config[self::LOAD_BALANCE_Y];
    $ZPercentage = (int)$this->_config[self::LOAD_BALANCE_Z];

    $map = array();
    if($isWActive) $map[self::W] = $WPercentage;
    if($isXActive) $map[self::X] = $XPercentage;
    if($isYActive) $map[self::Y] = $YPercentage;
    if($isZActive) $map[self::Z] = $ZPercentage;

    asort($map);
    return key($map);    
}

Изменение: Исправлено неправильное sort(), вам нужно asort() чтобы поддерживать индекс.

  • 0
    при использовании asort ответ будет только на более высокий процент адаптера. Я хочу, например: AdapterY ≃ 40% транзакций, 40 из 100 запросов будут использовать этот адаптер, если вы понимаете, что я имею в виду.
  • 0
    Хорошо, вы устанавливаете процент загрузки вручную и хотите сбалансировать его на основе этого процента. Чем я совершенно не прав с моим ответом :)
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню