Wie funktioniert die Batch-API intern?


19

Ich bin neulich auf ein Timeout-Problem mit der Migration gestoßen und habe mich gefragt, wie die Batch-API intern funktioniert.

So wie ich es verstehe, übergeben Sie in der einfachsten Form ein Array von Werten (z. B. NIDs) und eine Funktion, mit der diese Werte verarbeitet werden können. Die Batch-API verarbeitet dann eine feste Anzahl dieser Werte bei jeder Anforderung, bis sie abgeschlossen ist.

Wenn ein Stapel ausgeführt wird, verwendet die Seite anscheinend Ajax-Anforderungen, um den Fortschritt des Stapelvorgangs anzuzeigen (% erledigt und Meldungen). Ich nehme an, es wartet, bis die Anfrage beendet ist, um den Fortschritt zu aktualisieren und dann die nächste Anfrage sofort danach zu starten.

Wenn die Seite mit der Stapelanforderung geschlossen wird, stoppt die Stapelverarbeitung? Wird es neu gestartet, wenn dieselbe URL erneut geöffnet wird? Das Migrationsmodul wird manchmal fortgesetzt, verwendet aber wahrscheinlich Warteschlangen?

Antworten:


40

So funktioniert Batch (nach meinem Verständnis)

1. Initialisieren

  1. Initialisieren Sie die Stapelverarbeitung. Basierend auf der Konfiguration der Clients (Browser), ob JavaScript aktiviert ist oder nicht.
  2. JavaScript-fähige Clients werden durch das Cookie 'has_js' in drupal.js identifiziert. Wenn während der Browsersitzung des aktuellen Benutzers keine JavaScript-fähige Seite aufgerufen wurde, wird die Nicht-JavaScript-Version zurückgegeben.
  3. Wenn JavaScript aktiviert ist, verwendet Batch eine Ajax- Anforderung, um die Verbindung über die Anforderung hinweg aufrechtzuerhalten.
  4. Wenn JavaScript nicht aktiviert ist, legt Batch using ein Meta-Tag in HTML fest, um regelmäßige Aktualisierungsintervalle festzulegen , damit die Verbindung über die Anforderung hinweg erhalten bleibt.

(So ​​wird der Fortschrittsbalken über den Fortschritt des Auftrags aktualisiert.)

Stapelverarbeitung

  1. Zum Starten des Prozesses erstellt Batch eine Warteschlange und fügt alle Operationen (Funktionen und Argumente) hinzu , die Sie im Batch-Array wie folgt definieren:

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

    Zusätzlich wird eine Chargen-ID zugewiesen, die für alle Chargen eindeutig ist.

  2. Batch-Aufrufe beanspruchen nun die Queue-Elemente nacheinander und führen die Funktion aus, die mit den darin definierten Argumenten definiert wurde.

  3. Dies ist ein entscheidender Teil. Die Funktion (Operation), die die Batch-Operation implementiert, sollte die Daten aufteilen und sie sehr effizient verarbeiten, wobei das Speicherlimit von PHP, Timeout, zu berücksichtigen ist . Andernfalls liegt das Problem bei Ihnen.

Ich bin neulich auf ein Timeout-Problem mit der Migration gestoßen und habe mich gefragt, wie die Batch-API intern funktioniert.

Die Batch-Funktion

Die Funktionen, die Batch implementieren, sollten die folgenden Dinge sehr sorgfältig ausführen:

  • Anzahl der Elemente innerhalb der Operationen, die verarbeitet werden sollen,

    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}'));
    }
  • Begrenzen der Anzahl der Elemente, die in einem Funktionsaufruf verarbeitet werden sollen, z. B. Einrichten eines Limits.

    // For this example, we decide that we can safely process 5 nodes at a time without a timeout.
    $limit = 5;
  • Update auf den Prozess zur Nachbearbeitung wie

    // Update our progress information.
        $context['sandbox']['progress']++;
        $context['sandbox']['current_node'] = $node->nid;
        $context['message'] = t('Now processing %node', array('%node' => $node->title));
  • Informieren der Batch-Engine, ob der Batch abgeschlossen ist oder nicht,

    // 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'];
     }

Die meisten der oben genannten Punkte werden für die Drupal-Core-Batch-Vorgänge verwendet, wenn sie in der Implementierungsfunktion fehlen. Es ist jedoch immer am besten, in der implementierenden Funktion zu definieren

Batch-Rückruf beendet

  • Dies ist der letzte Rückruf, der aufgerufen wird, wenn er im Batch-Array definiert ist. Normalerweise ein Bericht darüber, wie viel verarbeitet wurde usw.

ANTWORTEN

Wenn die Seite mit der Stapelanforderung geschlossen wird, stoppt die Stapelverarbeitung? Wird es neu gestartet, wenn dieselbe URL erneut geöffnet wird? Das Migrationsmodul wird manchmal fortgesetzt, verwendet aber wahrscheinlich Warteschlangen?

Ja, im Idealfall sollte der Batch neu gestartet werden und basiert, wie oben erwähnt, auf der von Ihnen implementierten Funktion.

Um Ihr Problem mit PHP Timeout zu lösen , verwenden Sie Drush Batch, das im Migrate-Modul verfügbar ist. Aber zuerst müssen Sie die Batch-Funktionen von migrate ausgraben und versuchen, Ihre Verarbeitungsdaten aufzuteilen.


