Pipelineabhängigkeiten in Dataflow verwalten

Viele Apache Beam-Pipelines können mit den standardmäßigen Dataflow-Laufzeitumgebungen ausgeführt werden. Bei einigen Anwendungsfällen in der Datenverarbeitung ist es jedoch sinnvoll, zusätzliche Bibliotheken oder Klassen zu verwenden. In diesen Fällen müssen Sie möglicherweise Ihre Pipelineabhängigkeiten verwalten.

In der folgenden Liste finden Sie einige Gründe, warum Sie Ihre Pipelineabhängigkeiten verwalten müssen:

  • Die Abhängigkeiten, die von der Standardlaufzeitumgebung bereitgestellt werden, reichen für Ihren Anwendungsfall nicht aus.
  • Die Standardabhängigkeiten haben entweder Versionskollisionen oder Klassen und Bibliotheken, die mit Ihrem Pipelinecode nicht kompatibel sind.
  • Sie müssen bestimmte Bibliotheksversionen für Ihre Pipeline anheften.
  • Sie haben eine Python-Pipeline, die mit einem konsistenten Satz von Abhängigkeiten ausgeführt werden muss.

Wie Sie Abhängigkeiten verwalten, hängt davon ab, ob Ihrer Pipeline Java, Python oder Go verwendet.

Java

Inkompatible Klassen und Bibliotheken können Probleme mit Java-Abhängigkeiten verursachen. Wenn Ihre Pipeline nutzerspezifischen Code und Einstellungen enthält, darf der Code keine gemischten Bibliotheksversionen enthalten.

Probleme mit Java-Abhängigkeiten

Wenn Ihre Pipeline Probleme mit der Java-Abhängigkeit hat, kann einer der folgenden Fehler auftreten:

  • NoClassDefFoundError: Dieser Fehler tritt auf, wenn eine ganze Klasse während der Laufzeit nicht verfügbar ist.
  • NoSuchMethodError: Dieser Fehler tritt auf, wenn die Klasse im Klassenpfad eine Version verwendet, die nicht die erforderliche Methode enthält, oder wenn sich die Methodensignatur geändert hat.
  • NoSuchFieldError: Dieser Fehler tritt auf, wenn für die Klasse im Klassenpfad eine Version verwendet wird, der ein zur Laufzeit erforderliches Feld fehlt.
  • FATAL ERROR: Dieser Fehler tritt auf, wenn eine integrierte Abhängigkeit nicht richtig geladen werden kann. Wenn Sie eine Uber-JAR-Datei (Shaded) verwenden, nehmen Sie keine Bibliotheken auf, die Signaturen in derselben JAR-Datei verwenden, z. B. Conscrypt.

Abhängigkeitsverwaltung

Zur Vereinfachung der Abhängigkeitsverwaltung für Java-Pipelines verwendet Apache Beam Bill of Materials (BOM)-Artefakte. Die BOM unterstützt die Tools für die Abhängigkeitsverwaltung bei der Auswahl kompatibler Abhängigkeitskombinationen. Weitere Informationen finden Sie unter Apache Beam SDK für Java-Abhängigkeiten in der Apache Beam-Dokumentation.

Wenn Sie eine BOM mit Ihrer Pipeline verwenden und der Abhängigkeitsliste explizit weitere Abhängigkeiten hinzufügen möchten, fügen Sie der Datei pom.xml für das SDK-Artefakt die folgenden Informationen hinzu. Verwenden Sie beam-sdks-java-io-google-cloud-platform-bom, um die richtige Libraries-BOM zu importieren.

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.apache.beam</groupId>
      <artifactId>beam-sdks-java-google-cloud-platform-bom</artifactId>
      <version>LATEST</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

<dependencies>
  <dependency>
    <groupId>org.apache.beam</groupId>
    <artifactId>beam-sdks-java-core</artifactId>
  </dependency>
  <dependency>
    <groupId>org.apache.beam</groupId>
    <artifactId>beam-runners-google-cloud-dataflow-java</artifactId>
  </dependency>
  <dependency>
    <groupId>org.apache.beam</groupId>
    <artifactId>beam-sdks-java-io-google-cloud-platform</artifactId>
  </dependency>
