TransportClient类说明

先来看,官方文档给出的说明:

Client for fetching consecutive chunks of a pre-negotiated stream. This API is intended to allow efficient transfer of a large amount of data, broken up into chunks with size ranging from hundreds of KB to a few MB. 
Note that while this client deals with the fetching of chunks from a stream (i.e., data plane), the actual setup of the streams is done outside the scope of the transport layer. The convenience method "sendRPC" is provided to enable control plane communication between the client and server to perform this setup. 
For example, a typical workflow might be: 
client.sendRPC(new OpenFile("/foo")) --> returns StreamId = 100 
client.fetchChunk(streamId = 100, chunkIndex = 0, callback) 
client.fetchChunk(streamId = 100, chunkIndex = 1, callback)
... 
client.sendRPC(new CloseStream(100))
Construct an instance of TransportClient using TransportClientFactory. A single TransportClient may be used for multiple streams, but any given stream must be restricted to a single client, in order to avoid out-of-order responses. 
NB: This class is used to make requests to the server, while TransportResponseHandler is responsible for handling responses from the server. Concurrency: thread safe and can be called from multiple threads.

用于获取预先协商的流的连续块的客户端。此API允许有效传输大量数据,分解为大小从几百KB到几MB的chunk。
注意,虽然该客户端处理从流(即,数据平面)获取chunk,但是流的实际设置在传输层的范围之外完成。提供便利方法“sendRPC”以使客户端和服务器之间的控制平面通信能够执行该设置。
例如,典型的工作流程可能是:

// 打开远程文件
client.sendRPC(new OpenFile(“/ foo”)) - >返回StreamId = 100

// 打开获取远程文件chunk-0
client.fetchChunk(streamId = 100,chunkIndex = 0,callback)

// 打开获取远程文件chunk-1 
client.fetchChunk(streamId = 100,chunkIndex = 1,callback)
.. .

// 关闭远程文件
client.sendRPC(new CloseStream(100))
使用TransportClientFactory构造TransportClient的实例。

单个TransportClient可以用于多个流,但是任何给定的流必须限制在单个客户端,以避免无序响应。
注意:此类用于向服务器发出请求,而TransportResponseHandler负责处理来自服务器的响应。并发:线程安全,可以从多个线程调用。

简言之,可以认为TransportClient就是Spark Rpc 最底层的基础客户端类。主要用于向server端发送rpc 请求和从server 端获取流的chunk块。

下面看一下类的结构:

它有两个内部类:RpcChannelListener和StdChannelListener,这两个类的继承关系如下:

其公共父类GenericFutureListener 官方说明如下:

Listens to the result of a Future. The result of the asynchronous operation is notified once this listener is added by calling Future.addListener(GenericFutureListener).

即,监听一个Future 对象的执行结果,通过Future.addListener(GenericFutureListener)的方法,添加监听器来监听这个异步任务的最终结果。当异步任务执行成功之后,会调用监听器的 operationComplete 方法。在StdChannelListener 中,其operationComplete 方法其实就是添加了日志打印运行轨迹的作用,添加了异常的处理方法 handleFailure,它是一个空实现,如下:

其子类RpcChannelListener的handleFailure实现如下:

这个handleFailure 方法充当着失败处理转发的作用。其调用了 RpcResponseCallback (通过构造方法传入)的 onFailure 方法。

再来看一下TransportClient 的主要方法解释:

1. fetchChunk : Requests a single chunk from the remote side, from the pre-negotiated streamId. Chunk indices go from 0 onwards. It is valid to request the same chunk multiple times, though some streams may not support this. Multiple fetchChunk requests may be outstanding simultaneously, and the chunks are guaranteed to be returned in the same order that they were requested, assuming only a single TransportClient is used to fetch the chunks.其源码如下:

2. stream:Request to stream the data with the given stream ID from the remote end.其源码如下:

3. sendRpc:Sends an opaque message to the RpcHandler on the server-side. The callback will be invoked with the server's response or upon any failure.

4. uploadStream:Send data to the remote end as a stream. This differs from stream() in that this is a request to *send* data to the remote end, not to receive it from the remote.

5. sendRpcSync:Synchronously sends an opaque message to the RpcHandler on the server-side, waiting for up to a specified timeout for a response.

6. send:Sends an opaque message to the RpcHandler on the server-side. No reply is expected for the message, and no delivery guarantees are made.

7. removeRpcRequest:Removes any state associated with the given RPC.主要是从handler 中把监听的rpcRequest移除。

8. close:close the channel

