spark分布式计算框架

MapReduce是计算逻辑清晰的,只有两个步骤,任务是JVM进程级别,每执行到什么步骤 去申请具体的资源。

而spark根本不知道具体有几个stage,逻辑未知,每个人的job stage等根本不知道。它是默认倾向于抢占资源的,他会在sparkContext()这个函数执行的时候,直接根据下面textFile()代码逻辑抢占所有资源,任务以JVM线程的级别泡在Excutor里面

目前已知的: 每一个Excutor里面的就是一个job的stage,一个excutor跑在某一个节点,等需要shuffle的时候,另一个节点通过他的excutor把刚才的数据拿过来


Spark-Core源码解析:

首先 这些都是分布式计算框架,不同个体对象之间要使用RPC

!!!!!!!!!!!!!!!

Spark Master启动流程及源码详解_ustbxyls的博客-优快云博客

1. RPC

 下图为Master.scala里面 start-master.sh的具体流程

 RPC也就是发送方与接收方通过传输层进行远程通信连接,来调用对方远程的服务。传输层里面最代表的就是Netty,他把各种IO进行了封装了只提供相应接口。

除此之外,不同主机可能会有多个进程进行传输,所以在通信时可以指定传输目标的IO,防止接收混乱。

分发 与 队列设置也是帮助多个实体进行传输。

内部的inbox是为了暂时存储,方便未来看给自己的哪个函数调用,他才是具体的处理东西的对象。

除此之外 ,还要设定消息投递规则,如接收不到就重发 或者 只发一次等

什么是 RPC 框架 - jiuchengi - 博客园


 2. start-master首先要创建RpcEnv环境

一共分为两部分 Dispatcher(分发器)和传输服务(Netty)

Dispatcher 就是那个用来分发处理的   postMessage来生成data放入receive队列里面,threadpool线程池来使用死循环处理信息,根据信息具体内容实现不同 分发 操作

传输服务:

 上图是spark-core Master.scala里 RpcEnv(就是包含了分发dispatcher 以及传输层Netty)里的源码 是传输服务这一部分(通过startServer开启),也就是具体的Netty实现

上面的Loop就是一个类似死循环,不能让线程频繁的创建消亡,只开通

下面bootstrap里面的channel可以直接实现接收读取数据或者发送数据,以往写java的时候必须要实现input类和output类,而这里一个channel就可以直接实现读写操作,具体实现在里面的Handler里面,Handler就是实现了区分读取和写数据,然后将数据使用RpcEnv里的postMessage保存起来(应该是对应于那个写进队列操作)。而这个postMessage就是DIspatcher里的方法


3.经过创建RpcEnv环境后(Dispatcher和传输层Netty等之后),开始注册Master信息。

在这个脚本里面,他只注册了Master这一个endpoint

最终结果就是利用rpcEnv创建EndPoint(Master)和 EndPointRef(Master的引用) 这个引用是Master的,但是如果对方主机获得了这个引用,就可以使用send方法给Master传信息(在未来的start-worker.sh脚本里面)

(在这个脚本里面 它的作用主要有两个:
(1)创建 Master对象, 该对象就是一个 RpcEndpoint, 在 RpcEnv 中注册这个 RpcEndpoint
(2)返回该 RpcEndpoint 的引用(master 的RpcEndpointRef))

首先Master就是继承于 EndPoint     里面重写了receive方法 这个是 大前提

方法中想创建的EndPoint(启动Master角色)返回的是一个引用EndPointRef,EndPoint有receive和receiveAndReplay方法用来接收引用传的数据(send方法和ask方法),根据引用传不同的数据 相应不同的方法(对应于不同的角色)

这里的EndPoint主要是针对不同角色和Master进行交涉的时候,比如Driver想申请资源,创建Master的引用传入message为Driver信息,一般来说一个EndPoint对应多个EndPointRef,

这种思想类似于接口 ref就是接口实现

在rpcenv里面注入master实体这个endpoint

并等待未来处理各类endpoint请求

