Treci la conținut

Lucrători

Lucrătorii sunt procese de lungă durată care interoghează baza de date pentru joburi în așteptare, le execută și avansează fluxurile de lucru. Comanda wp queuety work rulează în WP-CLI, în timp ce coada este revendicată direct din MySQL prin cel mai potrivit driver DB Queuety disponibil.

Pluginul instalează și o alternativă implicită WordPress cron, care rulează o dată pe minut, pentru mediile fără acces la shell. Această pagină descrie lucrătorii dedicați WP-CLI, modul de implementare recomandat pentru un volum mai mare de procesare.

Pornirea unui lucrător

Shell
wp queuety work

Aceasta pornește un singur lucrător pe coada default. Rulează într-o buclă: revendică un job, îl execută și repetă. Când coada este goală, așteaptă QUEUETY_WORKER_SLEEP secunde (implicit: 1) înainte de a o interoga din nou.

Opțiuni

Opțiune Descriere
--queue=<queue> Queue(s) de procesat, separate prin virgulă pentru ordonarea priorităților (implicit: default)
--once Procesează cel mult un job și iese
--workers=<n> Pornește N procese lucrătoare (necesită extensiile pcntl și posix)
--min-workers=<n> Numărul minim de lucrători pentru un grup adaptiv. Necesită --max-workers
--max-workers=<n> Numărul maxim de lucrători pentru un grup adaptiv
Shell
# Process a specific queue
wp queuety work --queue=emails

# Process at most one job and exit
wp queuety work --once

# Run 4 concurrent workers
wp queuety work --workers=4

# Scale between 2 and 6 workers as backlog changes
wp queuety work --queue=providers --min-workers=2 --max-workers=6

Priorități pentru mai multe cozi

Un singur lucrător poate procesa mai multe cozi în ordinea priorităților. Transmiteți o listă de nume de cozi separate prin virgulă către --queue:

Shell
wp queuety work --queue=critical,default,low

Lucrătorul încearcă să revendice câte un job din fiecare coadă, în ordinea listată. Verifică mai întâi critical. Dacă critical are un job, îl procesează. Dacă critical este goală, trece la default, apoi la low. Astfel, cozile cu prioritate mai mare se golesc întotdeauna înaintea celor cu prioritate mai mică.

Cum funcționează ordonarea priorităților

La fiecare iterație, lucrătorul încearcă să revendice un job din prima coadă din listă. Dacă acea coadă este goală sau suspendată, trece la următoarea și continuă până când găsește un job sau epuizează lista. Dacă nu găsește niciun job, așteaptă și încearcă din nou. Acesta este un model strict de priorități, ceea ce înseamnă că un flux constant de joburi critical va împiedica procesarea joburilor din cozile default și low. Dacă cozile cu prioritate mai mică au nevoie de un volum de procesare garantat, folosiți lucrători dedicați.

Utilizarea mai multor cozi în PHP

Metodele Worker::run() și Worker::flush() acceptă fie un șir, fie un tablou:

PHP
// Comma-separated string
Queuety::worker()->run( 'critical,default,low' );

// Array
Queuety::worker()->run( [ 'critical', 'default', 'low' ] );

// flush() also supports multi-queue
$count = Queuety::worker()->flush( 'critical,default,low' );

Strategii de implementare

Lucrătorii dedicați fiecărei cozi vă oferă control deplin asupra concurenței și izolării. Fiecare coadă primește propriul process(es) de lucrători și nu poate fi împiedicată de celelalte cozi:

Ini
[program:queuety-critical]
command=wp queuety work --queue=critical
numprocs=4

[program:queuety-default]
command=wp queuety work --queue=default
numprocs=2

[program:queuety-low]
command=wp queuety work --queue=low
numprocs=1

Ordonarea priorităților cu un singur lucrător este mai simplu de gestionat și funcționează bine când cozile cu prioritate mai mică pot tolera întârzieri:

Ini
[program:queuety-worker]
command=wp queuety work --queue=critical,default,low
numprocs=2

Puteți combina și cele două abordări: lucrători dedicați pentru critical, care garantează volumul de procesare, și un lucrător cu cozi ordonate după prioritate pentru toate celelalte:

Ini
[program:queuety-critical]
command=wp queuety work --queue=critical
numprocs=2

[program:queuety-fallback]
command=wp queuety work --queue=default,low
numprocs=2

