
# Resurssien hallinta

Queuety jakaa resurssien hallinnan neljään keskeiseen kerrokseen, joiden lisäksi voidaan määrittää joukon koko.

Ensimmäinen kerros kuvaa yhden työyksikön kustannusta. Toinen rajoittaa, kuinka suuren yhteisen kuormituksen yksi jono tai palveluntarjoajaryhmä voi kantaa kerrallaan. Kolmas määrittää, kuinka paljon yksittäinen työnkulun suoritus saa kuluttaa. Neljäs ratkaisee, aloittaako työntekijä seuraavan otetun työn heti vai lykkääkö sitä, kunnes nykyisessä prosessissa ja säiliössä on riittävästi kapasiteettia.

Nämä kerrokset toimivat yhdessä. Käsittelijä voi ilmoittaa kuuluvansa paljon resursseja kuluttavaan yhteiseen joukkoon, jono voi varata yhdelle palveluntarjoajalle vain tietyn painotetun työmäärän, työnkulku voi rajoittaa, kuinka paljon tällaista työtä se luo, ja työntekijä voi silti kieltäytyä aloittamasta sitä enempää, jos nykyinen prosessi tai säiliö on jo liian lähellä rajojaan.

## Kuvaa yhden työyksikön kustannus

Työt, työnkulun vaiheet ja tilasiirtymien toiminnot voivat kaikki ilmoittaa samat kolme resurssivihjettä:

- `concurrency_group`
- `concurrency_limit`
- `cost_units`

`concurrency_group` ja `concurrency_limit` kuvaavat yhteistä kuormitusta yhdelle jatkojärjestelmälle. Jos useat käsittelijät käyttävät samaa palveluntarjoajaa, API-tiliä tai vuokralaista, ne voivat käyttää samaa ryhmää, jotta työntekijät eivät aloita liian montaa työtä kerralla.

`cost_units` kuvaa suhteellista painoa. Välimuistin päivitys ja suuri palveluntarjoajakutsu voivat kumpikin olla ”yksi työ”, mutta niiden ei pidä vaikuttaa samalla tavalla, kun työnkulun budjetti tai työntekijän pääsysääntö ratkaisee, onko uuden työn aloittaminen yhä turvallista.

```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,
        ];
    }
}
```

Sama ajatus koskee lähetettäviä töitä luokan ominaisuuksien kautta ja yksittäisiä lähetyksiä `PendingJob::concurrency_group()`- ja `PendingJob::cost_units()`-arvojen kautta.

## Jaettujen jonojen ja palveluntarjoajaryhmien budjetointi

Yhteinen kuormitus ei aina tarkoita yksinkertaista samanaikaisuuden määrää. Joskus kustannus syntyy käynnissä olevan työn yhteenlasketusta painosta.

Queuety tukee tätä painotettujen jono- ja ryhmäbudjettien avulla. Jonobudjetit määritetään jonon nimen perusteella. Ryhmäbudjetit määritetään `concurrency_group`-arvon perusteella, jolloin toisiinsa liittymättömätkin käsittelijät voivat kuulua samaan yhteiseen rajaan.

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

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

Kun työntekijä ottaa työn käsiteltäväksi, se tarkistaa aktiiviset `processing`-rivit, jotka kuuluvat kyseiseen jonoon tai ryhmään. Jos käynnissä olevien töiden kustannus lisättynä otetun työn `cost_units`-arvolla ylittäisi määritetyn budjetin, työntekijä vapauttaa työn ja yrittää myöhemmin uudelleen.

Tämä tarjoaa toisenlaisen hallintakeinon kuin `concurrency_limit`. Palveluntarjoaja voi sallia kolme samanaikaista pyyntöä ja silti varata suurille pyynnöille vähemmän kokonaiskustannusyksiköitä kuin pienille.

## Pidä yksi työnkulku rajojen sisällä

Työnkulun budjeteista on hyötyä, kun ongelmana ei ole yksittäinen raskas työ vaan suoritus, joka löytää jatkuvasti enemmän työtä kuin oli tarkoitus.

Tämä on tavallista agenttipohjaisissa järjestelmissä. Suunnittelija voi palata samaan kalliiseen haaraan, jakaa työn liian moneen alitehtävään tai käynnistää jatkuvasti uusia alityönkulkuja, vaikka tavallisen uudelleenyritysmallin rajoissa pysyttäisiinkin.

Queuety tarjoaa tähän työnkulkutason rajoitukset:

```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()` estää suoritusta kuluttamasta aiottua suurempaa painotettua työmäärää. `max_started_workflows()` estää ylätason työnkulkua muodostamasta rajatonta alisuoritusten puuta. Muutkin suojakaiteet ovat yhä tärkeitä, sillä kaikki hallitsemattomasti kasvavat työnkulut eivät kuluta resursseja samalla tavalla.

Työnkulun tila näyttää määritetyt rajat ja nykyisen käytön julkisen `budget`-hyötykuorman kautta, joten suoritusta voi tarkastella rajojen ollessa voimassa.

## Anna työntekijöiden lykätä työtä, kun prosessi on jo liian kuormitettu

