通过Web应用程序启动Spark应用程序的最佳实践?

时间:2016-10-28 07:33:07

标签: apache-spark

我想通过Web应用程序向用户公开我的Spark应用程序。

基本上,用户可以决定他想要运行哪个动作并输入一些需要传递给spark应用程序的变量。 例如:用户输入几个字段,然后单击一个按钮,该按钮执行以下操作"使用参数min_x,max_x,min_y,max_y"运行 sparkApp1

应使用用户提供的参数启动spark应用程序。完成后,可能需要Web应用程序来检索结果(来自hdfs或mongodb)并将其显示给用户。处理时,Web应用程序应显示Spark应用程序的状态。

我的问题:

  • Web应用程序如何启动Spark应用程序?它可能能够从引擎盖下的命令行启动它,但可能有更好的方法来执行此操作。
  • Web应用程序如何访问Spark应用程序的当前状态?是从Spark WebUI的REST API中获取状态吗?

我正在运行带有YARN / Mesos(尚不确定)和MongoDB的Spark 1.6.1集群。

4 个答案:

答案 0 :(得分:34)

非常基本的答案:

基本上你可以使用SparkLauncher类来启动Spark应用程序并添加一些监听器来监视进度。

但是您可能对Livy服务器感兴趣,Livy服务器是Spark作业的RESTful Sever。据我所知,Zeppelin正在使用Livy提交工作并检索状态。

您还可以使用Spark REST界面检查状态,然后信息将更加精确。 Here有一个例子如何通过REST API提交作业

您有3个选项,答案是 - 自己检查;)这取决于您的项目和要求。两个主要选项:

  • SparkLauncher + Spark REST接口
  • Livy服务器

应该对你有好处,你必须检查在项目中使用哪些更容易和更好

扩展答案

您可以通过不同方式使用应用程序中的Spark,具体取决于您的需求和喜好。

SparkLauncher

SparkLauncher是来自spark-launcher工件的类。它用于启动已准备好的Spark作业,就像Spark Submit。

一样

典型用法是:

1)使用Spark作业构建项目,并将JAR文件复制到所有节点 2)从客户端应用程序,即Web应用程序,创建指向准备好的JAR文件的SparkLauncher

SparkAppHandle handle = new SparkLauncher()
    .setSparkHome(SPARK_HOME)
    .setJavaHome(JAVA_HOME)
    .setAppResource(pathToJARFile)
    .setMainClass(MainClassFromJarWithJob)
    .setMaster("MasterAddress
    .startApplication();
    // or: .launch().waitFor()

startApplication创建SparkAppHandle,允许您添加侦听器并停止应用程序。它还为getAppId提供了可能性。

SparkLauncher应该与Spark REST API一起使用。您可以查询http://driverNode:4040/api/v1/applications/*ResultFromGetAppId*/jobs,您将获得有关应用程序当前状态的信息。

Spark REST API

还可以通过RESTful API直接提交Spark作业。用法与SparkLauncher非常相似,但它以纯REST的方式完成。

示例请求 - 本文的学分:

curl -X POST http://spark-master-host:6066/v1/submissions/create --header "Content-Type:application/json;charset=UTF-8" --data '{
  "action" : "CreateSubmissionRequest",
  "appArgs" : [ "myAppArgument1" ],
  "appResource" : "hdfs:///filepath/spark-job-1.0.jar",
  "clientSparkVersion" : "1.5.0",
  "environmentVariables" : {
    "SPARK_ENV_LOADED" : "1"
  },
  "mainClass" : "spark.ExampleJobInPreparedJar",
  "sparkProperties" : {
    "spark.jars" : "hdfs:///filepath/spark-job-1.0.jar",
    "spark.driver.supervise" : "false",
    "spark.app.name" : "ExampleJobInPreparedJar",
    "spark.eventLog.enabled": "true",
    "spark.submit.deployMode" : "cluster",
    "spark.master" : "spark://spark-cluster-ip:6066"
  }
}'

此命令将ExampleJobInPreparedJar类中的作业提交给具有给定Spark Master的群集。在回复中,您将拥有submissionId字段,这将有助于检查应用程序的状态 - 只需调用其他服务:curl http://spark-cluster-ip:6066/v1/submissions/status/submissionIdFromResponse。这就是它,仅仅是代码

Livy REST服务器和Spark作业服务器

Livy REST ServerSpark Job Server是RESTful应用程序,允许您通过RESTful Web Service提交作业。这两者与Spark的REST界面之间的一个主要区别是,Livy和SJS并不需要先准备好工作并打包到JAR文件。您只需提交将在Spark中执行的代码。

用法非常简单。代码来自Livy存储库,但有一些削减以提高可读性

1)案例1:提交作业,放在本地机器

// creating client
LivyClient client = new LivyClientBuilder()
  .setURI(new URI(livyUrl))
  .build();

try {
  // sending and submitting JAR file
  client.uploadJar(new File(piJar)).get();
  // PiJob is a class that implements Livy's Job
  double pi = client.submit(new PiJob(samples)).get();
} finally {
  client.stop(true);
}

2)案例2:动态创造和执行作业

