Spark消息通信

本文深入探讨了Spark的通信机制,包括RpcEndpoint、RpcEnv、Dispatcher、Inbox、Outbox和TransportClient等关键组件的工作原理。RpcEndpoint作为通信实体,通过RpcEnv运行,Dispatcher负责消息分发。Inbox和Outbox分别用于存储本地和远程的消息,TransportClient处理消息发送。RpcEndpoint的send和ask方法用于发送消息,receive方法处理接收的消息,整个过程涉及多线程和阻塞队列的协调工作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二、Spark通信机制

2.1 Spark通信机制的重要概念

img

(1)RpcEndpoint:RPC端点,Spark将每个通信实体/集群节点(Client/Master/Worker等)都称之为一个Rpc端点,且都实现了RpcEndpoint接口,内部根据不同端点的需求,设计不同的消息和不同的业务处理,如果需要发送消息则调用Dispatcher中的相关方法;

(2)RpcEnv:RPC上下文环境,RpcEndpoint运行时依赖的上下文环境称之为RpcEnv,其管理RpcEndpoint需要的一些东西,如Dispatcher消息分发器,每个RpcEndpoint都对应着自己的一个RpcEnv;

(3)Dispatcher(存在于RpcEnv中):消息分发器,用于发送消息或者从远程RpcEndpoint和本地接收消息,并将消息分发至对应的指令收件箱/发件箱。如果消息接收方是自己的话(即发往本地的消息或从远程RpcEndpoint接收到的消息),那就将消息存入本地RpcEndpoint的收件箱,如果消息接收者为远程RpcEndpoint,则将消息放入指定远程RpcEndpoint的发件箱,每个RpcEndpoint内部维护了一批远程RpcEndpoint的Outbox,表示本地RpcEndpoint需要与这些RpcEndpoint进行通信。Dispatcher类中的MessageLoop线程负责读取LinkedBlockingQueue中的RpcMessage消息,然后处理Inbox中的消息,由于是阻塞队列,当没有消息的时候自然阻塞,一旦有消息,就开始工作。Dispatcher的ThreadPool负责消费这些Message。也就是说某个RpcEndpoint需要发送消息或接收到消息时均先将消息发送到自己的Dispatcher消息分发器中,然后再由消息分区器来分配消息的处理方式,RpcEndpoint对应的Dispatcher中维护了一些远程RpcEndpoint的地址(以Outbox的形式)。

(4)Inbox:本地RpcEndpoint的消息收件箱,一个本地RpcEndpoint对应一个Inbox,Dispatcher每次向Inbox存入消息时,都将对应的EndpointData(内部维护该消息发往的本地端点的endpoint和endpointRef,以及本地端点对应的Inbox)加入到内部的Receiver Queue(阻塞队列)中,且在Dispatcher创建时会启动一个单独的线程轮询Receiver Queue队列查看有无消息,若有消息则进行消息消费

(5)Outbox(存在于RpcEnv中):消息发件箱,一个RpcEndpoint对应的RpcEnv对象中维护了一些远程RpcEndpoint地址及其Outbox的映射(即某个RpcEndpoint中维护了一些远程RpcEndpoint的地址和对应于该远程RpcEndpoint的发件箱,便于拿到远程RpcEndpoint的地址,发送消息给远程RpcEndpoint),当消息放入Outbox后,紧接着将消息通过远程RpcEndpoint(实际是调用该端点的ref引用)对应的TransportClient发送出去。消息放入发件箱以及发送过程是在同一个线程中进行的。即发件箱中的消息是通过远程RpcEndpoint对应的TransportClient发送给其它RpcEndpoint。

(6)TransportClient:Netty通信客户端,根据Outbox消息的receiver的地址信息,实例化相应远程端点的TransportClient,然后发送消息至远程TransportServer,每个RpcEndpoint也维护了一个其它远程RpcEndpoint的TransportClient集合。

(7)TransportServer:Netty通信服务端,一个RpcEndpoint对应一个TransportServer,接收到远程消息后调用自己的Dispatcher分发消息至本地endpoint的收件箱。

综上所述:一个RpcEndpoint内部主要维护了以下一些东西:

(1)依赖一个RpcEnv上下文执行环境;

(2)维护一个Inbox,接收本地发往本地的消息以及从远程RpcEndpoint接收到的消息;

(3)维护多个远程RpcEndpoint对应的Outbox集合,每个远程RpcEndpoint对应一个Outbox,本地往某个远程RpcEndpoint发消息时,先根据远程RpcEndpoint地址找到对应的Outbox,往那个Outbox添加消息;

(4)一个Dispatcher消息分发器;

(5)维护远程RpcEndpoint对应的TransportClient映射;

(6)维护本地的TransportServer用于接收远程RpcEndpoint发送过来的消息。

RpcEndpoint接收/发送消息的过程大致如下:

接收消息:每个RpcEndpoint对应的TransportServer负责接收其它RpcEndpoint发送过来的消息,然后将消息添加到本地RpcEndpoint中的Dispatcher中,Dispatcher再将消息添加到本地的Inbox收件箱,Inbox中会有一个阻塞队列用于存放接收到的消息,然后有一个线程会不断地轮询这个队列,拉取消息进行消息的消费;

发送消息:RpcEndpoint发送消息时,先将消息放到自己的Dispatcher中,然后Dispatcher根据消息发往的远程RpcEndpoint地址找到相应的Outbox发件箱(每个本地端点维护了一些远程端点的Outbox对象),然后将消息添加到指定的Outbox中,后续通过远程RpcEndpoint对应的TransportClient将对应Outbox发件箱中的消息发送出去。

