Jak wewnętrznie działa interfejs API wsadowego?


19

Pewnego dnia natknąłem się na problem z przekroczeniem limitu czasu podczas migracji i zacząłem się zastanawiać, jak Batch API działa wewnętrznie.

Rozumiem, że w najprostszej postaci przekażesz tablicę wartości (na przykład nids) i funkcję do działania na tych wartościach. Wsadowy interfejs API przetwarza następnie stałą liczbę tych wartości przy każdym żądaniu, aż do jego zakończenia.

Gdy partia jest uruchomiona, strona wydaje się używać żądań Ajax, aby pokazać postęp operacji wsadowej (% wykonanych i wiadomości). Zakładam, że czeka, aż żądanie zakończy się, aby zaktualizować postęp, a następnie natychmiast rozpocznie następne żądanie?

Jeśli strona z żądaniem wsadowym zostanie zamknięta, czy przetwarzanie wsadowe zostanie zatrzymane? Czy uruchomi się ponownie, gdy ten sam adres URL zostanie ponownie otwarty? Moduł migracji czasami kontynuuje, ale prawdopodobnie używa kolejek?

Odpowiedzi:


40

Tak działa partia (na podstawie mojego zrozumienia)

1. Zainicjuj

  1. Zainicjuj przetwarzanie wsadowe. Na podstawie konfiguracji klientów (przeglądarek), czy JavaScript jest włączony, czy nie.
  2. Klienci z włączoną obsługą JavaScript są identyfikowani przez plik cookie „has_js” w pliku drupal.js. Jeśli podczas sesji przeglądarki bieżącego użytkownika nie odwiedzono strony obsługującej JavaScript, zwracana jest wersja inna niż JavaScript.
  3. Jeśli włączona jest obsługa JavaScript, Batch korzysta z żądania ajax, aby połączenie pozostało aktywne .
  4. Jeśli JavaScript nie jest włączony, Batch używa metatagu w html do regularnych interwałów odświeżania, aby utrzymać połączenie przy życiu przez żądanie.

(W ten sposób pasek postępu jest aktualizowany o postępie wykonanego zadania.)

Proces wsadowy

  1. Aby rozpocząć proces, Batch tworzy kolejkę i dodaje wszystkie operacje (funkcje i argumenty) zdefiniowane w tablicy wsadowej, takie jak:

    $batch = array (
    'operations' => array(
      array('batch_example_process', array($options1, $options2)),
      array('batch_example_process', array($options3, $options4)),
      ),
    'finished' => 'batch_example_finished',
    'title' => t('Processing Example Batch'),
    'init_message' => t('Example Batch is starting.'),
    'progress_message' => t('Processed @current out of @total.'),
    'error_message' => t('Example Batch has encountered an error.'),
    'file' => drupal_get_path('module', 'batch_example') . '/batch_example.inc',
    );

    Dodatkowo przypisuje również identyfikator partii, który jest unikalny we wszystkich partiach.

  2. Teraz wywołania Batch przejmują kolejno pozycje Kolejki i wykonują funkcję zdefiniowaną za pomocą zdefiniowanych w niej argumentów.

  3. Jest to kluczowa część, funkcja (operacja), która implementuje operację wsadową, powinna porcjować dane i przetwarzać je bardzo skutecznie, pamiętając o limicie pamięci PHP, Limit czasu . Niezastosowanie się do tego spowoduje problem.

Pewnego dnia natrafiłem na problem z przekroczeniem limitu czasu podczas migracji i zacząłem się zastanawiać, jak działa wsadowy interfejs API.

Funkcja partii

Funkcje wdrażające Batch powinny bardzo ostrożnie podchodzić do następujących rzeczy,

  • Liczba elementów w ramach operacji do przetworzenia, np.

    if (!isset($context['sandbox']['progress'])) {
    $context['sandbox']['progress'] = 0;
    $context['sandbox']['current_node'] = 0;
    $context['sandbox']['max'] = db_result(db_query('SELECT COUNT(DISTINCT nid) FROM {node}'));
    }
  • Ograniczenie liczby elementów do przetworzenia w jednym wywołaniu funkcji, np. Ustawienie limitu,

    // For this example, we decide that we can safely process 5 nodes at a time without a timeout.
    $limit = 5;
  • Zaktualizuj proces przetwarzania końcowego, np.

    // Update our progress information.
        $context['sandbox']['progress']++;
        $context['sandbox']['current_node'] = $node->nid;
        $context['message'] = t('Now processing %node', array('%node' => $node->title));
  • Informowanie silnika partii, czy partia jest ukończona, czy nie,

    // Inform the batch engine that we are not finished,
    // and provide an estimation of the completion level we reached.
    if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
      $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
     }

Większość powyższych punktów zajmuje się operacjami wsadowymi Drupala, jeśli zostaną pominięte w funkcji implementacji. Ale zawsze najlepiej jest zdefiniować w funkcji implementacyjnej

Batch Finished callback

  • Jest to ostatnie wywołanie zwrotne, gdy jest zdefiniowane w tablicy wsadowej. Zwykle raport o tym, ile przetworzono itp.

ODPOWIEDZI

Jeśli strona z żądaniem wsadowym zostanie zamknięta, czy przetwarzanie wsadowe zostanie zatrzymane? Czy uruchomi się ponownie, gdy ten sam adres URL zostanie ponownie otwarty? Moduł migracji czasami kontynuuje, ale prawdopodobnie używa kolejek?

Tak, najlepiej byłoby uruchomić ponownie partię i jak wspomniano powyżej, jest on oparty na implementowanej funkcji.