1
Toller Rundgang. Ich möchte auch darauf hinweisen, dass die Stapelverarbeitung während der "Initialisierung" beginnt, die dem Benutzer zumindest als "Initialisierung" erscheint. Bildschirm. Das heißt, wenn das Einrichten 4 Sekunden und das Verarbeiten des ersten Batch-Elements 10 Sekunden dauert, wird dem Benutzer der Vorgang "Initialisieren" angezeigt. für vierzehn Sekunden in diesem Beispiel. Dies ist sinnvoll, da die erste Nicht-Init-Bildschirmmeldung "n erledigt" ist, was erst funktionieren würde, nachdem einige verarbeitet wurden. Wenn dies falsch ist, korrigieren Sie mich bitte!
Texas-Bronius

Auch aus meiner Erfahrung. Wenn Sie die Seite verlassen, verbraucht der Batch-Vorgang / Block, der gerade ausgeführt wird, noch Ressourcen, bis er abgeschlossen ist. Der Stapeljob wird nicht mehr ausgelöst, der aktuelle Job wird jedoch abgeschlossen.
Elijah Lynn

10

Wenn die Seite mit der Stapelanforderung geschlossen wird, stoppt die Stapelverarbeitung?

Ja, es wird gestoppt.

Wird es neu gestartet, wenn dieselbe URL erneut geöffnet wird? Das Migrationsmodul wird manchmal fortgesetzt, verwendet aber wahrscheinlich Warteschlangen?

Wie Dinesh sagte, hängt es von der Implementierung ab.

Sie sollten die Migration mit drush ausführen, weil

Drush wird in der Befehlszeile ausgeführt und unterliegt keinen zeitlichen Beschränkungen (insbesondere gilt nicht die max_execution_time von PHP). Wenn Sie also einen Migrationsprozess starten, der über drush ausgeführt wird, wird er einfach gestartet und läuft so lange weiter, bis er abgeschlossen ist.

Beim Ausführen von Prozessen über eine Webschnittstelle gilt die maximale Ausführungszeit von PHP (normalerweise 30 Sekunden, wenn nicht weniger). Daher müssen wir für Prozesse mit langer Laufzeit die Batch-API verwenden, die die Aufteilung eines Prozesses auf mehrere Anforderungen verwaltet. Daher wird ein Migrationsprozess gestartet, ca. 25 Sekunden lang ausgeführt und dann angehalten, und die Batch-API gibt eine neue Seitenanforderung aus, in der der Migrationsprozess unendlich oft neu gestartet wird.

Wenn man das versteht, warum ist Drush besser?

Es ist schneller

Die Batch-API verursacht viel Overhead: Das Herunterfahren und erneute Aufrufen der Seitenanforderungen, der Migrationsprozess muss alle erforderlichen Konstruktoren erneut durchlaufen, die Datenbankverbindungen müssen wiederhergestellt und Abfragen erneut ausgeführt werden usw. Für einen Teilimport muss ausgewählt werden Wo aufgehört - Wenn die ersten 500 Quelldatensätze importiert wurden, muss der 501. Datensatz gefunden werden. Abhängig von Ihrem Quellformat und seinem Aufbau kann dies skaliert werden oder nicht. Wenn Sie Hochwassermarken mit einer SQL-Quelle verwenden, kann die Abfrage selbst die früheren Datensätze entfernen und genau dort beginnen, wo Sie aufgehört haben. Ist dies nicht der Fall, muss Migrate einen Bildlauf durch die Quelldaten durchführen, um nach dem ersten nicht importierten Datensatz zu suchen. Mit zum Beispiel einer großen XML-Datei als Quelle,

Es ist zuverlässiger

Wenn Sie Migrationen über Ihren Browser ausführen, werden Ihr Desktop und Ihre lokale Internetverbindung als Fehlerquellen hinzugefügt. Ein Netzwerkfehler, wenn die Batch-API zur nächsten Seitenanforderung wechselt, ein Browserabsturz, ein versehentliches Schließen der falschen Registerkarte oder des falschen Fensters können Ihre Migration unterbrechen. Drushing reduziert die beweglichen Teile - Sie eliminieren Ihre Desktop- und lokale Internetverbindung als Faktoren.

Es ist hilfreicher

Wenn beim Ausführen von Drush etwas schief geht, werden nützliche Fehlermeldungen angezeigt. Fehler, die die Batch-API verwenden, werden häufig verschluckt und Sie sehen nur die völlig unbrauchbare Meldung "Eine AJAX-HTTP-Anforderung wurde abnormal beendet. Es folgen Debuginformationen. Pfad: / batch? Id = 901 & op = do StatusText: ResponseText: ReadyState: 4".

Weitere Informationen dazu finden Sie hier .

In der Zwischenzeit sollten Sie das Modul Hintergrundprozess in Betracht ziehen, wenn Sie den Stapel auch dann ausführen möchten, wenn das Browserfenster geschlossen ist . Es hat ein Submodul Background Batch, das den Trick macht.

Dieses Modul übernimmt die vorhandene Batch-API und führt Batch-Jobs in einem Hintergrundprozess aus. Das heißt, wenn Sie die Stapelseite verlassen, werden die Jobs fortgesetzt und Sie können später zur Fortschrittsanzeige zurückkehren.


Wow, die Verwendung von Drush zur Migration hat eine enorme Verbesserung gebracht. Ich muss in eine Live-Site migrieren und das System wird viel weniger belastet! Vielen Dank!
Uwe

0

Verstehen Sie die Batch-API sorgfältig und diese Module helfen Ihnen:

1- Progerss Dies ist ein Versuch, ein generisches Framework zu implementieren, um Fortschritte zu verfolgen

2- Der Hintergrundfortschritt übernimmt die vorhandene Stapel-API und führt Stapeljobs in einem Hintergrundprozess aus

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.