spark2.0 rpc.netty.Dispatcher
来源:互联网 发布:php解析xml字符串方法 编辑:程序博客网 时间:2024/05/14 07:01
Dispatcher 包含一个receivers的消息队列,消息队列中的对象类型是Endpoint,一个处理消息的线程池。当接收一个消息时,把消息放到相应Endpoint的inbox队列中,然后把这个Endpoint放到receiver中。线程池中的线程不断从receivers中取出Endpoint元素,然后处理该Endpoint的一个消息。
private[netty] class Dispatcher(nettyEnv: NettyRpcEnv) extends Logging { private class EndpointData( val name: String, val endpoint: RpcEndpoint, val ref: NettyRpcEndpointRef) { val inbox = new Inbox(ref, endpoint) } private val endpoints: ConcurrentMap[String, EndpointData] = new ConcurrentHashMap[String, EndpointData] private val endpointRefs: ConcurrentMap[RpcEndpoint, RpcEndpointRef] = new ConcurrentHashMap[RpcEndpoint, RpcEndpointRef] // Track the receivers whose inboxes may contain messages. private val receivers = new LinkedBlockingQueue[EndpointData] /** * True if the dispatcher has been stopped. Once stopped, all messages posted will be bounced * immediately. */ @GuardedBy("this") private var stopped = false def registerRpcEndpoint(name: String, endpoint: RpcEndpoint): NettyRpcEndpointRef = { val addr = RpcEndpointAddress(nettyEnv.address, name) val endpointRef = new NettyRpcEndpointRef(nettyEnv.conf, addr, nettyEnv) synchronized { if (stopped) { throw new IllegalStateException("RpcEnv has been stopped") } if (endpoints.putIfAbsent(name, new EndpointData(name, endpoint, endpointRef)) != null) { throw new IllegalArgumentException(s"There is already an RpcEndpoint called $name") } val data = endpoints.get(name) endpointRefs.put(data.endpoint, data.ref) receivers.offer(data) // for the OnStart message } endpointRef } def getRpcEndpointRef(endpoint: RpcEndpoint): RpcEndpointRef = endpointRefs.get(endpoint) def removeRpcEndpointRef(endpoint: RpcEndpoint): Unit = endpointRefs.remove(endpoint) // Should be idempotent private def unregisterRpcEndpoint(name: String): Unit = { val data = endpoints.remove(name) if (data != null) { data.inbox.stop() receivers.offer(data) // for the OnStop message } // Don't clean `endpointRefs` here because it's possible that some messages are being processed // now and they can use `getRpcEndpointRef`. So `endpointRefs` will be cleaned in Inbox via // `removeRpcEndpointRef`. } def stop(rpcEndpointRef: RpcEndpointRef): Unit = { synchronized { if (stopped) { // This endpoint will be stopped by Dispatcher.stop() method. return } unregisterRpcEndpoint(rpcEndpointRef.name) } } /** * Send a message to all registered [[RpcEndpoint]]s in this process. * * This can be used to make network events known to all end points (e.g. "a new node connected"). */ def postToAll(message: InboxMessage): Unit = { val iter = endpoints.keySet().iterator() while (iter.hasNext) { val name = iter.next postMessage(name, message, (e) => logWarning(s"Message $message dropped. ${e.getMessage}")) } } /** Posts a message sent by a remote endpoint. */ def postRemoteMessage(message: RequestMessage, callback: RpcResponseCallback): Unit = { val rpcCallContext = new RemoteNettyRpcCallContext(nettyEnv, callback, message.senderAddress) val rpcMessage = RpcMessage(message.senderAddress, message.content, rpcCallContext) postMessage(message.receiver.name, rpcMessage, (e) => callback.onFailure(e)) } /** Posts a message sent by a local endpoint. */ def postLocalMessage(message: RequestMessage, p: Promise[Any]): Unit = { val rpcCallContext = new LocalNettyRpcCallContext(message.senderAddress, p) val rpcMessage = RpcMessage(message.senderAddress, message.content, rpcCallContext) postMessage(message.receiver.name, rpcMessage, (e) => p.tryFailure(e)) } /** Posts a one-way message. */ def postOneWayMessage(message: RequestMessage): Unit = { postMessage(message.receiver.name, OneWayMessage(message.senderAddress, message.content), (e) => throw e) } /** * Posts a message to a specific endpoint. * * @param endpointName name of the endpoint. * @param message the message to post * @param callbackIfStopped callback function if the endpoint is stopped. */ private def postMessage( endpointName: String, message: InboxMessage, callbackIfStopped: (Exception) => Unit): Unit = { val error = synchronized { val data = endpoints.get(endpointName) if (stopped) { Some(new RpcEnvStoppedException()) } else if (data == null) { Some(new SparkException(s"Could not find $endpointName.")) } else { data.inbox.post(message) receivers.offer(data) None } } // We don't need to call `onStop` in the `synchronized` block error.foreach(callbackIfStopped) } def stop(): Unit = { synchronized { if (stopped) { return } stopped = true } // Stop all endpoints. This will queue all endpoints for processing by the message loops. endpoints.keySet().asScala.foreach(unregisterRpcEndpoint) // Enqueue a message that tells the message loops to stop. receivers.offer(PoisonPill) threadpool.shutdown() } def awaitTermination(): Unit = { threadpool.awaitTermination(Long.MaxValue, TimeUnit.MILLISECONDS) } /** * Return if the endpoint exists */ def verify(name: String): Boolean = { endpoints.containsKey(name) } /** Thread pool used for dispatching messages. */ private val threadpool: ThreadPoolExecutor = { val numThreads = nettyEnv.conf.getInt("spark.rpc.netty.dispatcher.numThreads", math.max(2, Runtime.getRuntime.availableProcessors())) val pool = ThreadUtils.newDaemonFixedThreadPool(numThreads, "dispatcher-event-loop") for (i <- 0 until numThreads) { pool.execute(new MessageLoop) } pool } /** Message loop used for dispatching messages. */ private class MessageLoop extends Runnable { override def run(): Unit = { try { while (true) { try { val data = receivers.take() if (data == PoisonPill) { // Put PoisonPill back so that other MessageLoops can see it. receivers.offer(PoisonPill) return } data.inbox.process(Dispatcher.this) } catch { case NonFatal(e) => logError(e.getMessage, e) } } } catch { case ie: InterruptedException => // exit } } } /** A poison endpoint that indicates MessageLoop should exit its message loop. */ private val PoisonPill = new EndpointData(null, null, null)}
0 0
- spark2.0 rpc.netty.Dispatcher
- rpc netty
- Netty-RPC
- Netty RPC框架
- netty rpc 框架
- RPC与netty
- Netty RPC demo 试跑
- Netty实现简单RPC
- spark2.0
- spark2.0
- Spark2.X 原码分析 ---- Rpc初探
- Spark2.x---3. RPC源码解析
- Spark RPC之Dispatcher、Inbox、Outbox
- RPC学习----------netty实现通讯
- RPC与Netty是什么鬼
- 3. [netty-RPC]--服务端程序设计
- Spark RPC之Netty启动
- Netty 实现简单RPC调用
- caffe 提取图像特征
- caffe code 理解-net.hpp-net.cpp
- 出现PerformSelector may cause a leak because its selector is unknown的问题
- SQL Server之存储过程基础知识
- 代码常见错误
- spark2.0 rpc.netty.Dispatcher
- EPM问题汇总之--ADF_FACES-60097报错
- Intellij Idea 建Maven新项目
- 常见的排序算法 附java代码 上
- Faster R-CNN CPU模式下安装与配置
- BeepComp & bcplayer 简介
- jQuery图片延迟加载插件jQuery.lazyload
- spark MLLib简介
- IOC即inverse of control 控制反转