Aby rozwiązać problem przekroczenia limitu czasu PHP, użyj pakietu wsadowego Drush, który jest dostępny w module migracji, ale najpierw wykop funkcje wsadowe migracji i spróbuj podzielić dane przetwarzania.


1
Wspaniałe przejście. Chciałbym również zauważyć, że partia zaczyna przetwarzanie podczas, co, przynajmniej dla użytkownika, wydaje się być „Inicjowaniem”. ekran. Oznacza to, że jeśli skonfigurowanie zajmie 4 sekundy i 10 sekund na przetworzenie pierwszego elementu partii, wówczas użytkownik zobaczy proces „Inicjalizacja”. przez czternaście sekund w tym przykładzie. Ma to sens, ponieważ pierwszy nieinicjalny komunikat ekranowy jest „n zakończony”, co zadziałałoby dopiero po przetworzeniu niektórych. Jeśli to źle, popraw mnie!
texas-bronius

Również z mojego doświadczenia. Jeśli opuścisz stronę, trwająca operacja wsadowa / porcja nadal będzie zużywać zasoby, dopóki się nie zakończy. Nie uruchamia już więcej zadania wsadowego, ale wykonuje bieżące.
Elijah Lynn

10

Jeśli strona z żądaniem wsadowym zostanie zamknięta, czy przetwarzanie wsadowe zostanie zatrzymane?

Tak, zostanie zatrzymany.

Czy uruchomi się ponownie, gdy ten sam adres URL zostanie ponownie otwarty? Moduł migracji czasami kontynuuje, ale prawdopodobnie używa kolejek?

Jak powiedział Dinesh, zależy to od implementacji.

Powinieneś uruchomić migrację za pomocą drush, ponieważ

Drush działa w wierszu poleceń i nie podlega żadnym ograniczeniom czasowym (w szczególności nie obowiązuje maksymalny czas wykonania PHP). Tak więc po uruchomieniu procesu migracji za pośrednictwem drush, po prostu uruchamia się i działa aż do zakończenia.

Podczas uruchamiania procesów przez interfejs sieciowy obowiązuje PHP max_execution_time (zwykle 30 sekund, jeśli nie mniej). Dlatego w przypadku długotrwałych procesów musimy użyć interfejsu API usługi Batch, który zarządza podziałem procesu na wiele żądań. Tak więc proces migracji rozpocznie się, będzie trwał około 25 sekund, a następnie zatrzyma się i pozwoli interfejsowi API usługi Batch wygenerować nowe żądanie strony, w którym proces migracji zostanie ponownie uruchomiony, ad infinitum.

Rozumiejąc to, dlaczego Drush jest lepszy?

Jest szybsze

Interfejs API usługi Batch wprowadza wiele narzutów - wyłączanie i ponowne wywoływanie żądań stron, proces migracji musi zostać ponownie uruchomiony przez wszystkie niezbędne konstruktory, przywrócone połączenia z bazami danych i ponownie uruchomione zapytania itp. I w przypadku częściowego importu musi wybrać tam, gdzie zostało przerwane - jeśli zaimportowanych zostało 500 pierwszych rekordów źródłowych, musi znaleźć 501. rekord. W zależności od formatu źródłowego i sposobu jego zbudowania może to być skalowane lub nie - jeśli używasz znaków wysokiej wody ze źródłem SQL, samo zapytanie może wyeliminować wcześniejsze rekordy i rozpocząć od miejsca, w którym zostało przerwane. Jeśli nie, Migrate musi przewijać dane źródłowe w poszukiwaniu pierwszego niezaimportowanego rekordu. Mając, powiedzmy, duży plik XML jako źródło,

Jest bardziej niezawodny

Uruchamianie migracji za pomocą przeglądarki dodaje pulpit i lokalne połączenie internetowe jako punkty awarii. Błąd sieciowy, gdy interfejs API usługi Batch przechodzi do żądania następnej strony, awaria przeglądarki, przypadkowe zamknięcie niewłaściwej karty lub okna może wszystko zakłócić migrację. Praca w pogotowiu zmniejsza liczbę ruchomych części - eliminujesz czynniki związane z komputerem i lokalnym połączeniem internetowym.

To jest bardziej pomocne

Jeśli coś pójdzie nie tak podczas działania w Drush, jeśli pojawią się jakieś przydatne komunikaty o błędach, zobaczysz je. Błędy przy korzystaniu z Batch API często zostają połknięte, a wszystko, co widzisz, to całkowicie bezużyteczne „Żądanie HTTP AJAX zakończyło się nieprawidłowo. Pojawiają się informacje o debugowaniu. Ścieżka: / batch? Id = 901 & op = do StatusText: ResponseText: ReadyState: 4”.

Więcej informacji na ten temat można znaleźć tutaj .

W międzyczasie, jeśli chcesz uruchomić pakiet, nawet jeśli okno przeglądarki jest zamknięte, rozważ moduł Przetwarzanie w tle . Ma podmoduł Background Batch, który załatwia sprawę .

Moduły te przejmują istniejące API Batch i uruchamiają zadania wsadowe w procesie w tle. Oznacza to, że jeśli opuścisz stronę partii, zadania będą kontynuowane, a później możesz powrócić do wskaźnika postępu.


wow, użycie drusha do migracji spowodowało ogromną poprawę. Muszę przeprowadzić migrację do działającej witryny, co znacznie zmniejsza obciążenie systemu! Dziękuję Ci!
Uwe

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.