2.2 Spark通信相关类解析

2.2.1 RpcEndpoint

在Spark中,RpcEndpoint是所有通信实体的抽象。RpcEndpoint是一个trait,其中定义了一些函数,这些函数都是在收到某个特定的消息后才会被触发,执行相应的逻辑(真正的执行逻辑是由具体实现类实现的,如Master),其中onStart、receive和onStop这三个方法的调用是有先后顺序的,RpcEndpoint中的方法如下:

 

rpcEnv:RpcEndpoint执行依赖的上下文环境;

receive:接收消息并处理;

receiveAndReply:接收消息处理后,并给消息发送者返回响应;

onError:发生异常时调用;

onConnected:当客户端(远程端点)与本地RpcEndpoint建立连接后调用;

onDisconnected:当客户端与本地RpcEndpoint失去连接后调用;

onNetworkError:当网络连接发生错误时调用;

onStart:RpcEndpoint启动时调用;

onStop:RpcEndpoint停止时调用。

RpcEndpoint中最重要的几个方法:onStart、receive、receiveAndReply以及onStop,这几个方法就是RpcEndpoint的生命周期。

RpcEndpoint的继承体系如下图:

img

由上图可知,Master和Worker等都是一个RpcEndpoint,ClientEndpoint是每个SparkApp的终端点——即Spark应用对应的RpcEndpoint,DriverEndpoint是Spark Driver的endpoint,HeartbeatReceiver是Executor发送心跳消息给Driver的Endpoint,CoarseGrainedExecutorBackend是Spark Executor的endpoint,用于执行Executor的相关操作。上述这些RpcEndpoint都继承自ThreadSafeRpcEndpoint,即均是线程安全的。

2.2.2 RpcEndpointRef

RpcEndpointRef是对RpcEndpoint的引用,本地RpcEndpoint要向远端的一个RpcEndpoint发送消息时,必须通过远程RpcEndpoint的引用 RpcEndpointRef才能往远程端点发送消息。RpcEndpointRef指定了ip和port,是一个类似spark://host:port这种的地址,RpcEndpointRef在Spark中只有一个子类,即NettyRpcEndpointRef,即无论是何种类型的RpcEndpoint,其ref引用都是NettyRpcEndpointRef对象,内部提供了一些方法用于发送消息,如下所示:

 

RpcEndpoint的地址在spark中表示为RpcAddress对象,该类只有两个字段:host和port

//每个RpcEndpoint均对应不同的port,所以一个RpcEndpoint的地址由host和port唯一确定
private[spark] case class RpcAddress(host: String, port: Int) {
  def hostPort: String = host + ":" + port
  def toSparkURL: String = "spark://" + hostPort
  override def toString: String = hostPort
}

其中的address返回该引用对应的真实RpcEndpoint的地址,name则返回对应真实RpcEndpoint的名称。此外该类还提供了ask和askSync方法,其中ask方法是异步的,返回一个Future对象用于获取响应,而askSync则是同步的,调用时会阻塞等待结果返回,而send()方法只管发送消息,不关心响应,endpointRef中的ask和send方法都是用于向远程RpcEndpoint发送消息的

2.2.3 RpcEnv

RpcEnv是RpcEndpoint的运行环境,内部维护了RpcEndpoint运行所需的一系列东西,如Dispatcher消息分发器、Outbox发件箱等(每个远程端点都对应一个Outbox),内部结构如下图:

 

RpcEnv类有一个伴生对象RpcEnv,该伴生对象内提供了两个create方法用于创建RpcEnv对象,其实最终调用的都是第二个create方法,通过RpcEnvFactory工厂创建NettyRpcEnv对象。

RpcEnv类中提供了一些方法用于在Dispatch

Spark 内部通信认证是指在Spark集群内部节点之间进行通信时,确保通信的安全性和可信度的一种机制。Spark的内部通信认证主要有以下几种方式: 1. 传输层安全(Transport Layer Security,简称TLS):Spark可以通过使用TLS协议来加密传输的数据,防止数据在传输过程中被窃取或篡改。TLS可以对通信双方进行身份验证,并使用加密技术来保护数据的机密性和完整性。 2. 认证密钥:Spark集群可以使用认证密钥来验证节点之间的通信。每个节点都有一个唯一的密钥,其他节点在通信时需要通过验证该密钥来确保身份的合法性。这种方式可以有效防止非法节点的加入或未授权的访问。 3. 认证代理(Authentication Proxy):Spark可以使用认证代理来验证集群中的节点身份。认证代理是一个专门负责验证节点身份的中间服务器,它会对连接的节点进行身份验证,并将信息转发给目标节点。这种方式可以确保节点之间的通信不会被未经验证的节点干扰或监听。 4. 访问控制列表(Access Control List,简称ACL):Spark可以通过ACL来对节点进行授权管理,只允许特定的节点与其他节点进行通信。ACL可以通过配置文件或其他方式进行管理,以确保只有经过授权的节点才能与集群内部节点进行通信。 总之,Spark内部通信认证是通过使用TLS加密、验证密钥、认证代理和ACL等机制来确保集群内部节点间通信的安全与可信度。这些认证机制可以防止数据泄露、篡改和未经授权的访问,并确保节点身份的合法性。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值