一、概述

和 Java 传统的 RPC 解决方案对比,Spark RPC 不是通过定义接口或者方法标示(比如通常的 id 或者 name),而是巧妙的使用 Scala 的模式匹配进行方法的路由,在进程之问通信不需要在额外定义通信协议,通过定义 case class 做为请求消息,只需要在服务端的接收入口西数中对请求进行模糊匹配,匹配到相应的请求处理分支就行~
虽然点对点通信的契约交换受制于语言,但是 Spark RPC 定位于内部组件通信,所以无伤大雅~

二、消息转换

2.1. RpcEndpointRef#send()

1
worker.send(DriverStateChanged(driverId, finalState.get, finalException))

2.2. NettyRpcEnv#send()

$NettyRpcEnv.send()$ 主要负责把 $RpcEndpointRef.send()$ 传递过来的各种 case class 格式消息进行转为 RequestMessage。

2.3. NettyRpcEnv#postToOutbox()

$NettyRpcEnv.postToOutbox()$ 主要负责把 $NettyRpcEnv.send()$ 传递过来的消息进行序列化。

2.4. TransportClient#sendRpc()

$TransportClient.sendRpc()$ 会把 $NettyRpcEnv.postToOutbox()$ 传递来的消息转换为 Message,Message 接口定义了 Spark RPC 通信过程中消息格式,其结构包括消息类型、消息体以及一个用于判断消息的主体是否包含在消息的同一帧中的方法。

Message
  1. 消息类型

    $type()$ 方法返回消息类型。

    消息实现类都直接或问接地实现了 RequestMessage 或 ResponseMessage 接口

    • RequestMessage

      其中 RequestMessage 的具体实现有 4 种:

      1. ChunkFetchRequest: 请求获取流的单个块的序列。
      2. RpcRequest: 此消息类型由远程的 RPC 服务端进行处理,是一种需要服务端向客户端回复的RPC请求信息类型。
      3. OneWayMessage: 比消息也需要由远程的RPC服务端进行处理,与RpcRequest不同的是,不需要服务端向客户端回复。
      4. StreamRequest: 此消息表示向远程的服务发起请求,以获取流式数据
    • ResponseMessage

      由于 OneWayMessage 不需要响应, 所以 ResponseMessage 对于成功或失败状态的实现各有 3 种, 分别如下

      1. ChunkFetchSuccess 处理 ChunkFetchRequest 成功后返回的消息
      2. ChunkFetchFailure 处理 ChunkFetchRequest 失败后返回的消息
      3. RpcResponse 处理RpcRequest成功后返回的消息。
      4. RpcFailure 处理RpcRequest失败后返回的消息。
      5. StreamResponse 处理StreamRequest成功后返回的消息。
      6. StreamFailure 处理StreamRequest失败后返回的消息。
  2. 消息体

    消息体的类型为 ManagedBuffer。ManagedBuffer 提供了由字节构成数据的不可变视图

  3. $isBodyInFrame()$

    $isBodyInFrame()$ 用于判断消息的主体是否包含在消息的同一帧中

2.5. TransportChanneLHandler#channelRead0()