Към съдържанието

Управление на ресурсите

Queuety разделя управлението на ресурсите на четири основни слоя и допълнително, по избор, оразмеряване на пуловете.

Първият слой описва колко ресурсоемка е една единица работа. Вторият ограничава колко общо натоварване може да поеме едновременно една опашка или група доставчици. Третият определя колко може да изразходва едно изпълнение на работен поток. Четвъртият решава дали работникът да започне следващата поета задача веднага, или да я отложи, докато текущият процес и контейнер разполагат с достатъчно свободен капацитет.

Тези слоеве работят заедно. Обработчик може да посочи, че принадлежи към споделен пул с високи разходи, опашка може да запази ограничено количество претеглена работа за един доставчик, работен поток може да ограничи количеството такава работа, което е готов да създаде, а работникът пак може да откаже да започне още такава работа, когато текущият процес или контейнер вече е твърде близо до лимитите си.

Опишете разхода за една единица работа

Задачите, стъпките на работния поток и действията при влизане в състояние могат да задават едни и същи три подсказки за ресурсите:

  • concurrency_group
  • concurrency_limit
  • cost_units

concurrency_group и concurrency_limit описват общото натоварване на една последваща система. Ако няколко обработчика използват един и същ доставчик, API акаунт или клиент, те могат да използват една и съща група, за да не започват работниците твърде много задачи едновременно.

cost_units описва относителната тежест. Обновяването на кеша и голямото извикване към доставчик може и двете да са „една задача“, но не бива да се отчитат еднакво, когато бюджетът на работния поток или правило за допускане на работници решава дали е безопасно да започне още работа.

PHP
final class CallProviderStep implements \Queuety\Step
{
    public function handle( array $state ): array
    {
        // ...
    }

    public function config(): array
    {
        return [
            'concurrency_group' => 'providers',
            'concurrency_limit' => 3,
            'cost_units' => 5,
        ];
    }
}

Същата идея важи за задачите, които могат да се изпращат, чрез свойствата на класа, както и за отделните изпращания чрез PendingJob::concurrency_group() и PendingJob::cost_units().

Задаване на бюджети за споделени опашки и групи доставчици

Общото натоварване невинаги се свежда до прост брой едновременни изпълнения. Понякога скъпата част е общата тежест на вече изпълняваните задачи.

Queuety поддържа претеглени бюджети за опашки и групи. Бюджетите на опашките са обвързани с името на опашката. Бюджетите на групите са обвързани с concurrency_group, което позволява на несвързани обработчици да участват в един и същ общ лимит.

PHP
define( 'QUEUETY_RESOURCE_QUEUE_COST_BUDGETS', [
    'providers' => 20,
    'exports' => 8,
] );

define( 'QUEUETY_RESOURCE_GROUP_COST_BUDGETS', [
    'openai' => 12,
    'tenant:acme' => 6,
] );

Когато работникът поеме задача, той проверява активните редове processing, които вече принадлежат към тази опашка или група. Ако текущият разход плюс cost_units на поетата задача надхвърля конфигурирания бюджет, работникът освобождава задачата и опитва отново по-късно.

Това осигурява различен контрол от concurrency_limit. Доставчикът може да допуска три едновременни заявки, но въпреки това да запазва по-малко общи единици за разход за по-големи заявки, отколкото за по-малки.

Дръжте един работен поток в рамките на лимит

Бюджетите за работни потоци са полезни, когато проблемът не е една тежка задача, а изпълнение, което продължава да открива повече работа от предвиденото.

Това е често срещано в агентни системи. Планировчикът може многократно да преглежда един и същ скъп клон, да разделя работата на твърде много подзадачи или да продължава да стартира дъщерни работни потоци, като формално остава в рамките на обичайния модел за повторни опити.

Queuety предоставя ограничения на ниво работен поток за тази цел:

PHP
Queuety::workflow( 'research_run' )
    ->max_transitions( 20 )
    ->max_for_each_items( 12 )
    ->max_state_bytes( 32768 )
    ->max_cost_units( 40 )
    ->max_started_workflows( 8 )
    ->then( PlanResearchStep::class )
    ->for_each( 'tasks', ExecuteResearchTask::class, 'results' )
    ->dispatch();