</dependencies>

Das Artefakt beam-sdks-java-core enthält nur das Core SDK. Sie müssen der Liste der Abhängigkeiten explizit weitere Abhängigkeiten wie E/A und Runner hinzufügen.

Python

Wenn Sie Dataflow-Jobs mit dem Apache Beam Python SDK ausführen, ist die Abhängigkeitsverwaltung in den folgenden Szenarien nützlich:

  • Ihre Pipeline verwendet öffentliche Pakete aus dem Python Package Index (PiPy) und Sie möchten diese Pakete aus der Ferne verfügbar machen.
  • Sie möchten eine reproduzierbare Umgebung erstellen.
  • Um die Startzeit zu verkürzen, sollten Sie Abhängigkeitsinstallationen auf Workern zur Laufzeit vermeiden.

Python-Pipelineabhängigkeiten definieren

Obwohl Sie ein einziges Python-Skript oder -Notebook verwenden können, um eine Apache Beam-Pipeline zu schreiben, wird Software in der Python-Umgebung häufig als Pakete verteilt. Wenn Ihr Pipelinecode mehrere Dateien umfasst, sollten Sie die Pipelinedateien als Python-Paket gruppieren, um die Wartung zu vereinfachen.

  • Definieren Sie die Abhängigkeiten der Pipeline in der setup.py-Datei Ihres Pakets.
  • Stellen Sie das Paket mithilfe der Pipeline-Option --setup_file auf den Workern bereit.

Wenn die Remote-Worker starten, installieren sie Ihr Paket. Ein Beispiel finden Sie unter Juliset im Apache Beam GitHub.

So strukturieren Sie Ihre Pipeline als Python-Paket:

  1. Erstellen Sie eine setup.py-Datei für Ihr Projekt. Fügen Sie in die Datei setup.py das Argument install_requires ein, um den minimalen Satz von Abhängigkeiten für die Pipeline anzugeben. Das folgende Beispiel zeigt eine einfache setup.py-Datei.

    import setuptools
    
    setuptools.setup(
      name='PACKAGE_NAME',
      version='PACKAGE_VERSION',
      install_requires=[],
      packages=setuptools.find_packages(),
    )
    
  2. Fügen Sie die Datei setup.py, die zentrale Workflowdatei und ein Verzeichnis mit den restlichen Dateien dem Stammverzeichnis Ihres Projekts hinzu. Diese Dateigruppierung ist das Python-Paket für Ihre Pipeline. Die Dateistruktur sieht so aus wie das folgende Beispiel:

    root_dir/
      package_name/
        my_pipeline_launcher.py
        my_custom_transforms.py
        ...other files...
      setup.py
      main.py
    
  3. Installieren Sie das Paket in der Einreichungsumgebung, um die Pipeline auszuführen. Verwenden Sie die Pipelineoption --setup_file, um das Paket auf den Workern bereitzustellen. Beispiel:

    python -m pip install -e .
    python main.py --runner DataflowRunner --setup_file ./setup.py  <...other options...>
    

Diese Schritte vereinfachen die Wartung des Pipelinecodes, insbesondere wenn der Code größer und komplexer wird. Weitere Möglichkeiten zum Angeben von Abhängigkeiten finden Sie in der Apache Beam-Dokumentation unter Python-Pipelineabhängigkeiten verwalten.

Benutzerdefinierte Container verwenden, um die Laufzeitumgebung zu steuern

Um eine Pipeline mit dem Apache Beam Python SDK auszuführen, benötigen Dataflow-Worker eine Python-Umgebung mit einem Interpreter, dem Apache Beam SDK und den Pipelineabhängigkeiten. Docker-Container-Images bieten die erforderliche Umgebung für die Ausführung Ihres Pipelinecodes.

Stock-Container-Images werden mit jeder Version des Apache Beam SDK veröffentlicht und diese Images enthalten die Apache Beam SDK-Abhängigkeiten. Weitere Informationen finden Sie unter Apache Beam SDK für Python-Abhängigkeiten in der Apache Beam-Dokumentation.

