Mejores prácticas para crear aplicaciones de flujo de Spark de Python

Consejos y mejores prácticas para configurar proyectos de creación de Python en Data Flow.

Las aplicaciones Spark de Python son más complejas que las aplicaciones Java, ya que las dependencias son necesarias al mismo tiempo para los tiempos de ejecución de JVM y Python. Los tiempos de ejecución tienen sus propios sistemas de gestión de proyectos y paquetes. Para ayudar con el empaquetado de dependencias de un tiempo de ejecución diferente, Data Flow tiene una herramienta de empaquetado de dependencias. La herramienta empaqueta todas las dependencias en un único archivo que se debe cargar en Object Storage. Data Flow proporciona dependencias de ese archivo a la aplicación Spark.

El archivo garantiza la disponibilidad cuando se almacena en Oracle Cloud Infrastructure Object Storage, la misma reproducibilidad (el artefacto es dinámico y, por lo tanto, puede producir un árbol de dependencias diferente) y deja de descargar las mismas dependencias de orígenes externos.

Puede encontrar más información sobre cómo configurar y utilizar el gestor de dependencias en la sección sobre la Funcionalidad spark-submit en Data Flow.

Al crear archive.zip para su aplicación, muestre las bibliotecas Java necesarias en packages.txt y el empaquetador de dependencias las empaqueta junto con sus dependencias.
Proporcione una dependencia mediante cualquiera de las siguientes opciones:
  • Utilice la opción --packages o la configuración de Spark spark.jars.packages. Una aplicación que se ejecute en un punto final privado debe permitir que el tráfico de la subred privada vaya a la red pública de Internet para que se descargue el paquete.
  • Proporcione la ubicación de Object Storage en --jars o spark.jars como una lista separada por comas.
  • Utilice python o structured_streaming_java_dependencies_for_python create archive.zip.
Por ejemplo, para incluir spark-sql-kafka-0-10_2.12, agréguelo en packages.txt:
org.apache.spark:spark-sql-kafka-0-10_2.12:3.2.1
Ejecute este comando:
docker run --pull always --rm -v $(pwd):/opt/dataflow -it phx.ocir.io/oracle/dataflow/dependency-packager:latest
El resultado es un archivo archive.zip:
  adding: java/ (stored 0%)
  adding: java/org.lz4_lz4-java-1.7.1.jar (deflated 3%)
  adding: java/org.slf4j_slf4j-api-1.7.30.jar (deflated 11%)
  adding: java/org.xerial.snappy_snappy-java-1.1.8.2.jar (deflated 1%)
  adding: java/org.apache.spark_spark-token-provider-kafka-0-10_2.12-3.0.2.jar (deflated 8%)
  adding: java/org.apache.spark_spark-sql-kafka-0-10_2.12-3.0.2.jar (deflated 5%)
  adding: java/com.github.luben_zstd-jni-1.4.4-3.jar (deflated 1%)
  adding: java/org.spark-project.spark_unused-1.0.0.jar (deflated 42%)
  adding: java/org.apache.kafka_kafka-clients-2.4.1.jar (deflated 8%)
  adding: java/org.apache.commons_commons-pool2-2.6.2.jar (deflated 9%)
  adding: version.txt (deflated 59%)
archive.zip is generated!
Nota

En Spark 3.2.1, la mayoría del código de origen y las bibliotecas que se utilizan para ejecutar Data Flow están ocultos. Ya no tendrá que coincidir con las versiones del SDK de Data Flow y ya no tendrá conflictos de dependencia de terceros con Data Flow. Consulte el tutorial Desarrollo local de aplicaciones de Oracle Cloud Infrastructure Data Flow y despliegue en la nube para obtener más información. Para conocer las versiones de biblioteca necesarias, consulte Migrate Data Flow to Spark 3.2.1. Resuelva la dependencia de flujo mediante las opciones mencionadas anteriormente. Hay ejemplos de dependencias de Java de transmisión estructurada para Python disponibles en github.