9. timeOut: Mark this channel as having timed out.

可以看出,其主要是一个比较底层的客户端,主要用于发送底层数据的request,主要是数据层面的流中的chunk请求或者是控制层面的rpc请求,发送数据请求的方法中都有一个回调方法,回调方法是用于处理请求返回的结果。

TransportClient初始化

它是由TransportClientFactory 创建的。看TransportClientFactory 的核心方法: createClient(java.net.InetSocketAddress)的关键代码如下:

 1 // 1. 添加一个 ChannelInitializer 的 handler
2 bootstrap.handler(new ChannelInitializer<SocketChannel>() {
3 @Override
4 public void initChannel(SocketChannel ch) {
5 TransportChannelHandler clientHandler = context.initializePipeline(ch);
6 clientRef.set(clientHandler.getClient());
7 channelRef.set(ch);
8 }
9 });
10
11 // Connect to the remote server
12 long preConnect = System.nanoTime();
13 // 2. 连接到远程的服务端,返回一个ChannelFuture 对象,调用其 await 方法等待其结果返回。
14 ChannelFuture cf = bootstrap.connect(address);
15 // 3. 等待channelFuture 对象其结果返回。
16 if (!cf.await(conf.connectionTimeoutMs())) {
17 throw new IOException(
18 String.format("Connecting to %s timed out (%s ms)", address, conf.connectionTimeoutMs()));
19 } else if (cf.cause() != null) {
20 throw new IOException(String.format("Failed to connect to %s", address), cf.cause());
21 }

在connect 方法中,初始化了handler。handler 被添加到ChannelPipiline之后,使用线程池来处理初始化操作,其调用了 DefaultChannelPipeline的callHandlerAdded0 方法,callHandlerAdded0调用了handler 的 handlerAdded 方法,handlerAdded内部调用了 initChannel 私有方法,initChannel又调用了保护抽象方法 initChannel,其会调用 ChannelInitializer自定义匿名子类的initChannel 方法。在这个 initChannel 方法中调用了TransportContext 的initializePipeline方法,在这个方法中实例化了 TransportClient对象。

我们再来看一下TransportContext 的initializePipeline方法的核心方法createChannelHandler:

再来看 NettyRpcEnv 是如何初始化transportContext 的:

从上面可以看到 rpcHandler 是NettyRpcHandler, 其依赖三个对象,Dispatcher 对象,nettyEnv 对象以及StreamManager 对象。

Dispatcher 对象已经有做说明,可以看我的博客spark 源码分析之六 -- Spark内置RPC机制剖析之二Dispatcher和Inbox剖析做进一步了解。

NettyEnv 对象就是NettyRpcEnv 对象。

NettyRpcHandler已经有做说明,可以看我的博客spark 源码分析之九 -- Spark内置RPC机制剖析之五StreamManager和NettyRpcHandler做进一步了解。

即channelRpcHandler 就是NettyRpcHandler实例。

关于TransportResponseHandler、TransportRequestHandler和TransportChannelHandler三个类的说明,可以参照博客spark 源码分析之十 -- Spark内置RPC机制剖析之六TransportResponseHandler、TransportRequestHandler和TransportChannelHandler剖析 做进一步了解。

TransportServer

官方说明:

Server for the efficient, low-level streaming service.

即:用于高效,低级别流媒体服务的服务器。

使用TransportContext createServer方法创建:

其构造方法源码如下:

重点看其init方法:

ServerBootstrap是用于初始化Server的。跟TransportClientFactory创建TransportClient类似,也有ChannelInitializer的回调,跟Bootstrap类似。参照上面的剖析。

至此,TransClient和TransServer的剖析完毕。

 