Wenn Ihre Pipeline eine Abhängigkeit benötigt, die nicht im Standard-Container-Image enthalten ist, muss diese Abhängigkeit zur Laufzeit installiert werden. Das Installieren von Paketen zur Laufzeit kann folgende Auswirkungen haben:

  • Die Startzeit des Workers erhöht sich aufgrund der Auflösung, des Downloads und der Installation von Abhängigkeiten.
  • Für die Ausführung der Pipeline ist eine Internetverbindung erforderlich.
  • Nicht-Determinismus tritt aufgrund von Softwarereleases in Abhängigkeiten auf.

Um diese Probleme zu vermeiden, stellen Sie die Laufzeitumgebung in einem benutzerdefinierten Docker-Container-Image bereit. Die Verwendung eines benutzerdefinierten Docker-Container-Images, in dem die Pipelineabhängigkeiten vorinstalliert sind, bietet die folgenden Vorteile:

  • Sorgt dafür, dass die Pipeline-Laufzeitumgebung jedes Mal, wenn Sie Ihren Dataflow-Job starten, dieselben Abhängigkeiten hat.
  • Hiermit können Sie die Laufzeitumgebung Ihrer Pipeline steuern.
  • Vermeidet eine potenziell zeitaufwendige Abhängigkeitsauflösung beim Start.

Beachten Sie bei der Verwendung benutzerdefinierter Container-Images die folgenden Hinweise:

  • Verwenden Sie das Tag :latest nicht für benutzerdefinierte Bilder. Taggen Sie Ihre Builds mit einem Datum, einer Version oder einer eindeutigen Kennung. So können Sie bei Bedarf zu einer bekannten funktionierenden Konfiguration zurückkehren.
  • Verwenden Sie eine Startumgebung, die mit Ihrem Container-Image kompatibel ist. Weitere Informationen zur Verwendung benutzerdefinierter Container finden Sie unter Container-Image erstellen.

Weitere Informationen zum Vorinstallieren von Python-Abhängigkeiten finden Sie unter Python-Abhängigkeiten vorinstallieren.

Startumgebung mit Dataflow-Vorlagen steuern

Wenn für Ihre Pipeline zusätzliche Abhängigkeiten erforderlich sind, müssen Sie diese möglicherweise sowohl in der Laufzeit- als auch in der Startumgebung installieren. In der Startumgebung wird die Produktionsversion der Pipeline ausgeführt. Da die Startumgebung mit der Laufzeitumgebung kompatibel sein muss, müssen in beiden Umgebungen dieselben Versionen der Abhängigkeiten verwendet werden.

Verwenden Sie Dataflow-Flex-Vorlagen, um eine containerisierte, reproduzierbare Startumgebung zu erhalten. Weitere Informationen finden Sie unter Flex-Vorlage erstellen und ausführen. Berücksichtigen Sie bei der Verwendung flexibler Vorlagen die folgenden Faktoren:

Dadurch ist Ihre Startumgebung sowohl reproduzierbar als auch mit Ihrer Laufzeitumgebung kompatibel.

Ein Beispiel für diesen Ansatz finden Sie in der Anleitung Flex-Vorlage für eine Pipeline mit Abhängigkeiten und einem benutzerdefinierten Container in GitHub.

Weitere Informationen finden Sie unter Startumgebung mit der Laufzeitumgebung kompatibel machen und Von der Pipeline verwendete Abhängigkeiten steuern in der Apache Beam-Dokumentation.

Go

Wenn Sie Dataflow-Jobs mit dem Apache Beam Go SDK ausführen, werden Go-Module zum Verwalten von Abhängigkeiten verwendet. Die folgende Datei enthält die Standardkompilierungs- und Laufzeitabhängigkeiten, die von Ihrer Pipeline verwendet werden:

https://raw.githubusercontent.com/apache/beam/vVERSION_NUMBER/sdks/go.sum

Ersetzen Sie VERSION_NUMBER durch die von Ihnen verwendete SDK-Version.

Informationen zum Verwalten von Abhängigkeiten für Ihre Go-Pipeline finden Sie in der Go-Dokumentation unter Abhängigkeiten verwalten.