val masterEndpoint = rpcEnv.setupEndpoint(ENDPOINT_NAME,
  new Master(rpcEnv, rpcEnv.address, webUiPort, securityMgr, conf))
    // name是endpoint的name endpoint这里是master 
 def registerRpcEndpoint(name: String, endpoint: RpcEndpoint): NettyRpcEndpointRef = {
    val addr = RpcEndpointAddress(nettyEnv.address, name) //别台主机的名字但是放 master的地址
    val endpointRef = new NettyRpcEndpointRef(nettyEnv.conf, addr, nettyEnv) 
    //endpointRef就存着另一台主机端点 他的端口号主机地址等
    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
  }

里面会将各类主机信息注册到分发器Dispatcher,同时在填写分发器内部数据EndpointData时候,填的数据里面有个inbox来处理具体东西,他会先有个一个同步操作 即

inbox.synchronized {
  messages.add(OnStart)
}

这个操作会将启动进程放入message未来的队列里面,未来多线程运行的时候,他就会先启动。标志着start-master的开始。(它是由初始化inbox的时候生成的,所以先于所有其他端点信息进入队列)

后续的队列处理才会处理那些天的endpoints

也就是

val masterEndpoint = rpcEnv.setupEndpoint(ENDPOINT_NAME,
  new Master(rpcEnv, rpcEnv.address, webUiPort, securityMgr, conf))

这一步 不仅注册了端点信息,还实现了startmaster,都是通过放入dispatcher处理队列里面实现的


start-worker.sh流程

同样的RPCEnv环境初始化,同样的注册自己这个worker信息,同样的inbox里面onStart()启动自己这个worker环境。

在启动之后 调用onStart()方法,里面会连接Master传递信息。首先是用Master的address和名字创建Master的引用(引用就是给别人调用的,别人用我的引用给我传消息)。然后发送自己要注册的信息

RegisterWorker(
  workerId,
  host,
  port,
  self,
  cores,
  memory,
  workerWebUiUrl,
  masterEndpoint.address))

Master的receive方法接收到之后,返回响应信息,Worker接收到之后,和Master不停的建立心跳连接。

 

### Spark 分布式计算框架概述 Spark 是一种快速通用的大规模数据处理引擎,专为速度、易用性和复杂分析而设计。相较于传统的 MapReduce 框架Spark 提供了更高的灵活性和效率[^3]。 #### 主要特点 - **内存计算**:通过将中间结果存储在内存中减少磁盘I/O操作。 - **丰富的API接口**:除了基本的转换和动作外,还提供机器学习库MLlib、图形处理GraphX等功能模块[^2]。 - **兼容性好**:能够很好地集成Hadoop生态系统中的其他组件如YARN、Hive等,并且可以直接读取来自多种数据源的数据文件。 #### 工作原理 Spark 的核心概念是弹性分布式数据集(Resilient Distributed Datasets, RDD)。这是一种不可变的容错集合对象,可以被显式分区到集群节点上执行并行运算。当遇到失败时,可以通过血缘关系重新构建丢失的部分而不必重做整个任务。此外,在实际应用过程中通常还会涉及到DAG调度器来优化作业流程以及Shuffle过程用于跨阶段传递数据[^4]。 ```python from pyspark import SparkContext sc = SparkContext(appName="WordCount") text_file = sc.textFile("hdfs://...") counts = text_file.flatMap(lambda line: line.split()) \ .map(lambda word: (word, 1)) \ .reduceByKey(lambda a, b: a + b) counts.saveAsTextFile("hdfs://.../output") ``` 这段简单的Python代码展示了如何利用PySpark来进行单词计数的任务。首先创建了一个`SparkContext`实例连接至集群;接着加载输入文本文件形成RDD;之后经过一系列变换操作最终保存输出结果回到指定位置。 #### 使用教程 为了更好地理解和掌握Spark,可以从以下几个方面入手: 1. 安装配置环境变量确保本地开发工具链正常工作; 2. 学习基础语法包括但不限于RDD编程范式及其常用算子; 3. 探索高级特性例如DataFrame/Dataset API的应用场景; 4. 实践案例研究深入理解不同业务逻辑下的最佳实践方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值