SparkEnv是Spark的执行环境对象,其中包括与众多Executor执行相关的对象。在local模式下Driver会创建Executor,local-cluster部署模式或者Standalone部署模式下Worker另起的CoarseGrainedExecutorBackend进程中也会创建Executor,所以SparkEnv存在于Driver或者CoarseGrainedExecutorBackend进程中。创建SparkEnv主要使用SparkEnv的createDriverEnv方法,有四个参数:conf、isLocal、listenerBus 以及在本地模式下driver运行executor需要的numberCores。
// 是否是本地模式
def isLocal: Boolean = (master == "local" || master.startsWith("local["))
// 采用监听器模式维护各类事件的处理
// An asynchronous listener bus for Spark events
private[spark] val listenerBus = new LiveListenerBus
...
/**
* 获取在本地模式下执行程序需要的cores个数,否则为0
* The number of driver cores to use for execution in local mode, 0 otherwise.
*/
private[spark] def numDriverCores(master: String): Int = {
def convertToInt(threads: String): Int = {
if (threads == "*") Runtime.getRuntime.availableProcessors() else threads.toInt
}
master match {
case "local" => 1
case SparkMasterRegex.LOCAL_N_REGEX(threads) => convertToInt(threads)
case SparkMasterRegex.LOCAL_N_FAILURES_REGEX(threads, _) => convertToInt(threads)
case _ => 0 // driver is not used for execution
}
}
...
// This function allows components created by SparkEnv to be mocked in unit tests:
private[spark] def createSparkEnv(
conf: SparkConf,
isLocal: Boolean,
listenerBus: LiveListenerBus): SparkEnv = {
SparkEnv.createDriverEnv(conf, isLocal, listenerBus, SparkContext.numDriverCores(master))
}
SparkEnv的构造步骤如下:
1. 创建安全管理器SecurityManager;
2. 创建RpcEnv;
3. 创建基于Akka的分布式消息系统ActorSystem(注意:Spark 1.4.0之后已经废弃了)
4. 创建Map任务输出跟踪器MapOutputTracker;
5. 创建ShuffleManager;
6. 内存管理器MemoryManager;
7. 创建块传输服务NettyBlockTransferService;
8. 创建BlockManagerMaster;
9. 创建块管理器BlockManager;
10. 创建广播管理器BroadcastManager;
11. 创建缓存管理器CacheManager;
12. 创建测量系统MetricsSystem;
13. 创建OutputCommitCoordinator;
14. 创建SparkEnv
1. 创建安全管理器SecurityManager
SecurityManager主要对权限、账号进行设置,如果使用Hadoop YARN作为集群管理器,则需要使用证书生成secret key登录,最后给当前系统设置默认的口令认证实例,此实例采用的是匿名内部类:
private val secretKey = generateSecretKey()
...
// 使用HTTP链接设置口令认证
// Set our own authenticator to properly negotiate user/password for HTTP connections.
// This is needed by the HTTP client fetching from the HttpServer. Put here so its
// only set once.
if (authOn) {
Authenticator.setDefault(
// 创建口令认证实例,复写PasswordAuthentication方法,获得用户名和密码
new Authenticator() {
override def getPasswordAuthentication(): PasswordAuthentication = {
var passAuth: PasswordAuthentication = null
val userInfo = getRequestingURL().getUserInfo()
if (userInfo != null)