Przejdź do treści

Procesy robocze

Procesy robocze to długotrwale działające procesy, które odpytują bazę danych o oczekujące zadania, wykonują je i posuwają przepływy pracy naprzód. Polecenie wp queuety work działa wewnątrz WP-CLI, a kolejka jest pobierana bezpośrednio z MySQL za pośrednictwem najlepszego dostępnego sterownika DB Queuety.

Wtyczka instaluje też domyślny mechanizm awaryjny WordPress cron uruchamiany raz na minutę, przeznaczony dla środowisk bez dostępu do powłoki. Ta strona opisuje dedykowane procesy robocze WP-CLI, zalecany tryb wdrożenia zapewniający większą przepustowość.

Uruchamianie procesu roboczego

Powłoka
wp queuety work

Uruchamia to pojedynczy proces roboczy dla kolejki default. Działa on w pętli: pobiera zadanie, wykonuje je i powtarza cykl. Gdy kolejka jest pusta, czeka QUEUETY_WORKER_SLEEP sekund (domyślnie: 1), a następnie ponownie odpytuje kolejkę.

Opcje

Opcja Opis
--queue=<queue> Queue(s) do przetworzenia; nazwy oddzielone przecinkami ustalają kolejność priorytetów (domyślnie: default)
--once Przetwórz najwyżej jedno zadanie i zakończ działanie
--workers=<n> Rozgałęź procesy robocze na N procesów (wymaga rozszerzeń pcntl i posix)
--min-workers=<n> Minimalna liczba procesów roboczych w puli adaptacyjnej. Wymaga --max-workers
--max-workers=<n> Maksymalna liczba procesów roboczych w puli adaptacyjnej
Powłoka
# 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

Priorytety wielu kolejek

Pojedynczy proces roboczy może przetwarzać wiele kolejek w kolejności priorytetów. Przekaż do --queue rozdzieloną przecinkami listę nazw kolejek:

Powłoka
wp queuety work --queue=critical,default,low

Proces roboczy próbuje pobrać zadanie z każdej kolejki w podanej kolejności. Najpierw sprawdza critical. Jeśli critical zawiera zadanie, przetwarza je. Jeśli critical jest pusta, przechodzi do default, a następnie do low. Oznacza to, że kolejki o wyższym priorytecie są zawsze opróżniane przed tymi o niższym priorytecie.

Jak działa kolejność priorytetów

W każdej iteracji proces roboczy próbuje pobrać zadanie z pierwszej kolejki na liście. Jeśli kolejka jest pusta lub wstrzymana, przechodzi do następnej i kontynuuje, aż znajdzie zadanie albo sprawdzi całą listę. Jeśli nigdzie nie znajdzie zadania, czeka i ponawia próbę. To ścisły model priorytetów, co oznacza, że stały napływ zadań critical zagłodzi kolejki default i low. Jeśli kolejki o niższym priorytecie mają mieć gwarantowaną przepustowość, użyj dedykowanych procesów roboczych.

Korzystanie z wielu kolejek w PHP

Metody Worker::run() i Worker::flush() przyjmują ciąg znaków lub tablicę:

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' );

Strategie wdrażania

Dedykowane procesy robocze dla każdej kolejki zapewniają pełną kontrolę nad współbieżnością i izolacją. Każda kolejka ma własny proces roboczy process(es), więc inne kolejki nie mogą go zagłodzić:

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

Kolejność priorytetów w pojedynczym procesie roboczym jest łatwiejsza w zarządzaniu i sprawdza się, gdy kolejki o niższym priorytecie mogą tolerować opóźnienia:

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

Możesz też połączyć oba podejścia: użyć dedykowanych procesów roboczych dla critical, aby zagwarantować przepustowość, a dla pozostałych kolejek procesu roboczego z kolejnością priorytetów:

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

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

Przydzielanie zasobów z ich uwzględnieniem

Procesy robocze robią więcej niż tylko pobierają kolejny oczekujący wiersz. Przed rozpoczęciem pobranego zadania Queuety może zastosować wstępne kontrole dopuszczenia na podstawie grupy współbieżności zadania i niedawnego profilu wykonania tego obsługującego je kodu.

Więcej informacji o całym modelu i jego powiązaniu z metadanymi zadań oraz limitami przepływów pracy znajdziesz w sekcji Zarządzanie zasobami.

