概述
本文主要介绍RpcEnv.scala中三个Class/Object。
1. RpcEnv
1.1 Object RpcEnv
rpcenv实现必须具有具有空构造函数的[[rpcenvfactory]]实现,以便可以通过反射创建它
private[spark] object RpcEnv {
def create(
name: String,
host: String,
port: Int,
conf: SparkConf,
securityManager: SecurityManager,
clientMode: Boolean = false): RpcEnv = {
create(name, host, host, port, conf, securityManager, 0, clientMode)
}
def create(
name: String,
bindAddress: String,
advertiseAddress: String,
port: Int,
conf: SparkConf,
securityManager: SecurityManager,
numUsableCores: Int,
clientMode: Boolean): RpcEnv = {
val config = RpcEnvConfig(conf, name, bindAddress, advertiseAddress, port, securityManager,
numUsableCores, clientMode)
new NettyRpcEnvFactory().create(config)
}
}
1.2 Abstract Class RpcEnv
*rpc环境。[[rpcendpoint]]s需要用名称注册到[[rpcenv]]才能接收消息。然后,[[rpcenv]]将处理从[[rpcendpointref]]或远程节点发送的消息,并将它们传递到相应的[[rpcendpoint]]s。对于由[[rpcenv]]捕获的未捕获异常,[[rpcenv]]将使用[[rpccallcontext.sendfailure]]将异常发送回发送方,或者在没有发件人或“NotSerializableException”的情况下记录它们。。
*
*[[rpcenv]]还提供了一些方法来检索[rpcendpointref]]的给定名称或uri。
private[spark] abstract class RpcEnv(conf: SparkConf) {
private[spark] val defaultLookupTimeout = RpcUtils.lookupRpcTimeout(conf)
/**
* *返回注册的[[rpcendpoint]]的rpcendpointref。
* 将用于实现[[rpcendpoint.self]]。如果相应的[[rpcendpointref]]不存在,则返回“null”
*/
private[rpc] def endpointRef(endpoint: RpcEndpoint): RpcEndpointRef
/**
* 返回[[RpcEnv]]正在监听的地址
*/
def address: RpcAddress
/**
* 用名称注册一个[[rpcendpoint]]并返回其[[rpcendpointref]]。
* [[rpcenv]]不能保证线程安全。
*/
def setupEndpoint(name: String, endpoint: RpcEndpoint): RpcEndpointRef
/**
* 异步检索由“uri”表示的[[rpcendpointref]]
*/
def asyncSetupEndpointRefByURI(uri: String): Future[RpcEndpointRef]
/**
* 检索由“uri”表示的[[rpcendpointref]]。这是阻塞行为。
*/
def setupEndpointRefByURI(uri: String): RpcEndpointRef = {
defaultLookupTimeout.awaitResult(asyncSetupEndpointRefByURI(uri))
}
/**
* *检索由“address”和“endpointname”表示的[[rpcendpointref]]。
* 这是阻塞行为。
*/
def setupEndpointRef(address: RpcAddress, endpointName: String): RpcEndpointRef = {
setupEndpointRefByURI(RpcEndpointAddress(address, endpointName).toString)
}
/**
* stop[[rpcendpoint]]由“endpoint”指定
*/
def stop(endpoint: RpcEndpointRef): Unit
/**
* 异步关闭此[[rpcenv]]。如果需要确保[[rpcenv]]成功退出,
* 请在[[shutdown()]]之后直接调用[[awaittemination()]]。
*/
def shutdown(): Unit
/**
* Wait until [[RpcEnv]] exits.
* 在[[RpcEnv]]退出之前保持等待
* TODO do we need a timeout parameter?
*/
def awaitTermination(): Unit
/**
* *没有[[rpcenv]]无法反序列化[[rpcendpointref]]。
* 因此,当反序列化任何包含[[rpcendpointref]]s的对象时,反序列化代码应该用此方法包装。
*/
def deserialize[T](deserializationAction: () => T): T
/**
* *返回用于提供文件的文件服务器的实例。
* 如果rpcenv未在服务器模式下运行,则此值可能为“null”。
*/
def fileServer: RpcEnvFileServer
/**
* *打开一个通道从给定的uri下载文件。
* 如果rpcenvfileserver返回的uri使用“spark”方案,那么utils类将调用此方法来检索文件
* @param uri URI with location of the file.
*/
def openChannel(uri: String): ReadableByteChannel
}
2. Trait RpcEnvFileServer
文件服务器可以返回由公共库(如“http”或“hdfs”)处理的uri,也可以返回由“rpcenv#fetchfile处理的“spark”uri`
private[spark] trait RpcEnvFileServer {
// * 添加要由此rpcenv提供服务的文件。当文件存储在驱动程序的本地文件系统中时,它用于将文件从驱动程序提供给执行程序。
def addFile(file: File): String
// * 添加要由此rpcenv提供服务的文件。与addFile相似。
def addJar(file: File): String
// * 通过fileServer来设置一些本地文件加以供存储
def addDirectory(baseUri: String, path: File): String
// 确认并标准化用于访问文件夹的URI
protected def validateDirectoryUri(baseUri: String): String = {
val fixedBaseUri = "/" + baseUri.stripPrefix("/").stripSuffix("/")
require(fixedBaseUri != "/files" && fixedBaseUri != "/jars",
"Directory URI cannot be /files nor /jars.")
fixedBaseUri
}
}
3. RpcConfig
private[spark] case class RpcEnvConfig(
conf: SparkConf,
name: String,
bindAddress: String,
advertiseAddress: String,
port: Int,
securityManager: SecurityManager,
numUsableCores: Int,
clientMode: Boolean
)