max_cost_units() не позволява на изпълнението да изразходва повече претеглена работа от предвиденото. max_started_workflows() не позволява на родителски работен поток да се превърне в неограничено дърво от дъщерни изпълнения от най-високо ниво. Останалите предпазни ограничения също са важни, защото не всички излизащи извън контрол работни потоци са ресурсоемки по един и същ начин.

Статусът на работния поток показва конфигурираните ограничения и текущото потребление чрез публичния обект budget, така че изпълнението остава видимо, докато ограниченията са активни.

Позволете на работниците да отлагат задачи, когато процесът вече е претоварен

Дори когато метаданните и бюджетите на работния поток са конфигурирани добре, окончателното решение пак принадлежи на работния процес, който предстои да изпълни задачата.

Тук се намесва допускането според ресурсите. Преди да започне поета задача, Queuety може да провери:

  • общата група за паралелност на задачата
  • претеглените бюджети на опашката и групата доставчици
  • скорошната продължителност и историята на пиковото потребление на памет от обработчика
  • оставащия капацитет на паметта на текущия работник
  • оставащия капацитет на паметта на текущия контейнер или хост
  • оставащото времево ограничение за изпълнения в стил еднократно стартиране

Ако работникът вече е твърде близо до конфигурирания си лимит, Queuety освобождава задачата, вместо да започва работа, която вероятно няма да завърши чисто.

Това умишлено е консервативен подход. Не представлява цялостен планировчик на клъстер. Това е защитен слой, който помага на натоварен работник да избегне претоварването на процеса, в който работи, а когато има данни за паметта — и на контейнера или хоста около него.

Проверката на контейнера или хоста е по избор. Когато QUEUETY_RESOURCE_SYSTEM_MEMORY_AWARENESS е активирано, Queuety първо се опитва да прочете данните за паметта от cgroup, а при хостове с Linux преминава към /proc/meminfo. Ако няма надеждна системна моментна снимка, работникът продължава да използва локалните за процеса проверки.

Мащабирайте пуловете от работници, без да пренебрегвате капацитета

Фиксираните пулове от работници са лесни за разбиране, но изискват да изберете една стойност както за спокойните периоди, така и за пиковете.

Адаптивните пулове ви позволяват вместо това да зададете минимум и максимум:

Обвивка
wp queuety work --queue=providers --min-workers=2 --max-workers=6

Родителският процес поддържа поне минималния брой активни дъщерни процеси, увеличава броя им към максимума при нарастване на опашката от задачи, готови за поемане, и го намалява след период на тишина в опашката, равен на конфигурирания период на изчакване.

Увеличаването на броя все пак се съобразява с наличния капацитет. Ако е активирано следене на системната памет и родителският процес не вижда достатъчно свободна памет за още един пълен работник, пулът остава с текущия си размер, вместо да стартира още дъщерни процеси.

Реалистичен начин за комбиниране на слоевете

Представете си проучвателен работен поток, който планира извиквания към доставчици, стартира специализирани работни потоци и след това обобщава резултата.

Стъпката, която комуникира с доставчика, може да зададе cost_units и общ concurrency_group, така че множество работници да не претоварят един и същ доставчик на модели. Опашката може да запази претеглен бюджет за трафика към този доставчик. Родителският работен поток може да ограничи max_cost_units() и max_started_workflows(), така че планировчикът да не разраства изпълнението безкрайно. След това работникът пак може да отложи новопоето извикване към доставчик, ако скорошните данни за пиковото потребление на памет показват, че процесът или контейнерът вече е твърде близо до лимита си.

Така получавате четири отделни контроли:

  1. опишете тежестта на работата
  2. запазете общ капацитет за опашката или доставчика
  3. ограничете какво може да създаде едно изпълнение
  4. не позволявайте на натоварен работник да започва повече задачи от допустимото

Къде се намират подробните API

Тази страница е концептуален обзор.

За конкретните настройки:

  • Работници описва поведението при допускане и константите по време на изпълнение
  • CLI описва командите за фиксирани и адаптивни пулове от работници
  • Предпазни ограничения за работни потоци описва бюджетите за работни потоци
  • Задачи описва метаданните на задачите и обработчиците
  • Машини на състоянията описва метаданните за ресурсите на действията при състояния
  • API изброява конкретните методи и формите на върнатите стойности