在Scala中创建SparkSession对象以在unittest和spark-submit中使用它们的最佳实践

时间:2017-07-31 04:20:17

标签: scala apache-spark spark-submit

我试图将DataFrame的转换方法写入DataFrame。 而且我也想通过scalatest进行测试。

如您所知,在使用Scala API的Spark 2.x中,您可以按如下方式创建SparkSession对象:

Exec AProc_Getback '512888,512889'

此代码适用于单元测试。 但是,当我使用spark-submit运行此代码时,群集选项不起作用。 例如,

import org.apache.spark.sql.SparkSession

val spark = SparkSession.bulider
     .config("spark.master", "local[2]")
     .getOrCreate()

不会创建任何执行者。

我发现当我删除上述代码的spark-submit --master yarn --deploy-mode client --num-executors 10 ... 部分时会应用spark-submit参数。 但是,没有主设置,单元测试代码就不起作用。

我试图将spark(SparkSession)对象生成部分拆分为test和main。 但是需要火花的代码块太多了,例如config("master", "local[2]")import spark.implicit,_

有没有最好的做法来编写代码来创建spark对象来测试和运行spark-submit?

4 个答案:

答案 0 :(得分:4)

一种方法是创建一个提供SparkContext / SparkSession的特征,并在测试用例中使用它,如下所示:

trait SparkTestContext {
  private val master = "local[*]"
  private val appName = "testing"
  System.setProperty("hadoop.home.dir", "c:\\winutils\\")
  private val conf: SparkConf = new SparkConf()
    .setMaster(master)
    .setAppName(appName)
    .set("spark.driver.allowMultipleContexts", "false")
    .set("spark.ui.enabled", "false")

  val ss: SparkSession = SparkSession.builder().config(conf).enableHiveSupport().getOrCreate()
  val sc: SparkContext = ss.sparkContext
  val sqlContext: SQLContext = ss.sqlContext
}

然后您的测试类标题如下所示:

class TestWithSparkTest extends BaseSpec with SparkTestContext with Matchers{

答案 1 :(得分:1)

我制作了一个版本,测试后Spark会正确关闭。

import org.apache.spark.sql.{SQLContext, SparkSession}
import org.apache.spark.{SparkConf, SparkContext}
import org.scalatest.{BeforeAndAfterAll, FunSuite, Matchers}

trait SparkTest extends FunSuite with BeforeAndAfterAll with Matchers {
  var ss: SparkSession = _
  var sc: SparkContext = _
  var sqlContext: SQLContext = _

  override def beforeAll(): Unit = {
    val master = "local[*]"
    val appName = "MyApp"
    val conf: SparkConf = new SparkConf()
      .setMaster(master)
      .setAppName(appName)
      .set("spark.driver.allowMultipleContexts", "false")
      .set("spark.ui.enabled", "false")

    ss = SparkSession.builder().config(conf).getOrCreate()

    sc = ss.sparkContext
    sqlContext = ss.sqlContext
    super.beforeAll()
  }

  override def afterAll(): Unit = {
    sc.stop()
    super.afterAll()
  }
}

答案 2 :(得分:1)

带有参数--master yarn的spark-submit命令正在设置纱线master。 即使您使用master(“ yarn”)之类的代码,这也会与您的代码master(“ x”)冲突。

如果您想使用toDF,toDS或其他func之类的import sparkSession.implicits._, 您可以只使用如下创建的本地sparkSession变量:

val spark = SparkSession.builder()。appName(“ YourName”)。getOrCreate()

未在spark-submit --master纱线中设置master(“ x”),而不在本地机器中设置。

我建议:不要在代码中使用全局sparkSession。这可能会导致某些错误或异常。

希望这对您有所帮助。 祝你好运!

答案 3 :(得分:0)

如何定义一个方法,在该对象中方法创建SparkSession的单例实例,如MySparkSession.get(),并在每个单元测试中将其作为参数传递。

在main方法中,您可以创建一个单独的SparkSession实例,该实例可以有不同的配置。