一、概述

客户端请求程序通过本地调用的方式调用服务,服务调用过程中,真正的方法逻辑存在于服务端中,客户端保存就是服务端真实方法的一个存根 stub(也可以认为是服务端的代理,存放服务端的地址等信息); 当客户端需要远程访问服务端方法的时候,可以凭借服务端在客户端中的存根来组装发起远程调用所需要的信息。Spark 远程通信全部使用 netty 进行了替换, TransportClientFactory 是 RPC 客户端的工厂类。

spark rpc client

二、架构设计

2.1. 请求程序

本地程序通过本地调用的方式调用远程服务。

2.2. stub 程序

当客户端需要远程访问服务端方法的时候,可以凭借服务端在客户端中的存根来组装发起远程调用所需要的信息。

2.2.1. 协议层

不同的请求本质上是不同的协议。因此,有众多不同的协议实现类。在这些实现类中,主要负责对各自请求的结构体进行序列化与反序列化的操作。

2.2.2. 代理层

在 NettyRpcEnv 中向远端 RpcEndpoint 发送请求, 首先需要持有 RpcEndpoint 的引用对象 NettyRpcEndpointRef(类似 Akka 中 ActorRef),RpcEndpointRef 是一个对 RpcEndpoint 的远程引用对象(可以理解为代理对象),内部记录了 RpcEndpoint 的位置信息,通过它可以向远程的 RpcEndpoint 端发送消息以进行通信。

2.2.3. 路由层

Spark RPC 路由层负责将 RPC 消息路由到要该对此消息处理的 RpcEndpoint。

2.3. 传输层 Client

数据传输全部使用 Netty 进行了替换。

三、总结

3.1. 发送消息

发送消息流程为分为两种,一种端点(Master)自己把消息发送到本地 Inbox,一种端点(Master)接收到消息后,通过 TransPortRequestHander 接收后处理,放入 Inbox

Spark 通信机制之发送消息

3.1.1. 本地

endpointRef -> NettyRpcEnv-> Dispatcher -> postMessage() > MessageLoop(Dispatcher) -> inbox 一>
process -> endpoint.receiveAndReply()

3.1.2. 远程

endpointRef(Worker) ->TransportChannelHandler -> channelRead0() -> TransPortRequestHander ->
handle() -> processRpcRequest() -> NettyRpcHandler(在 NettyRpcEnv 中) 一> receive() -> internalReceive -> dispatcher.postToAll(RemoteProcessConnected(remoteEnvAddress))(响应)一>
dispatcher.postRemoteMessage(messageToDispatch, callback)(发送远端来的消息放进inbox) -> postMessage() -> inbox -> process()

3.2. 接受响应

3.3. refer

http://t.zoukankan.com/huanghanyu-p-12989067.h