本文为您介绍如何搭建MaxCompute Spark开发环境。

前提条件

搭建开发环境之前,请确保您已经完成如下软件的安装:
  • JDK 1.8
  • Python2.7
  • Maven
  • Git

下载MaxCompute Spark客户端

MaxCompute Spark发布包集成了MaxCompute认证功能。作为客户端工具,它通过Spark-Submit方式提交作业到MaxCompute项目中运行。目前提供了面向Spark1.x和Spark2.x的2个发布包:

设置环境变量

  • JAVA_HOME设置。
    # 推荐使用JDK 1.8
    export JAVA_HOME=/path/to/jdk
    export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
    export PATH=$JAVA_HOME/bin:$PATH
  • SPARK_HOME设置。
    下载MaxCompute Spark客户端并解压到本地任意路径。将SPARK_HOME参数替换为您的解压路径。
    export SPARK_HOME=/path/to/spark_extracted_package
    export PATH=$SPARK_HOME/bin:$PATH
  • PySpark的用户请安装Python2.7版本,并设置PATH。
    export PATH=/path/to/python/bin/:$PATH

配置spark-defaults.conf

第一次使用MaxCompute Spark客户端时,需要配置spark-defaults.conf文件。

$SPARK_HOME/conf路径下存在spark-defaults.conf.template文件,您可以将其作为spark-defaults.conf的模版进行相关配置。
注意 请将spark-defaults.conf.template重命名为spark-defaults.conf后再进行相关配置。如果没有对文件进行重命名,将会导致配置无法生效。
# spark-defaults.conf
# 填写MaxCompute的项目空间名称以及账号信息。
spark.hadoop.odps.project.name = XXX  
spark.hadoop.odps.access.id = XXX     
spark.hadoop.odps.access.key = XXX

# 以下配置保持不变。
spark.hadoop.odps.end.point = http://service.cn.maxcompute.aliyun.com/api   # Spark客户端连接访问MaxCompute项目的Endpoint,您可以根据自己情况进行修改。详情请参见配置Endpoint。
spark.hadoop.odps.runtime.end.point = http://service.cn.maxcompute.aliyun-inc.com/api  # Spark运行环境Endpoint,所在Region的MaxCompute VPC网络的Endpoint。您可以根据自己情况进行修改。
spark.sql.catalogImplementation=odps
spark.hadoop.odps.task.major.version = cupid_v2
spark.hadoop.odps.cupid.container.image.enable = true
spark.hadoop.odps.cupid.container.vm.engine.type = hyper

spark.hadoop.odps.cupid.webproxy.endpoint = http://service.cn.maxcompute.aliyun-inc.com/api
spark.hadoop.odps.moye.trackurl.host = http://jobview.odps.aliyun.com

特殊场景和功能,需要开启一些其它的配置参数,详情请参见Spark配置详解

准备项目工程

MaxCompute Spark提供了项目工程模版,建议您下载模版复制后直接在模版里开发。
说明 模版工程里的关于spark依赖的scope为provided,请不要更改,否则提交的作业无法正常运行。
  • Spark-1.x 模板及编译
    git clone https://github.com/aliyun/MaxCompute-Spark.git
    cd spark-1.x
    mvn clean package
  • Spark-2.x 模板及编译
    git clone https://github.com/aliyun/MaxCompute-Spark.git
    cd spark-2.x
    mvn clean package

配置依赖说明

  • 配置访问MaxCompute表所需的依赖。
    Spark作业访问MaxCompute表,需要依赖odps-spark-datasource模块。Maven配置举例如下。
    <!-- Spark-2.x请依赖此模块 -->
    <dependency>
        <groupId>com.aliyun.odps</groupId>
        <artifactId>odps-spark-datasource_2.11</artifactId>
        <version>3.3.8-public</version>
    </dependency>
    
    <!-- Spark-1.x请依赖此模块 -->
    <dependency>
      <groupId>com.aliyun.odps</groupId>
      <artifactId>odps-spark-datasource_2.10</artifactId>
      <version>3.3.8-public</version>
    </dependency>
  • 配置访问OSS所需的依赖。
    如果作业需要访问OSS,直接添加以下依赖即可。
    <dependency>
        <groupId>com.aliyun.odps</groupId>
        <artifactId>hadoop-fs-oss</artifactId>
        <version>3.3.8-public</version>
    </dependency>
  • Spark-2.x依赖配置

    pom文件请参见Spark-2.x pom文件

  • Spark-1.x依赖配置

    pom文件请参见Spark-1.x pom文件

