Aplikasi Spark sering kali bergantung pada library Java atau Scala pihak ketiga. Berikut adalah pendekatan yang direkomendasikan untuk menyertakan dependensi ini saat Anda mengirimkan tugas Spark ke cluster Managed Service untuk Apache Spark:
Saat mengirimkan tugas dari komputer lokal Anda dengan perintah
gcloud dataproc jobs submit, gunakan flag--properties spark.jars.packages=[DEPENDENCIES].
Contoh:gcloud dataproc jobs submit spark \ --cluster=my-cluster \ --region=region \ --properties=spark.jars.packages='com.google.cloud:google-cloud-translate:1.35.0,org.apache.bahir:spark-streaming-pubsub_2.11:2.2.0'
Saat mengirimkan tugas langsung di cluster Anda gunakan perintah
spark-submitdengan parameter--packages=[DEPENDENCIES].
Contoh:spark-submit --packages='com.google.cloud:google-cloud-translate:1.35.0,org.apache.bahir:spark-streaming-pubsub_2.11:2.2.0'
Saat menyertakan file atau paket JAR kustom:
- Dependensi khusus tugas: Tentukan jalur Cloud Storage ke
JAR Anda menggunakan flag
--jars, kolom Google Cloud konsol Jar files, atau kolomjarFileUrisAPI saat Anda mengirimkan tugas. - Dependensi di seluruh cluster: Gunakan
spark:spark.jarsproperti cluster selama pembuatan cluster (--properties="spark:spark.jars=gs://<var>your-bucket</var>/<var>your-jarfile</var>.jar").
- Dependensi khusus tugas: Tentukan jalur Cloud Storage ke
JAR Anda menggunakan flag
Menghindari konflik dependensi
Pendekatan sebelumnya mungkin gagal jika dependensi aplikasi Spark berkonflik dengan dependensi Hadoop. Konflik ini dapat terjadi karena Hadoop menyuntikkan
dependensinya ke classpath aplikasi, sehingga dependensinya lebih
diutamakan daripada dependensi aplikasi. Jika terjadi konflik, NoSuchMethodError atau error lainnya dapat dihasilkan.
Contoh:
Guava
adalah library inti Google untuk Java yang digunakan oleh banyak library dan
framework, termasuk Hadoop. Konflik dependensi dapat terjadi jika tugas atau dependensinya memerlukan versi Guava yang lebih baru daripada yang digunakan oleh Hadoop.
Hadoop v3.0 telah menyelesaikan
masalah ini, tetapi aplikasi yang mengandalkan versi Hadoop sebelumnya memerlukan solusi dua bagian berikut untuk menghindari kemungkinan konflik dependensi.
- Buat satu JAR yang berisi paket aplikasi dan semua dependensinya.
- Pindahkan paket dependensi yang berkonflik dalam JAR uber untuk mencegah nama jalur berkonflik dengan paket dependensi Hadoop. Daripada mengubah kode, gunakan plugin (lihat di bawah) untuk melakukan pemindahan ini secara otomatis (juga dikenal sebagai "shading") sebagai bagian dari proses pengemasan.
Membuat JAR uber yang di-shade dengan Maven
Maven adalah alat pengelolaan paket untuk membuat aplikasi Java. Plugin Maven scala dapat digunakan untuk membuat aplikasi yang ditulis dalam Scala, bahasa yang digunakan oleh aplikasi Spark. Plugin Maven shade
dapat digunakan untuk membuat JAR yang di-shade.
Berikut adalah contoh file konfigurasi pom.xml yang menaungi library Guava, yang terletak di paket com.google.common. Konfigurasi ini
menginstruksikan Maven untuk mengganti nama paket com.google.common menjadi
repackaged.com.google.common dan memperbarui semua referensi ke class dari
paket asli.
<?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> <properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <groupId><!-- YOUR_GROUP_ID --></groupId> <artifactId><!-- YOUR_ARTIFACT_ID --></artifactId> <version><!-- YOUR_PACKAGE_VERSION --></version> <dependencies> <dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-sql_2.11</artifactId> <version><!-- YOUR_SPARK_VERSION --></version> <scope>provided</scope> </dependency> <!-- YOUR_DEPENDENCIES --> </dependencies> <build> <plugins> <plugin> <groupId>net.alchim31.maven</groupId> <artifactId>scala-maven-plugin</artifactId> <executions> <execution> <goals> <goal>compile</goal> <goal>testCompile</goal> </goals> </execution> </executions> <configuration> <scalaVersion><!-- YOUR_SCALA_VERSION --></scalaVersion> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass><!-- YOUR_APPLICATION_MAIN_CLASS --></mainClass> </transformer> <!-- This is needed if you have dependencies that use Service Loader. Most Google Cloud client libraries do. --> <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/> </transformers> <filters> <filter> <artifact>*:*</artifact> <excludes> <exclude>META-INF/maven/**</exclude> <exclude>META-INF/*.SF</exclude> <exclude>META-INF/*.DSA</exclude> <exclude>META-INF/*.RSA</exclude> </excludes> </filter> </filters> <relocations> <relocation> <pattern>com</pattern> <shadedPattern>repackaged.com.google.common</shadedPattern> <includes> <include>com.google.common.**</include> </includes> </relocation> </relocations> </configuration> </execution> </executions> </plugin> </plugins> </build> </project>
Untuk menjalankan build:
mvn package
Catatan tentang pom.xml:
- ManifestResourceTransformer
memproses atribut dalam file manifes JAR uber (
MANIFEST.MF). Manifes juga dapat menentukan titik entri untuk aplikasi Anda. - Cakupan Spark
adalah
provided, karena Spark diinstal di Managed Service untuk Apache Spark. - Tentukan versi Spark yang diinstal di cluster Managed Service untuk Apache Spark Anda (lihat Daftar Versi Managed Service untuk Apache Spark . Jika aplikasi Anda memerlukan versi Spark yang berbeda dengan versi yang diinstal di cluster Managed Service untuk Apache Spark, Anda dapat menulis tindakan inisialisasi atau membuat image kustom yang menginstal versi Spark yang digunakan oleh aplikasi Anda.
- Entri
<filters>mengecualikan file tanda tangan dari direktoriMETA-INFdependensi Anda. Tanpa entri ini, pengecualian runtimejava.lang.SecurityException: Invalid signature file digest for Manifest main attributesdapat terjadi karena file tanda tangan tidak valid dalam konteks JAR uber Anda. - Anda mungkin perlu menaungi beberapa library. Untuk melakukannya, sertakan beberapa jalur.
Contoh berikutnya menaungi library Guava dan Protobuf.
<relocation> <pattern>com</pattern> <shadedPattern>repackaged.com</shadedPattern> <includes> <include>com.google.protobuf.**</include> <include>com.google.common.**</include> </includes> </relocation>
Membuat JAR uber yang di-shade dengan SBT
SBT
adalah alat untuk membuat aplikasi Scala. Untuk membuat JAR yang di-shade dengan SBT, tambahkan plugin
sbt-assembly
ke definisi build Anda, pertama dengan membuat file bernama assembly.sbt di direktori project/:
├── src/
└── build.sbt
└── project/
└── assembly.sbt
... lalu dengan menambahkan baris berikut di assembly.sbt:
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.6")Berikut adalah contoh file konfigurasi build.sbt yang menaungi library Guava, yang terletak di com.google.common package:
lazy val commonSettings = Seq( organization := "YOUR_GROUP_ID", name := "YOUR_ARTIFACT_ID", version := "YOUR_PACKAGE_VERSION", scalaVersion := "YOUR_SCALA_VERSION", ) lazy val shaded = (project in file(".")) .settings(commonSettings) mainClass in (Compile, packageBin) := Some("YOUR_APPLICATION_MAIN_CLASS") libraryDependencies ++= Seq( "org.apache.spark" % "spark-sql_2.11" % "YOUR_SPARK_VERSION" % "provided", // YOUR_DEPENDENCIES ) assemblyShadeRules in assembly := Seq( ShadeRule.rename("com.google.common.**" -> "repackaged.com.google.common.@1").inAll )
Untuk menjalankan build:
sbt assembly
Catatan tentang build.sbt:
- Aturan shade dalam contoh sebelumnya mungkin tidak menyelesaikan semua konflik dependensi karena SBT menggunakan strategi penyelesaian konflik yang ketat. Oleh karena itu, Anda mungkin perlu memberikan aturan yang lebih terperinci yang secara eksplisit menggabungkan jenis file yang berkonflik tertentu menggunakan strategi
MergeStrategy.first,last,concat,filterDistinctLines,rename, ataudiscard. Lihat strategi penggabungansbt-assembly's untuk mengetahui detail selengkapnya. - Anda mungkin perlu menaungi beberapa library. Untuk melakukannya, sertakan beberapa jalur.
Contoh berikutnya menaungi library Guava dan Protobuf.
assemblyShadeRules in assembly := Seq( ShadeRule.rename("com.google.common.**" -> "repackaged.com.google.common.@1").inAll, ShadeRule.rename("com.google.protobuf.**" -> "repackaged.com.google.protobuf.@1").inAll )
Mengirimkan JAR uber ke Managed Service untuk Apache Spark
Setelah membuat JAR uber yang di-shade yang berisi aplikasi Spark
dan dependensinya, upload JAR ke Cloud Storage dan kirimkan tugas
ke Managed Service untuk Apache Spark (menggunakan flag --jars di
Google Cloud CLI CLI, kolom Jar files di Google Cloud konsol, kolom
API jarFileUris atau dengan menentukan JAR yang di-shade sebagai JAR
aplikasi utama).
Langkah berikutnya
- Lihat spark-translate, contoh aplikasi Spark yang berisi file konfigurasi untuk Maven dan SBT.
- Tulis dan jalankan tugas Spark Scala di Managed Service untuk Apache Spark. Mulai cepat untuk mempelajari cara menulis dan menjalankan tugas Spark Scala di cluster Managed Service untuk Apache Spark.