Grupa współbieżności wyznacza wspólny limit dla kilku programów obsługi lub klas zadań. Jeśli kilka kosztownych dostawców przypiszesz do tej samej grupy i limitu, proces roboczy zwolni nowo pobrane zadanie zamiast je uruchamiać, gdy grupa osiągnie limit. Dzięki temu niezależne kolejki nie przeciążą jednego systemu podrzędnego tylko dlatego, że kilka procesów roboczych jest bezczynnych.

Niedawne dzienniki wykonania służą też do tworzenia prostego profilu dopuszczania. Gdy ta funkcja jest włączona, Queuety sprawdza niedawny średni czas trwania i szczytowe zużycie pamięci programu obsługi, który ma uruchomić. Jeśli bieżący proces roboczy zbliża się już do skonfigurowanego limitu pamięci, kolejka lub grupa dostawców osiągnęła już swój ważony budżet, bieżący kontener nie ma dość wolnej pamięci na podstawie zaobserwowanego profilu programu obsługi albo uruchomienie w stylu --once zbliża się do limitu czasu, Queuety odracza zadanie zamiast rozpoczynać pracę, która prawdopodobnie nie zakończy się poprawnie.

Zasady włączasz w definicji zadania, a nie w poleceniu procesu roboczego:

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

Te same metadane można dołączyć do klas zadań możliwych do wysłania, używając właściwości publicznych, albo do pojedynczego wysłania za pomocą PendingJob::concurrency_group() i PendingJob::cost_units().

Profile dopuszczania po stronie procesu roboczego kontrolują następujące stałe:

Stała Opis
QUEUETY_RESOURCE_ADMISSION Włączanie lub wyłączanie kontroli dopuszczania na podstawie profilu
QUEUETY_RESOURCE_PROFILE_WINDOW_MINUTES Zakres czasu uwzględniany przy tworzeniu niedawnych profili programów obsługi
QUEUETY_RESOURCE_PROFILE_TTL Czas TTL pamięci podręcznej niedawnych profili programów obsługi
QUEUETY_RESOURCE_MEMORY_HEADROOM_MB Rezerwa pamięci przed dopuszczeniem kolejnego zadania
QUEUETY_RESOURCE_SYSTEM_MEMORY_AWARENESS Włączanie lub wyłączanie przybliżonych kontroli pamięci kontenera lub hosta
QUEUETY_RESOURCE_SYSTEM_MEMORY_HEADROOM_MB Rezerwa pamięci systemowej przed dopuszczeniem kolejnego zadania
QUEUETY_RESOURCE_QUEUE_COST_BUDGETS Ważone budżety kosztów według nazwy kolejki
QUEUETY_RESOURCE_GROUP_COST_BUDGETS Ważone budżety kosztów według concurrency_group
QUEUETY_RESOURCE_TIME_HEADROOM_MS Rezerwa czasu dla jednorazowych uruchomień procesów roboczych

Cykl życia procesu roboczego

Proces roboczy zatrzymuje się poprawnie po zakończeniu bieżącego zadania, gdy spełniony jest jeden z następujących warunków:

Warunek Konfiguracja
Maksymalna liczba przetworzonych zadań QUEUETY_WORKER_MAX_JOBS (domyślnie: 1000)
Przekroczony limit pamięci QUEUETY_WORKER_MAX_MEMORY (domyślnie: 128 MB)

Po zatrzymaniu proces roboczy kończy działanie bez błędów. W środowisku produkcyjnym menedżer procesów uruchamia go ponownie automatycznie.