SparkPi冒烟测试

完成以上的工作之后,执行冒烟测试,验证MaxCompute Spark是否可以端到端连通。以Spark-2.x为例,您可以提交一个SparkPi验证功能是否正常,提交命令如下。
# /path/to/MaxCompute-Spark请指向正确的编译出来后的应用程序的Jar包。
cd $SPARK_HOME
bin/spark-submit --master yarn-cluster --class com.aliyun.odps.spark.examples.SparkPi \
/path/to/MaxCompute-Spark/spark-2.x/target/spark-examples_2.11-1.0.0-SNAPSHOT-shaded.jar

# 当看到以下日志表明冒烟作业成功。
19/06/11 11:57:30 INFO Client: 
         client token: N/A
         diagnostics: N/A
         ApplicationMaster host: 11.222.166.90
         ApplicationMaster RPC port: 38965
         queue: queue
         start time: 1560225401092
         final status: SUCCEEDED

IDEA本地执行注意事项

通常,本地调试成功后会在集群上执行代码。但是Spark可以支持在IDEA里以Local模式直接运行代码,运行时请注意以下几点:
  • 代码需要手动设置spark.master
    val spark = SparkSession
          .builder()
          .appName("SparkPi")
          .config("spark.master", "local[4]") // 需要设置spark.master为local[N]才能直接运行,N为并发数。
          .getOrCreate()
  • 在IDEA里手动添加MaxCompute Spark客户端的相关依赖。
    <dependency>
        <groupId>org.apache.spark</groupId>
        <artifactId>spark-core_${scala.binary.version}</artifactId>
        <version>${spark.version}</version>
        <scope>provided</scope> 
    </dependency>
    pom.xml中设置要求scope为provided,所以运行时会出现NoClassDefFoundError报错。
    Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/spark/sql/SparkSession$
        at com.aliyun.odps.spark.examples.SparkPi$.main(SparkPi.scala:27)
        at com.aliyun.odps.spark.examples.Spa。r。kPi.main(SparkPi.scala)
    Caused by: java.lang.ClassNotFoundException: org.apache.spark.sql.SparkSession$
        at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        ... 2 more
    您可以按照以下方式手动将MaxCompute Spark下的Jars目录加入IDEA模板工程项目中,既可以保持scope=provided,又能在IDEA里直接运行不报错:
    1. 在IDEA中单击顶部菜单栏上的File,选中Project Structure…44
    2. Project Structure页面,单击左侧导航栏上的Modules。选择资源包,并单击资源包的Dependencies页签。
    3. 在资源包的Dependencies页签下,单击左下角的+,选择JARs or directories…添加MaxCompute Spark下的Jars目录。
  • Local不能直接引用spark-defaults.conf里的配置,需要手动指定相关配置。
    通过Spark-Submit方式提交作业,系统会读取spark-defaults.conf文件中的配置。通过Local模式提交作业,需要手动在代码里指定相关配置。例如,在Local模式下如果要通过Spark-Sql读取MaxCompute的表,配置如下。
    val spark = SparkSession
          .builder()
          .appName("SparkPi")
          .config("spark.master", "local[4]") // 需设置spark.master为local[N]才能直接运行,N为并发数。
          .config("spark.hadoop.odps.project.name", "****")
          .config("spark.hadoop.odps.access.id", "****")
          .config("spark.hadoop.odps.access.key", "****")
          .config("spark.hadoop.odps.end.point", "http://service.cn.maxcompute.aliyun.com/api")
          .config("spark.sql.catalogImplementation", "odps")
          .getOrCreate()