Puede que sea necesario sombrear algunas bibliotecas Java.
Si utiliza Spark 2.4.4 o Spark 3.0.2, puede que tenga que sombrear sus bibliotecas. Cree un proyecto de Maven independiente para crear un Fat JAR que contenga todas las dependencias de Java y otros ajustes como el sombreado en un lugar. Inclúyalo como JAR personalizado mediante el empaquetador de dependencias. Por ejemplo, con oci-java-sdk-addons-sasl, ya que el SDK de Oracle Cloud Infrastructure se ha compilado en versiones posteriores de algunas bibliotecas de terceros, por lo que se pueden producir fallos de tiempo de ejecución.

Un proyecto de Maven de ejemplo:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
 
  <groupId>com.example</groupId>
  <artifactId>SaslFat</artifactId>
  <version>1.0-SNAPSHOT</version>
 
  <properties>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
    <spark.version>3.0.2</spark.version>
  </properties>
 
  <dependencies>
    <dependency>
      <groupId>com.oracle.oci.sdk</groupId>
      <artifactId>oci-java-sdk-addons-sasl</artifactId>
      <optional>false</optional>
      <version>1.36.1</version>
    </dependency>
    <dependency>
      <groupId>com.google.protobuf</groupId>
      <artifactId>protobuf-java</artifactId>
      <version>3.11.1</version>
    </dependency>
    <dependency>
      <groupId>org.apache.spark</groupId>
      <artifactId>spark-core_2.12</artifactId>
      <version>${spark.version}</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.apache.spark</groupId>
      <artifactId>spark-sql_2.12</artifactId>
      <version>${spark.version}</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.apache.spark</groupId>
      <artifactId>spark-sql-kafka-0-10_2.12</artifactId>
      <version>${spark.version}</version>
    </dependency>
  </dependencies>
 
  <build>
    <plugins>
 
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.2.4</version>
        <configuration>
          <createDependencyReducedPom>false</createDependencyReducedPom>
          <transformers>
            <transformer
              implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
            <transformer
              implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"/>
          </transformers>
          <relocations>
            <relocation>
              <pattern>com.google.</pattern>
              <shadedPattern>com.shaded.google.</shadedPattern>
            </relocation>
            <relocation>
              <pattern>com.oracle.bmc.</pattern>
              <shadedPattern>com.shaded.oracle.bmc.</shadedPattern>
              <excludes>
                <exclude>com.oracle.bmc.auth.sasl.*</exclude>
              </excludes>
            </relocation>
          </relocations>
          <!-- exclude signed Manifests -->
          <filters>
            <filter>
              <artifact>*:*</artifact>
              <excludes>
                <exclude>META-INF/*.SF</exclude>
                <exclude>META-INF/*.DSA</exclude>
                <exclude>META-INF/*.RSA</exclude>
              </excludes>
            </filter>
          </filters>
          <artifactSet>
            <excludes>
              <exclude>${project.groupId}:${project.artifactId}</exclude>
            </excludes>
          </artifactSet>
        </configuration>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>shade</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
 
    </plugins>
  </build>
</project>
Coloque SaslFat-1.0-SNAPSHOT.jar en el directorio de trabajo del empaquetador de dependencias y ejecute el comando:
docker run --pull always --rm -v $(pwd):/opt/dataflow -it phx.ocir.io/oracle/dataflow/dependency-packager:latest
SaslFat-1.0-SNAPSHOT.jar se empaqueta en archive.zip como una dependencia de Java:
  adding: java/ (stored 0%)
  adding: java/SaslFat-1.0-SNAPSHOT.jar (deflated 8%)
  adding: version.txt (deflated 59%)
archive.zip is generated!
O bien, puede crear manualmente un archive.zip de este tipo que contenga la carpeta java con SaslFat-1.0-SNAPSHOT.jar en ella.