Java Sparkストリーミング・アプリケーションを構築するためのベスト・プラクティス

データ・フローでJavaビルド・プロジェクトを構成するためのヒントとベスト・プラクティス。

次の例では、構成の様々な可能性を示すためにMavenを使用しています。

ライブラリおよびデータ・フロー全体で、同じバージョンのSparkを使用します
これを実現する最も簡単な方法は、共通の変数を定義して再利用することです。次の例で、共通の変数はspark.versionです。
<properties>
 ...
 <spark.version>3.0.2</spark.version>
 ...
</properties>
<dependencies>
 <dependency>
     <groupId>org.apache.spark</groupId>
     <artifactId>spark-core_2.12</artifactId>
     <version>${spark.version}</version>
     <scope>provided</scope>
 </dependency>
ノート

artifactIdのScalaのバージョンが、Sparkのバージョンに適していることを確認します。この例では、artifactIdは、Scala 2.12のspark-core_2.12に設定されています。
コードが重複しないよう、scopeprovidedにして、すでに標準のSparkバンドルの一部であるSparkバイナリを含めます。
前の例を展開します:
<properties>
 ...
 <spark.version>3.0.2</spark.version>
 ...
</properties>
<dependencies>
 <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>
...
ノート

依存関係のスコープの詳細は、Mavenのドキュメントを参照してください。
標準バンドルに含まれないSparkバイナリを、Sparkアプリケーションにパッケージ化します。
この例では、artifactIdspark-sql-kafka-0-10_2.12が指定されています。
<properties>
 ...
 <spark.version>3.0.2</spark.version>
 ...
</properties>
<dependencies>
<dependency>
    <groupId>org.apache.spark</groupId>
    <artifactId>spark-sql-kafka-0-10_2.12</artifactId>
    <version>${spark.version}</version>
</dependency>
...
Oracle Cloud Infrastructure SDKが、サードパーティ・ライブラリの別のバージョンに対してコンパイルされた場合、実行時に障害が発生する可能性があります。このような障害を回避するには、Oracle Cloud Infrastructure SDKおよびサードパーティ・ライブラリをSparkアプリケーションにパッケージ化し、シェーディングしたネームスペースに新しいサードパーティ・ライブラリを移動します。
例:
<dependencies>
    <dependency>
        <groupId>com.oracle.oci.sdk</groupId>
        <artifactId>
</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>
</dependencies>
...
<build>
 <plugins>
 ...
<plugin>
   <groupId>org.apache.maven.plugins</groupId>
   <artifactId>maven-shade-plugin</artifactId>
   <version>3.2.4</version>
   <configuration>
       <!-- The final uber jar file name will not have a version component. -->
       <finalName>${project.artifactId}</finalName>
       <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>
           </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>
   </configuration>
   <executions>
       <execution>
           <phase>package</phase>
           <goals>
               <goal>shade</goal>
           </goals>
       </execution>
   </executions>
</plugin>
...
Java Sparkストリーミング・アプリケーションのサンプルPOM.xmlファイル

データ・フローで使用するJavaベースのSparkストリーミング・アプリケーションを構築する際に使用するサンプルPOM.xml。

<?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>StructuredKafkaWordCount</artifactId>
    <version>1.0.0-SNAPSHOT</version>
 
    <properties>
      <spark.version>3.2.1</spark.version>
      <maven.compiler.source>1.8</maven.compiler.source>
      <maven.compiler.target>1.8</maven.compiler.target>
    </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/3.2.1</artifactId>
            <version>${spark.version}</version>
        </dependency>
    </dependencies>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <skipAssembly>false</skipAssembly>
                </configuration>
            </plugin>
 
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.2.4</version>
                <configuration>
                    <!-- The final uber jar file name will not have a version component. -->
                    <finalName>${project.artifactId}</finalName>
                    <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>
                        </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>
                </configuration>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
 
        </plugins>
    </build>
</project>