Alluxio源码分析:RPC框架浅析(三)
来源:互联网 发布:新乡学院网络管理系统 编辑:程序博客网 时间:2024/05/22 15:03
Alluxio源码分析是一个基于内存的分布式文件系统,和HDFS、HBase等一样,也是由主从节点构成的。而节点之间的通信,一般都是采用的RPC通讯模型。Alluxio中RPC是基于何种技术如何实现的呢?它对于RPC请求是如何处理的?都涉及到哪些组件?本文将针对这些问题,为您一一解答。
继《Alluxio源码分析:RPC框架浅析(二)》一文后,本文继续讲解Alluxio中RPC实现。
4、Client端实现
以FileSystemMasterClientService为例,Client端实现在FileSystemMasterClient类中,其内部有一个FileSystemMasterClientService.Client类型的成员变量FileSystemMasterClientService.Client,如下:
private FileSystemMasterClientService.Client mClient = null;它的初始化是在afterConnect()方法中完成的,如下:
@Override protected void afterConnect() throws IOException { mClient = new FileSystemMasterClientService.Client(mProtocol); }而使用呢,以读文件时需要的getStatus()方法为例,如下:
/** * @param path the file path * @return the file info for the given file id * @throws IOException if an I/O error occurs * @throws AlluxioException if an Alluxio error occurs */ public synchronized URIStatus getStatus(final AlluxioURI path) throws IOException, AlluxioException { // RPC调用,执行call()方法 return retryRPC(new RpcCallableThrowsAlluxioTException<URIStatus>() { @Override public URIStatus call() throws AlluxioTException, TException { // 构造一个URIStatus实例,并返回 // 构造URIStatus实例时,需要使用FileInfo对象,其通过FileSystemMasterClientService.Client的getStatus()方法获得 return new URIStatus(ThriftUtils.fromThrift(mClient.getStatus(path.getPath()))); } }); }执行retryRPC()方法,发起一个RPC调用,然后执行call()方法,构造一个URIStatus实例,并返回,构造URIStatus实例时,需要使用FileInfo对象,其通过FileSystemMasterClientService.Client的getStatus()方法获得,也就是我们需要远程调用服务端的FileSystemMasterClientService服务的getStatus()方法。
我们看下retryRPC(RpcCallableThrowsAlluxioTException)方法,它的定义在其祖先类AbstractClient中,如下:
/** * Similar to {@link #retryRPC(RpcCallable)} except that the RPC call may throw * {@link AlluxioTException} and once it is thrown, it will be transformed into * {@link AlluxioException} and be thrown. * * @param rpc the RPC call to be executed * @param <V> type of return value of the RPC call * @return the return value of the RPC call * @throws AlluxioException when {@link AlluxioTException} is thrown by the RPC call * @throws IOException when retries exceeds {@link #RPC_MAX_NUM_RETRY} or {@link #close()} has * been called before calling this method or during the retry */ protected synchronized <V> V retryRPC(RpcCallableThrowsAlluxioTException<V> rpc) throws AlluxioException, IOException { int retry = 0; // 如果客户端未关闭,即标志位mClosed为false,且重试次数retry小于30次,执行while循环 while (!mClosed && (retry++) <= RPC_MAX_NUM_RETRY) { // 调用connect()进行连接 connect(); try { // 调用rpc的call()方法,这里也就是外部重定义的RpcCallableThrowsAlluxioTException的call()方法 return rpc.call(); } catch (AlluxioTException e) { throw AlluxioException.from(e); } catch (ThriftIOException e) { throw new IOException(e); } catch (TException e) { LOG.error(e.getMessage(), e); mConnected = false; } } throw new IOException("Failed after " + retry + " retries."); }看下connect()方法,如下:
/** * Connects with the remote. * * @throws IOException if an I/O error occurs * @throws ConnectionFailedException if network connection failed */ public synchronized void connect() throws IOException, ConnectionFailedException { // 标志位 mConnected如果为true,标识连接已经建立,直接返回 if (mConnected) { return; }// 调用disconnect()方法,处理标志位mConnected、传输协议mProtocol等 disconnect(); // 检测客户端状态mClosed Preconditions.checkState(!mClosed, "Client is closed, will not try to connect."); // 连接最大重试次数maxConnectsTry取参数"alluxio.master.retry" int maxConnectsTry = mConfiguration.getInt(Constants.MASTER_RETRY_COUNT); final int BASE_SLEEP_MS = 50; RetryPolicy retry = new ExponentialBackoffRetry(BASE_SLEEP_MS, Constants.SECOND_MS, maxConnectsTry); while (!mClosed) {// 客户端未关闭的话,一直进行while循环,直到连接成功 // 获取Master地址mAddress mAddress = getAddress(); LOG.info("Alluxio client (version {}) is trying to connect with {} {} @ {}", Version.VERSION, getServiceName(), mMode, mAddress); // 创建传输协议TBinaryProtocol实例binaryProtocol,这是一个二进制协议 TProtocol binaryProtocol = new TBinaryProtocol(mTransportProvider.getClientTransport(mAddress)); // 创建多路复用协议TMultiplexedProtocol实例mProtocol mProtocol = new TMultiplexedProtocol(binaryProtocol, getServiceName()); try { // 多路复用协议mProtocol的open()方法打开连接 mProtocol.getTransport().open(); LOG.info("Client registered with {} {} @ {}", getServiceName(), mMode, mAddress); // 标志位 mConnected设置为true,标识连接已经建立 mConnected = true; // 调用afterConnect()方法,创建client实例 afterConnect(); // 检测版本号 checkVersion(getClient(), getServiceVersion()); return; } catch (TTransportException e) { LOG.error("Failed to connect (" + retry.getRetryCount() + ") to " + getServiceName() + " " + mMode + " @ " + mAddress + " : " + e.getMessage()); if (!retry.attemptRetry()) { break; } } } // Reaching here indicates that we did not successfully connect. throw new ConnectionFailedException("Failed to connect to " + getServiceName() + " " + mMode + " @ " + mAddress + " after " + (retry.getRetryCount()) + " attempts"); }比较简单,前面涉及一些状态位mConnected、mClosed等的判断,避免重复连接或者错误连接等,而最重要的几步如下:
1、获取Master地址mAddress;
2、创建传输协议TBinaryProtocol实例binaryProtocol,这是一个二进制协议;
3、创建多路复用协议TMultiplexedProtocol实例mProtocol;
4、多路复用协议mProtocol的open()方法打开连接,启动rpc连接;
5、标志位 mConnected设置为true,标识连接已经建立 ;
6、调用afterConnect()方法,创建client实例。
RPC服务一但启动,通讯链接一旦建立,那么剩下的就是类似调用本地方法一样进行远程过程调用了,我们最后再看下读文件时需要使用的getStatus()方法吧,如下:
/** * @param path the file path * @return the file info for the given file id * @throws IOException if an I/O error occurs * @throws AlluxioException if an Alluxio error occurs */ public synchronized URIStatus getStatus(final AlluxioURI path) throws IOException, AlluxioException { // RPC调用,执行call()方法 return retryRPC(new RpcCallableThrowsAlluxioTException<URIStatus>() { @Override public URIStatus call() throws AlluxioTException, TException { // 构造一个URIStatus实例,并返回 // 构造URIStatus实例时,需要使用FileInfo对象,其通过FileSystemMasterClientService.Client的getStatus()方法获得 return new URIStatus(ThriftUtils.fromThrift(mClient.getStatus(path.getPath()))); } }); }调用FileSystemMasterClientService.Client的getStatus()方法,然后利用ThriftUtils的数据转换方法fromThrift()进行对象转换,就能得到我们需要的对象数据!是不是so easy,屏蔽了很多底层细节,让我们感觉像调用本地方法一样?
就是这么简单!
- Alluxio源码分析:RPC框架浅析(三)
- Alluxio源码分析:RPC框架浅析(一)
- Alluxio源码分析:RPC框架浅析(二)
- alluxio rpc 分析
- Alluxio源码分析写数据:创建文件(一)
- Alluxio源码分析写数据:创建文件(二)
- Alluxio源码分析读数据:打开文件(一)
- Alluxio源码分析读数据:打开文件(二)
- Android网络通信Volley框架源码浅析(三)
- [置顶] Android网络通信Volley框架源码浅析(三)
- Android单元测试框架源码分析(一)浅析Mockito
- Android单元测试框架源码分析(二)浅析Robolectric
- skynet框架 源码分析 三
- MINA框架源码分析(三)
- skynet框架 源码分析 三
- RPC框架实现思路浅析
- Thrift源码分析(九)-- 扩展Thrift框架来实现Attachable的RPC调用
- 分布式文件系统KFS源码阅读与分析(三):RPC实现机制(MetaServer端)
- 云计算与openstack介绍
- C语言指针与数组易混淆知识点(一)
- sqlite文件大小问题,删除不干净,彻底清空数据库
- OpenStack及其构成简介
- 使用 Antlr 开发领域语言(DSL)
- Alluxio源码分析:RPC框架浅析(三)
- Java 中的垃圾回收策略
- capistrano/blob/v3.4.0部署
- JVM性能调优
- mysql登录
- JAVA 垃圾收集器与内存分配策略
- Notepad++崩溃了
- 15:39:52.027 [ActiveMQ InactivityMonitor WriteCheckTimer] DEBUG o.a.a.t.Abstract
- 下载Android源码