spark源码学习 -worker启动消息通信,inbox,outbox创建

注意:建议各位看如下代码,一定要导入一份源码到自己本地电脑中哦,可以导入进行调试。流程代码我删除许多,保留重点。

本章主要介绍的是,worker 开启,并与master通信流程,以及inbox收件箱outbox发件箱的创建。认真学习你可以收获许多哦,举例使用该inbox,outbox处理模式,可以嵌入到聊天程序当中哦,处理高并发请求。

废话不多说,进入主题。
spark业务操作和数据传输相隔里,数据传输就交给netty,netty不涉及业务,提高netty服务器的响应时间,提高代码的复用性,降低耦合性。work类中有许多业务处理逻辑,scale编写,数据消息传输netty Java编写。

worker 服务开启通信,需要一个开启远程通信环境RpcEnv。创建inbox收件箱outbox发件箱对消息进行收取转发。
具体worker创建,与master通信过程如下:
在这里插入图片描述
worker开启流程图

**开启worker步骤:**按顺序读

①Worker类: val rpcEnv = RpcEnv.create(systemName, host, port, conf, securityMgr)//开启worker服务入口类
②RpcEnv类
def create(。。。){
new NettyRpcEnvFactory().create(config)
}
③NettyRpcEnvFactory 类
def create(config: RpcEnvConfig): RpcEnv = {
val nettyEnv = new NettyRpcEnv(。。。。)
nettyEnv.startServer(config.bindAddress, actualPort)
}

④NettyRpcEnv类
{
private val dispatcher: Dispatcher = new Dispatcher(this, numUsableCores)
private val transportContext = new TransportContext(transportConf,new NettyRpcHandler(dispatcher, this, streamManager))
private val clientFactory = transportContext.createClientFactory(createClientBootstraps())

def startServer(bindAddress: String, port: Int): Unit = {
server = transportContext.createServer(bindAddress, port, bootstraps)//创建netty server 服务,即worker server服务进程
dispatcher.registerRpcEndpoint( RpcEndpointVerifier.NAME, new RpcEndpointVerifier(this, dispatcher))//注册验证
}

⑤dispatcher类
registerRpcEndpoint(name: String, endpoint: RpcEndpoint): NettyRpcEndpointRef = {
val addr = RpcEndpointAddress(nettyEnv.address, name)
val endpointRef = new NettyRpcEndpointRef(nettyEnv.conf, addr, nettyEnv)
endpoint match {
case e: IsolatedRpcEndpoint =>
new DedicatedMessageLoop(name, e, this)
case _ =>
sharedLoop.register(name, endpoint)//sharedLoop 延迟装载,装载时开启⑥,不断轮询 inbox ,worker开启调用两次registerRpcEndpoint()方法,如下图
}
在这里插入图片描述
Worker类中
rpcEnv.setupEndpoint(ENDPOINT_NAME, new Worker(rpcEnv, webUiPort, cores, memory,masterAddresses, ENDPOINT_NAME, workDir, conf, securityMgr, resourceFileOpt))//该方法直接向master发送onstart 消息。
在这里插入图片描述

⑥ SharedMessageLoop类:先初始化
override protected val threadpool: ThreadPoolExecutor = {
val numThreads = getNumOfThreads(conf)
val pool = ThreadUtils.newDaemonFixedThreadPool(numThreads, “dispatcher-event-loop”)
for (i <- 0 until numThreads) {
pool.execute(receiveLoopRunnable)
}
pool
}
⑦ MessageLoop类:SharedMessageLoop父类
{
protected val receiveLoopRunnable = new Runnable() {
override def run(): Unit = receiveLoop()
}
private def receiveLoop(): Unit = {
try {
while (true) {
val inbox = active.take()//该方法空阻塞 await
inbox.process(dispatcher)
}
⑧Inbox类
inbox.synchronized {
messages.add(OnStart)//类初始化时添加OnStart 开启消息
}
def process(dispatcher: Dispatcher): Unit = {
message = messages.poll()
message match {
case RpcMessage(_sender, content, context) => endpoint.receiveAndReply(context)
case OneWayMessage(sender, content) => endpoint.receive
case OnStart => endpoint.onStart() //endpoint分为验证和worker端点,验证处理空消息,worker处理onStart
case OnStop => endpoint.onStop()
case RemoteProcessConnected(remoteAddress) =>endpoint.onConnected(remoteAddress)
case RemoteProcessDisconnected(remoteAddress) => endpoint.onDisconnected(remoteAddress)
case RemoteProcessConnectionError(cause, remoteAddress) => endpoint.onNetworkError(cause, remoteAddress)
}
}
⑨Worker类
def onStart(): Unit = {
registerWithMaster()
}
def registerWithMaster(): Unit = {
registerMasterFutures = tryRegisterAllMasters()
}
private def tryRegisterAllMasters(): Array[JFuture[
]] = {
val masterEndpoint = rpcEnv.setupEndpointRef(masterAddress, Master.ENDPOINT_NAME)//创建master端点,注意该步还未创建netty远程客户端
sendRegisterMessageToMaster(masterEndpoint)
}
private def sendRegisterMessageToMaster(masterEndpoint: RpcEndpointRef): Unit = {
masterEndpoint.send(RegisterWorker( ))
}
⑩NettyRpcEndpointRef类
def send(message: Any): Unit = {
require(message != null, “Message is null”)
nettyEnv.send(new RequestMessage(nettyEnv.address, this, message))
}
def send(message: RequestMessage): Unit = {
postToOutbox(message.receiver, OneWayOutboxMessage(message.serialize(this)))
}
private def postToOutbox(receiver: NettyRpcEndpointRef, message: OutboxMessage): Unit = {
val newOutbox = new Outbox(this, receiver.address)
val oldOutbox = outboxes.putIfAbsent(receiver.address, newOutbox)
newOutbox =targetOutbox.send(message)
}

⑪OutBox类:
def send(message: OutboxMessage): Unit = {
messages.add(message)
drainOutbox()
}
def drainOutbox(): Unit = {
launchConnectTask()
message = messages.poll()
while (true) {
val _client = synchronized { client }
message.sendWith(_client)
}
private def launchConnectTask(): Unit = {
val _client = nettyEnv.createClient(address) //在这一步进行创建netty client,一步一步到TransportClientFactory类中创建
outbox.synchronized {
client = _client
outbox.synchronized { connectFuture = null }
}
⑫TransportClientFactory类
public TransportClient createClient(String remoteHost, int remotePort){
clientPool.clients[clientIndex] = createClient(resolvedAddress);//创建netty client
return clientPool.clients[clientIndex];
}

认真阅读本文至此,如本文对你有用处,希望点个赞哦。

作者:小亦
好好学习,天天向上

猜你喜欢

转载自blog.csdn.net/LinkStars/article/details/112982187
今日推荐