Obsługa sygnałów nie jest jeszcze poprawna (#4). Pojedynczy proces wp queuety work nie instaluje obsługi sygnałów, więc SIGTERM lub SIGINT (Ctrl+C) kończy go natychmiast, nawet w trakcie zadania. Zadanie pozostaje w stanie processing do czasu, aż odzyskiwanie nieaktualnych zadań zresetuje je po QUEUETY_STALE_TIMEOUT sekundach, dlatego programy obsługi powinny bezpiecznie znosić ponowne próby. Pula procesów roboczych przekazuje SIGTERM swoim procesom potomnym, ale te nie reagują na niego, więc pula działa dalej, dopóki nie zostaną zatrzymane z jednego z wymienionych powodów. Gdy trzeba zatrzymać pulę, ustaw w menedżerze procesów limit czasu zatrzymania, po którym wyśle SIGKILL.

Współbieżność wielu procesów roboczych

Flaga --workers=N rozgałęzia N procesów potomnych za pomocą pcntl_fork(). Każdy proces potomny nawiązuje własne połączenie z bazą danych i niezależnie przetwarza zadania. Proces nadrzędny monitoruje procesy potomne i uruchamia ponownie te, które ulegną awarii.

Powłoka
wp queuety work --queue=default --workers=4

Wymagania: Rozszerzenia pcntl i posix PHP muszą być zainstalowane (bez pcntl polecenie kończy się błędem „pcntl extension is required for --workers=N.”). Każdy proces potomny używa własnego połączenia z bazą danych, więc ustawienie MySQL max_connections musi uwzględniać pulę. Pule adaptacyjne (--min-workers/--max-workers) mają te same wymagania.

Adaptacyjne pule procesów roboczych

Pule adaptacyjne utrzymują minimalną liczbę gotowych procesów roboczych, a następnie zwiększają ją i zmniejszają w skonfigurowanym zakresie:

Powłoka
wp queuety work --queue=providers --min-workers=2 --max-workers=6

Proces nadrzędny obserwuje liczbę zadań gotowych do pobrania w wybranych kolejkach i dostosowuje liczbę procesów potomnych do zaległości, nie przekraczając skonfigurowanego maksimum. Gdy w kolejce robi się spokojnie, pula czeka przez określony czas bezczynności przed zmniejszeniem rozmiaru, aby krótkie skoki obciążenia nie powodowały natychmiastowych zmian listy procesów.

Zwiększanie skali jest nadal ostrożne. Gdy Queuety może odczytać dane o pamięci kontenera lub hosta, nie dodaje kolejnych procesów potomnych, jeśli nie ma dość wolnej pamięci na pełny zestaw zasobów kolejnego procesu roboczego.

Pętlę skalowania po stronie procesu nadrzędnego kontrolują:

Stała Opis
QUEUETY_WORKER_POOL_SCALE_INTERVAL Jak często proces nadrzędny uzgadnia rozmiar puli
QUEUETY_WORKER_POOL_IDLE_GRACE Jak długo zaległości muszą pozostawać bez zmian, zanim pula zmniejszy rozmiar

Odzyskiwanie nieaktualnych zadań

Jeśli proces roboczy ulegnie awarii podczas przetwarzania zadania, zadanie pozostaje w stanie processing. Długotrwale działający proces roboczy mniej więcej raz na minutę sprawdza, czy są zadania, które pozostają w stanie processing dłużej niż QUEUETY_STALE_TIMEOUT sekund. Nieaktualne zadanie, któremu pozostały próby, jest ponawiane po upływie czasu oczekiwania; zadanie, które wykorzystało wszystkie próby, trafia do archiwum, a jego przepływ pracy zostaje oznaczony jako nieudany. Procesy robocze --once i mechanizm awaryjny WP-Cron nie wykonują tego sprawdzenia.

Odzyskaj nieaktualne zadania ręcznie:

Powłoka
wp queuety recover

Tryb opróżniania

Przetwórz wszystkie oczekujące zadania i zakończ działanie. Przydatne do testowania lub jednorazowego przetwarzania wsadowego:

Powłoka
wp queuety flush
wp queuety flush --queue=emails

Wdrożenie produkcyjne

W środowisku produkcyjnym użyj menedżera procesów, aby procesy robocze działały bez przerwy. Oto dwa popularne sposoby.

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

Włącz i uruchom:

Powłoka
sudo systemctl enable queuety-worker
sudo systemctl start queuety-worker

Wskazówki dotyczące wdrażania

Uruchamiaj osobne procesy robocze dla poszczególnych kolejek, gdy potrzebujesz lepszej izolacji. Użyj --workers=N, gdy obciążenie ogranicza procesor, a przy obciążeniu związanym głównie z operacjami wejścia-wyjścia preferuj osobne nadzorowane procesy robocze. Ustaw QUEUETY_WORKER_MAX_JOBS, jeśli chcesz okresowo uruchamiać procesy ponownie, aby zwolnić pamięć, i obserwuj liczbę buried w webhookach lub metrykach.