Admiterea în funcție de resurse

Lucrătorii fac mai mult decât să revendice următorul rând în așteptare. Înainte de pornirea unui job revendicat, Queuety poate aplica verificări generale de admitere pe baza grupului de concurență al jobului și a profilului recent de execuție pentru acel handler.

Pentru modelul extins, inclusiv modul în care se leagă de metadatele joburilor și bugetele fluxurilor de lucru, consultați Gestionarea resurselor.

Un grup de concurență stabilește o limită comună pentru mai mulți handleri sau clase de joburi. Dacă atribuiți același grup și aceeași limită mai multor furnizori costisitori, un lucrător va elibera lucrările revendicate recent în loc să le pornească atunci când grupul este saturat. Astfel, cozile independente nu vor suprasolicita același sistem din aval doar pentru că există mai mulți lucrători inactivi.

Jurnalele recente de execuție contribuie și ele la un profil simplu de admitere. Când admiterea în funcție de resurse este activată, Queuety analizează durata medie recentă și memoria maximă pentru handlerul pe care urmează să-l execute. Dacă lucrătorul curent este deja aproape de limita de memorie configurată, coada sau grupul de furnizori a atins deja bugetul ponderat, containerul curent nu pare să aibă suficientă memorie disponibilă pentru profilul observat al handlerului sau o execuție de tip --once se apropie de limita de timp, Queuety amână jobul în loc să pornească o lucrare care probabil nu se va încheia fără probleme.

Activați această politică în definiția lucrării, nu în comanda lucrătorului:

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

Aceleași metadate pot fi atașate claselor de joburi care pot fi distribuite, prin proprietăți publice, sau unei distribuiri individuale prin PendingJob::concurrency_group() și PendingJob::cost_units().

Profilul de admitere de pe partea lucrătorului este controlat de aceste constante:

Constantă Descriere
QUEUETY_RESOURCE_ADMISSION Activează sau dezactivează verificările de admitere bazate pe profil
QUEUETY_RESOURCE_PROFILE_WINDOW_MINUTES Intervalul retrospectiv folosit la construirea profilurilor recente ale handlerelor
QUEUETY_RESOURCE_PROFILE_TTL Durata de păstrare în cache a profilurilor recente ale handlerelor
QUEUETY_RESOURCE_MEMORY_HEADROOM_MB Rezerva de memorie necesară înainte de admiterea unui alt job
QUEUETY_RESOURCE_SYSTEM_MEMORY_AWARENESS Activează sau dezactivează verificările aproximative ale memoriei containerului sau gazdei
QUEUETY_RESOURCE_SYSTEM_MEMORY_HEADROOM_MB Rezerva de memorie a sistemului necesară înainte de admiterea unui alt job
QUEUETY_RESOURCE_QUEUE_COST_BUDGETS Bugete de cost ponderat, grupate după numele cozii
QUEUETY_RESOURCE_GROUP_COST_BUDGETS Bugete de cost ponderat, grupate după concurrency_group
QUEUETY_RESOURCE_TIME_HEADROOM_MS Rezerva de timp pentru execuțiile lucrătorilor care rulează o singură dată

Ciclul de viață al lucrătorului

Un lucrător se oprește în mod controlat, după ce își termină jobul curent, dacă este îndeplinită oricare dintre aceste condiții:

Condiție Configurare
Numărul maxim de joburi procesate QUEUETY_WORKER_MAX_JOBS (implicit: 1000)
Memorie maximă depășită QUEUETY_WORKER_MAX_MEMORY (implicit: 128 MB)

După oprire, lucrătorul iese fără erori. În producție, un manager de procese îl repornește automat.

