Spark分布式消息发送流程

Spark集群中涉及分布式节点之间的通信,例如Worker启动注册信息到Master,这个过程就有消息的传输,接下来将要分析一下消息的传输过程。首先Worker的启动还是从main方法开始,之后运行期初始化OnStart方法调用registerWithMaster完成Worker向Master的注册,registerWithMaster经过一系列调用最后调用org.apache.spark.deploy.worker.Worker#registerWithMaster方法开始真正向Master发起注册信息:

  /** 向master注册worker
    *
    * @param masterEndpoint
    */
  private def registerWithMaster(masterEndpoint: RpcEndpointRef): Unit = {
    //RegisterWorker是向Master发送的消息
    masterEndpoint.ask[RegisterWorkerResponse](RegisterWorker(workerId, host, port, self, cores, memory, workerWebUiUrl))
      .onComplete {
        // This is a very fast action so we can use "ThreadUtils.sameThread"
        case Success(msg) =>
          Utils.tryLogNonFatalError {
            handleRegisterResponse(msg)
          }
        case Failure(e) =>
          logError(s"Cannot register with master: ${masterEndpoint.address}", e)
          System.exit(1)
      }(ThreadUtils.sameThread)
  }


接下来调用org.apache.spark.rpc.RpcEndpointRef#ask方法发送消息:

 def ask[T: ClassTag](message: Any): Future[T] = ask(message, defaultAskTimeout)

接下来调用org.apache.spark.rpc.netty.NettyRpcEndpointRef#ask方法:

 override def ask[T: ClassTag](message: Any, timeout: RpcTimeout): Future[T] = {
    //this 是NettyRpcEndpointRef的引用,为了让消息接收到容易知道消息发送者
    nettyEnv.ask(RequestMessage(nettyEnv.address, this, message), timeout)
  }

在调用org.apache.spark.rpc.netty.NettyRpcEnv#ask方法:

  private[netty] def ask[T: ClassTag](message: RequestMessage, timeout: RpcTimeout): Future[T] = {
		//省略部分代码
    try {
      if (remoteAddr == address) {
        val p = Promise[Any]()
        p.future.onComplete {
          case Success(response) => onSuccess(response)
          case Failure(e) => onFailure(e)
        }(ThreadUtils.sameThread)
        //本地消息
        dispatcher.postLocalMessage(message, p)
      } else {
        //外部节点消息
        val rpcMessage = RpcOutboxMessage(serialize(message),
          onFailure,
          (client, response) => onSuccess(deserialize[Any](client, response)))
        //发送消息
        postToOutbox(message.receiver, rpcMessage)
        promise.future.onFailure {
          case _: TimeoutException => rpcMessage.onTimeout()
          case _ =>
        }(ThreadUtils.sameThread)
      }
		//省略部分代码
  }

接下来调用org.apache.spark.rpc.netty.NettyRpcEnv#postToOutbox方法:

  private def postToOutbox(receiver: NettyRpcEndpointRef, message: OutboxMessage): Unit = {
    if (receiver.client != null) {
      //TODO 使用当前接受者的endpointref的TransportClient传输消息
      message.sendWith(receiver.client)
    } else {
      require(receiver.address != null,
        "Cannot send message to client endpoint with no listen address.")
      val targetOutbox = {
        //TODO RpcAddress和Outbox的映射
        val outbox = outboxes.get(receiver.address)
        if (outbox == null) {
          val newOutbox = new Outbox(this, receiver.address)
          val oldOutbox = outboxes.putIfAbsent(receiver.address, newOutbox)
          if (oldOutbox == null) {
            newOutbox
          } else {
            oldOutbox
          }
        } else {
          outbox
        }
      }
      if (stopped.get) {
        // It's possible that we put `targetOutbox` after stopping. So we need to clean it.
        outboxes.remove(receiver.address)
        targetOutbox.stop()
      } else {
        targetOutbox.send(message)
      }
    }
  }

接下来调用org.apache.spark.rpc.netty.OutboxMessage#sendWith方法。再调用org.apache.spark.network.client.TransportClient#send方法进行消息发送,TransportClient的send方法实现为:

  public void send(ByteBuffer message) {
    channel.writeAndFlush(new OneWayMessage(new NioManagedBuffer(message)));
  }

到此就完成消息的发送了,通过查看TransportClient代码我们可以发现有其他传输数据的方法,TransportClient充当通信的客户端。







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
电表数据的分布式储存流程可以包括以下几个步骤: 1. 数据采集:电表数据的采集通常通过电表设备进行,可以是自动读取或手动记录。采集到的数据可以包括电表读数、时间戳、电流、电压等信息。 2. 数据传输:采集到的电表数据需要传输到分布式储存系统,可以通过网络传输或其他方式将数据发送到储存系统中。传输过程中可以加密和压缩数据以保证数据的安全和传输效率。 3. 数据分区:在分布式储存系统中,电表数据需要进行分区,将数据分散存储在不同的节点上。分区可以按照地理位置、电表类型、时间等因素进行,以便后续的查询和计算操作。 4. 数据存储:将分区后的电表数据存储在各个节点上,可以使用分布式文件系统(如HDFS)或分布式数据库(如HBase、Cassandra)进行存储。存储过程中可以进行数据冗余和备份,以提高数据的可靠性和可用性。 5. 数据索引:为了方便查询和检索,对电表数据进行索引操作。索引可以基于特定的字段(如时间戳、地理位置)或自定义的标识符进行,以提高数据的访问效率。 6. 数据备份和恢复:定期对分布式储存系统中的电表数据进行备份,以防止数据丢失或损坏。备份可以采用多副本或异地备份的方式,确保数据的安全性和可靠性。在需要恢复数据时,可以通过备份进行数据恢复操作。 7. 数据访问和处理:通过查询和计算操作对电表数据进行访问和处理。可以使用分布式计算框架(如Hadoop、Spark)进行数据分析、统计和挖掘,以获得有价值的信息和结果。 以上是电表数据分布式储存的一般流程,具体的实施方式可以根据实际需求和系统架构进行调整和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值