spark涉及的模式-创建型- 建造者模式
定义:
将一个复杂的构造和他的表示分离,是的相同的构建过程可以创建不同的表示
该模式的应用
该模式主要关注于各种部件的组装问题。
回想Spark1.X时代,那是想要使用一个Spark环境就必须创建一个SparkConf,然后将它传入一个SparkContext的构造方法内。当然了还有sqlContext和hiveContext。这些由用户自行创建都是比较凌乱的,没有进行统一的管理。当Spark买入了2.x的时代,这些东西统一由SparkSession进行管理。
那么这和建造者模式有什么关系呢?这是因为创建SparkSession的过程使用了建造者模式。
建造者模式角色结构
- 产品 Product: 他是包含多个组件的复杂对象,由建造者创建其各个复杂的组件。
- 抽象建造者 Builder: 他是一个包含创建各个复杂组件的接口,一般会包含一个返回具体产品实例的一个方法(在SparkSession中对应getOrCreate方法)
- 具体建造者Concrete Builder: 实现Builder接口的具体类,由他完成各个复杂组件的构建
- 指挥者Director:调用建造者中不见构造和装备方法完成创建
但是你细品,在Spark中什么抽象建造者和指挥者都没有。这是因为在只创建一个产品的时候他们是可以省略的。 因此在这里仅仅有需要创建的产品SparkSession和具体的建造者
具体实现
object SparkSession extends Logging {
class Builder extends Logging {
def getOrCreate(): SparkSession = synchronized {
assertOnDriver()
// Get the session from current thread's active session.
var session = activeThreadSession.get()
if ((session ne null) && !session.sparkContext.isStopped) {
applyModifiableSettings(session)
return session
}
// Global synchronization so we will only set the default session once.
SparkSession.synchronized {
// If the current thread does not have an active session, get it from the global session.
session = defaultSession.get()
if ((session ne null) && !session.sparkContext.isStopped) {
applyModifiableSettings(session)
return session
}
// No active nor global default session. Create a new one.
val sparkContext = userSuppliedContext.getOrElse {
val sparkConf = new SparkConf()
options.foreach { case (k, v) => sparkConf.set(k, v) }
// set a random app name if not given.
if (!sparkConf.contains("spark.app.name")) {
sparkConf.setAppName(java.util.UUID.randomUUID().toString)
}
SparkContext.getOrCreate(sparkConf)
// Do not update `SparkConf` for existing `SparkContext`, as it's shared by all sessions.
}
applyExtensions(
sparkContext.getConf.get(StaticSQLConf.SPARK_SESSION_EXTENSIONS).getOrElse(Seq.empty),
extensions)
session = new SparkSession(sparkContext, None, None, extensions)
options.foreach { case (k, v) => session.initialSessionOptions.put(k, v) }
setDefaultSession(session)
setActiveSession(session)
registerContextListener(sparkContext)
}
return session
}
//省略若干代码
}
}
现在可以一键创建所有Spark环境的执行入口全家桶,这就是建造者模式带来的功劳。有意思的是这个代码是在伴生对象中写的,那么相当于在单例模式中使用这个建造者。