// example in Python. Data contains code in Scala, that will be executed in Spark
data = {
  'code': textwrap.dedent("""\
    val NUM_SAMPLES = 100000;
    val count = sc.parallelize(1 to NUM_SAMPLES).map { i =>
      val x = Math.random();
      val y = Math.random();
      if (x*x + y*y < 1) 1 else 0
    }.reduce(_ + _);
    println(\"Pi is roughly \" + 4.0 * count / NUM_SAMPLES)
    """)
}

r = requests.post(statements_url, data=json.dumps(data), headers=headers)
pprint.pprint(r.json()) 

如您所见,可以使用预编译的作业和对Spark的即席查询。

Hydrosphere Mist

另一个Spark as a Service应用程序。 Mist非常简单,类似于Livy和Spark Job Server。

用法非常相似

1)创建工作文件:

import io.hydrosphere.mist.MistJob

object MyCoolMistJob extends MistJob {
    def doStuff(parameters: Map[String, Any]): Map[String, Any] = {
        val rdd = context.parallelize()
        ...
        return result.asInstance[Map[String, Any]]
    }
} 

2)将作业文件打包到JAR中 3)向Mist发送请求:

curl --header "Content-Type: application/json" -X POST http://mist_http_host:mist_http_port/jobs --data '{"path": "/path_to_jar/mist_examples.jar", "className": "SimpleContext$", "parameters": {"digits": [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]}, "namespace": "foo"}'

我可以在Mist中看到的一个强大功能是它通过MQTT为流媒体作业提供开箱即用的支持。

Apache Toree

创建

Apache Toree是为了实现Spark的简单交互式分析。它不需要构建任何JAR。它通过IPython协议工作,但不仅支持Python。

目前文档侧重于Jupyter笔记本支持,但也有REST风格的API。

比较和结论

我列出了几个选项:

  1. SparkLauncher
  2. Spark REST API
  3. Livy REST服务器和Spark作业服务器
  4. Hydrosphere Mist
  5. Apache Toree
  6. 所有这些都适用于不同的用例。我可以区分几个类别:

    1. 需要带有作业的JAR文件的工具:Spark Launcher,Spark REST API
    2. 互动和预先打包工作的工具:Livy,SJS,Mist
    3. 专注于交互式分析的工具:Toree(但可能会对预先打包的作业提供一些支持;此时不会发布任何文档)
    4. SparkLauncher非常简单,是Spark项目的一部分。您正在使用普通代码编写作业配置,因此它比JSON对象更容易构建。

      对于完全RESTful风格的提交,请考虑Spark REST API,Livy,SJS和Mist。其中三个是稳定的项目,有一些生产用例。 REST API还要求预先打包作业,而Livy和SJS不需要。但是请记住,Spark REST API在每个Spark发行版中都是默认的,而Livy / SJS则不是。我不太了解Mist,但是 - 过了一段时间 - 它应该是整合所有类型Spark工作的非常好的工具。

      Toree专注于互动工作。它仍在孵化,但即使是现在你也可以检查它的可能性。

      为什么在内置REST API时使用自定义的附加REST服务?像Livy这样的SaaS是Spark的一个切入点。它管理Spark上下文,并且只在一个节点上,而不是在群集之外的其他地方。它们还支持交互式分析。 Apache Zeppelin使用Livy将用户代码提交给Spark

答案 1 :(得分:6)

这里有SparkLauncherT.Gawęda提到的一个例子:

SparkAppHandle handle = new SparkLauncher()
    .setSparkHome(SPARK_HOME)
    .setJavaHome(JAVA_HOME)
    .setAppResource(SPARK_JOB_JAR_PATH)
    .setMainClass(SPARK_JOB_MAIN_CLASS)
    .addAppArgs("arg1", "arg2")
    .setMaster("yarn-cluster")
    .setConf("spark.dynamicAllocation.enabled", "true")
    .startApplication();

Here您可以在单个项目中找到捆绑了Spark作业的Java Web应用程序示例。通过SparkLauncher,您可以获得SparkAppHandle,以获取有关工作状态的信息。如果您需要进度状态,可以使用Spark rest-api

http://driverHost:4040/api/v1/applications/[app-id]/jobs

SparkLauncher所需的唯一依赖项:

<dependency>
    <groupId>org.apache.spark</groupId>
    <artifactId>spark-launcher_2.10</artifactId>
    <version>2.0.1</version>
</dependency>

答案 2 :(得分:0)

您可以使用PredictionIO PredictionIO,面向开发人员和ML工程师的机器学习服务器。  https://github.com/apache/predictionio

答案 3 :(得分:0)

我觉得你可以试试SparkSQL JDBC的方式。

首先,您应该使用命令 ./dev/make-distribution.sh --name custom-spark --tgz -PR -Phive -Phive-thriftserver -Pyarn -Dhadoop.version=3.2.0 克隆 spark 源代码和 rebuild,不同的 jar 版本可能会导致兼容运行时错误。

第二,安装上述包并启动thriftserver sbin/start-thriftserver.sh --master yarn --deploy-mode client

然后可以使用beeline来测试JDBC是否工作正常。