Semnalele nu sunt încă gestionate în mod controlat (#4). Un singur proces wp queuety work nu instalează niciun handler de semnale, așa că SIGTERM sau SIGINT (Ctrl+C) îl oprește imediat, chiar și în mijlocul unui job. Jobul rămâne în starea processing până când recuperarea joburilor expirate îl resetează după QUEUETY_STALE_TIMEOUT secunde, așadar asigurați-vă că handlerii pot fi reîncercați în siguranță. Un grup de lucrători transmite SIGTERM proceselor copil, însă acestea nu îl tratează, astfel că grupul continuă să ruleze până când se opresc din unul dintre motivele de mai sus. Când trebuie să opriți un grup, configurați managerul de procese cu un timp de așteptare la oprire, după care trimite SIGKILL.

Concurența între mai mulți lucrători

Opțiunea --workers=N pornește N procese copil folosind pcntl_fork(). Fiecare copil creează propria conexiune la baza de date și procesează joburi independent. Procesul părinte monitorizează copiii și îi repornește pe cei care se blochează.

Shell
wp queuety work --queue=default --workers=4

Cerințe: Extensiile pcntl și posix PHP trebuie instalate (fără pcntl, comanda eșuează cu „pcntl extension is required for --workers=N.”), iar fiecare copil folosește propria conexiune la baza de date, deci setarea MySQL max_connections trebuie să fie suficientă pentru grup. Grupurile adaptive (--min-workers/--max-workers) au aceleași cerințe.

Grupuri adaptive de lucrători

Grupurile adaptive mențin un număr minim de lucrători pregătiți, apoi cresc sau scad în intervalul configurat:

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

Procesul părinte monitorizează volumul de joburi eligibile pentru revendicare din setul de cozi selectat și ajustează numărul de procese copil pentru a-l aproxima, fără a depăși maximul configurat. Când coada se liniștește, grupul așteaptă perioada de grație pentru inactivitate înainte de a reduce numărul de lucrători, astfel încât creșterile scurte de volum să nu modifice imediat lista de procese.

Extinderea grupului rămâne prudentă. Când Queuety poate citi datele de utilizare a memoriei containerului sau gazdei, refuză să adauge procese copil dacă memoria disponibilă nu este suficientă pentru încă un lucrător cu necesarul său complet de resurse.

Bucla de scalare din procesul părinte este controlată de:

Constantă Descriere
QUEUETY_WORKER_POOL_SCALE_INTERVAL Cât de des ajustează procesul părinte dimensiunea grupului
QUEUETY_WORKER_POOL_IDLE_GRACE Cât timp trebuie să rămână inactiv volumul de joburi înainte de reducerea grupului

Recuperarea joburilor expirate

Dacă un lucrător se blochează în timp ce procesează un job, jobul rămâne în starea processing. Un lucrător de lungă durată verifică aproximativ o dată pe minut dacă există joburi aflate în starea processing de mai mult de QUEUETY_STALE_TIMEOUT secunde. Un job expirat care mai are încercări disponibile este reîncercat după întârzierea configurată; unul care și-a epuizat toate încercările este îngropat, iar fluxul său de lucru este marcat ca eșuat. Lucrătorii --once și alternativa WP-Cron nu efectuează această verificare.

Recuperați manual joburile expirate:

Shell
wp queuety recover

Modul de golire

Procesează toate joburile în așteptare și iese. Util pentru testare sau procesarea loturilor o singură dată:

Shell
wp queuety flush
wp queuety flush --queue=emails

Implementarea în producție

Pentru producție, folosiți un manager de procese care menține lucrătorii în execuție. Iată două metode frecvente.

Supervisord

Ini
[program:queuety-default]
command=wp queuety work --queue=default
directory=/var/www/html
autostart=true
autorestart=true
numprocs=2
process_name=%(program_name)s_%(process_num)02d
stdout_logfile=/var/log/queuety-default.log
stderr_logfile=/var/log/queuety-default-error.log

[program:queuety-emails]
command=wp queuety work --queue=emails
directory=/var/www/html
autostart=true
autorestart=true
numprocs=1
stdout_logfile=/var/log/queuety-emails.log
stderr_logfile=/var/log/queuety-emails-error.log

Systemd

Ini
[Unit]
Description=Queuety Worker (default queue)
After=mysql.service

[Service]
Type=simple
User=www-data
WorkingDirectory=/var/www/html
ExecStart=/usr/local/bin/wp queuety work --queue=default
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

Activați și porniți:

Shell
sudo systemctl enable queuety-worker
sudo systemctl start queuety-worker

Sfaturi pentru implementare

Rulați lucrători separați pentru cozi distincte atunci când aveți nevoie de o izolare mai bună. Folosiți --workers=N când volumul de lucru este limitat de CPU și preferați lucrători monitorizați individual când volumul de lucru implică mai ales operațiuni de I/O. Setați QUEUETY_WORKER_MAX_JOBS dacă doriți reporniri periodice care să elibereze memoria și monitorizați numărul de buried prin webhookuri sau metrice.