Vaikka metatiedot ja työnkulun budjetit olisi määritetty hyvin, viimeisen päätöksen tekee silti työntekijäprosessi, joka on aloittamassa työn suorittamisen.

Tässä resurssitietoinen pääsynhallinta astuu kuvaan. Ennen otetun työn käynnistämistä Queuety voi tarkistaa seuraavat asiat:

- työn yhteinen samanaikaisuusryhmä
- painotetut jono- ja palveluntarjoajaryhmäbudjetit
- käsittelijän viimeaikainen suorituksen kesto ja huippumuistin käyttö
- nykyisen työntekijän jäljellä oleva muistikapasiteetti
- nykyisen säiliön tai isännän jäljellä oleva muistikapasiteetti
- kertaluonteisen suorituksen jäljellä oleva aikaraja

Jos työntekijä on jo liian lähellä määritettyä ylärajaa, Queuety vapauttaa työn sen sijaan, että aloittaisi työn, joka ei todennäköisesti valmistu ongelmitta.

Tämä ratkaisu on tarkoituksella varovainen. Se ei ole koko klusterin ajastin, vaan suojakerros, joka auttaa kuormitettua työntekijää välttämään käynnissä olevan prosessin ylikuormituksen ja muistimittausten ollessa käytettävissä myös ympäröivän säiliön tai isännän ylikuormituksen.

Säiliön tai isännän kapasiteettitarkistus on valinnainen. Kun `QUEUETY_RESOURCE_SYSTEM_MEMORY_AWARENESS` on käytössä, Queuety yrittää ensin lukea cgroup-muistitiedot ja käyttää varalla `/proc/meminfo`-tietoja Linux-isännillä. Jos luotettavaa järjestelmätason tilannekuvaa ei ole saatavilla, työntekijä käyttää silti prosessikohtaisia tarkistuksia.

## Skaalaa työntekijäjoukkoja kapasiteetti huomioiden

Kiinteitä työntekijäjoukkoja on helppo hahmottaa, mutta niissä on valittava sama määrä sekä hiljaisille ajoille että kuormituspiikeille.

Mukautuvissa joukoissa voit asettaa sen sijaan ala- ja ylärajan:

```bash
wp queuety work --queue=providers --min-workers=2 --max-workers=6
```

Yläprosessi pitää vähintään vähimmäismäärän aliprosesseja käynnissä, kasvattaa määrää enimmäismäärää kohti, kun käsiteltävissä oleva jono kasvaa, ja pienentää määrää, kun jono on ollut määritetyn joutoajan hiljainen.

Kasvattaminen huomioi yhä käytettävissä olevan kapasiteetin. Jos järjestelmämuistin seuranta on käytössä eikä yläprosessi näe riittävästi vapaata muistia yhden täysimittaisen työntekijän tarpeisiin, se pitää joukon nykyisessä koossa uusien aliprosessien käynnistämisen sijaan.

## Käytännön esimerkki kerrosten yhdistämisestä

Kuvitellaan tutkimustyönkulku, joka suunnittelee kutsuja palveluntarjoajille, käynnistää erikoistuneita työnkulkuja ja kokoaa sitten tuloksen.

Palveluntarjoajalle pyyntöjä lähettävä vaihe voi ilmoittaa `cost_units`-arvon ja yhteisen `concurrency_group`-ryhmän, jotta useat työntekijät eivät kuormita samaa mallipalveluntarjoajaa yhtä aikaa. Jono voi varata painotetun budjetin kyseiselle palveluntarjoajaliikenteelle. Ylätason työnkulku voi rajoittaa arvoja `max_cost_units()` ja `max_started_workflows()`, jotta suunnittelija ei voi kasvattaa suoritusta loputtomasti. Työntekijä voi silti lykätä juuri käsiteltäväksi otettua palveluntarjoajakutsua, jos viimeaikaiset huippumuistitiedot osoittavat prosessin tai säiliön olevan jo liian lähellä ylärajaa.

Tämä tarjoaa neljä erillistä hallintakeinoa:

1. kuvaa työn painoa
2. varaa jaetun jono- tai palveluntarjoajakapasiteetin
3. rajoita sitä, mitä yksi suoritus saa luoda
4. estä kuormitettua työntekijää aloittamasta liikaa töitä

## Mistä yksityiskohtaiset rajapinnat löytyvät

Tämä sivu on käsitteellinen yleiskatsaus.

Käytännön asetukset löytyvät seuraavilta sivuilta:

- [Workers](https://queuety.inline0.dev/fi/docs/features/workers) käsittelee hyväksymiskäyttäytymistä ja ajonaikaisia vakioita
- [CLI](https://queuety.inline0.dev/fi/docs/cli) käsittelee kiinteän ja mukautuvan työntekijäpoolin komentoja
- [Workflow Guardrails](https://queuety.inline0.dev/fi/docs/workflows/guardrails) käsittelee työnkulun budjetteja
- [Jobs](https://queuety.inline0.dev/fi/docs/jobs) käsittelee työn ja käsittelijän metatietoja
- [State Machines](https://queuety.inline0.dev/fi/docs/state-machines) käsittelee tilatoimintojen resurssien metatietoja
- [API](https://queuety.inline0.dev/fi/docs/api) luettelee tarkat metodit ja palautusarvojen muodot