spark 源码分析之十一--Spark RPC剖析之TransportClient、TransportServer剖析的更多相关文章

  1. spark 源码分析之十--Spark RPC剖析之TransportResponseHandler、TransportRequestHandler和TransportChannelHandler剖析

    spark 源码分析之十--Spark RPC剖析之TransportResponseHandler.TransportRequestHandler和TransportChannelHandler剖析 ...

  2. spark 源码分析之十七 -- Spark磁盘存储剖析

    上篇文章 spark 源码分析之十六 -- Spark内存存储剖析 主要剖析了Spark 的内存存储.本篇文章主要剖析磁盘存储. 总述 磁盘存储相对比较简单,相关的类关系图如下: 我们先从依赖类 Di ...

  3. spark 源码分析之九--Spark RPC剖析之StreamManager和RpcHandler

    StreamManager StreamManager类说明 StreamManager 官方说明如下: The StreamManager is used to fetch individual c ...

  4. spark 源码分析之十二 -- Spark内置RPC机制剖析之八Spark RPC总结

    在spark 源码分析之五 -- Spark内置RPC机制剖析之一创建NettyRpcEnv中,剖析了NettyRpcEnv的创建过程. Dispatcher.NettyStreamManager.T ...

  5. Spark 源码分析系列

    如下,是 spark 源码分析系列的一些文章汇总,持续更新中...... Spark RPC spark 源码分析之五--Spark RPC剖析之创建NettyRpcEnv spark 源码分析之六- ...

  6. spark 源码分析之十八 -- Spark存储体系剖析

    本篇文章主要剖析BlockManager相关的类以及总结Spark底层存储体系. 总述 先看 BlockManager相关类之间的关系如下: 我们从NettyRpcEnv 开始,做一下简单说明. Ne ...

  7. Spark源码分析 – 汇总索引

    http://jerryshao.me/categories.html#architecture-ref http://blog.csdn.net/pelick/article/details/172 ...

  8. Spark源码分析 – BlockManager

    参考, Spark源码分析之-Storage模块 对于storage, 为何Spark需要storage模块?为了cache RDD Spark的特点就是可以将RDD cache在memory或dis ...

  9. spark 源码分析之五 -- Spark内置RPC机制剖析之一创建NettyRpcEnv

    在前面源码剖析介绍中,spark 源码分析之二 -- SparkContext 的初始化过程 中的SparkEnv和 spark 源码分析之四 -- TaskScheduler的创建和启动过程 中的C ...

随机推荐

  1. SYN1618型 高精度天文时间同步系统

       SYN1618型 高精度天文时间同步系统 产品概述 SYN1618型 高精度天文时间同步系统是由西安同步电子科技有限公司精心设计.自行研发生产的一款高精度的时频频率标准设备,接收GPS.GLON ...

  2. Webapi实现websocket实时通讯

    应用场景:前端页面发起一个websocket请求与后端进行实时通讯.后端监听某端口获取数据,将监听到的数据加工处理,通过websocket发送到前端. 这里只提供后台的处理方案仅供参考. 1.后端监听 ...

  3. Hexo+NexT(三):Next主题配置详解

    阅读本篇之前,假定读者已经有了Node.js的基础,如需要补充Node.js知识的,请自行百度. Hexo是在Node.js框架下的一个项目,利用Node.js提供的强大功能,完成从Markdown到 ...

  4. 浅谈ASP.NET Core中IOC与DI的理解和使用

    说起IOC和DI,使用过ASP.NET Core的人对这两个概念一定不陌生,早前,自己也有尝试过去了解这两个东西,但是一直觉得有点很难去理解,总觉得对其还是模糊不清,所以,趁着今天有空,就去把两个概念 ...

  5. spring 5.x 系列第16篇 —— 整合dubbo (代码配置方式)

    文章目录 一. 项目结构说明 二.项目依赖 三.公共模块(dubbo-ano-common) 四. 服务提供者(dubbo-ano-provider) 4.1 提供方配置 4.2 使用注解@Servi ...

  6. 第六章 Fisco Bcos 多服务器分布式部署

    想了解相关区块链开发,技术提问,请加QQ群:538327407 前提概要 前面几章,我们通过单机部署,在单台服务器上搭建四个节点,完成Fisco Bcos 底层搭建,并完成相关合约开发.sdk 开发. ...

  7. zabbix2.4汉化

    zabbix的2.4版本安装完后,这里的语言界面选择没有中文,其实是这个版本把中文的屏蔽了. [root@zabbix-server opt]# vim /var/www/html/include/l ...

  8. 【HDU - 1010】Tempter of the Bone(dfs+剪枝)

    Tempter of the Bone 直接上中文了 Descriptions: 暑假的时候,小明和朋友去迷宫中寻宝.然而,当他拿到宝贝时,迷宫开始剧烈震动,他感到地面正在下沉,他们意识到这是一个陷阱 ...

  9. Ubuntu 16.4-desktop系统安装显卡CUDA具体步骤!

    1.禁用nouveau驱动(切换至tty界面) sudo vim /etc/modprobe.d/blacklist.conf 在文本最后添加:blacklist nouveau options no ...

  10. python 微信红包生成器

    #红包生成思路#200 块钱 10个红包#0-200 的一个轴,随机取9个点,分成10段, 每一段的值表示一个红包的大小 #把输入的 money值 * 100 拿到的数值就是分, 不用再考虑单位是元的 ...