RPC概述
RPC(Remote Procedure Call)即远程过程调用,是一种通过网络从远程计算机程序上请求服务的协议。RPC允许本地程序像调用本地方法一样调用远程计算机上的应用程序,其使用常见的网络传输协议(如TCP或UDP)传递RPC请求以及相应信息,使得分布式程序的开发更加容易。Hadoop作为分布式存储系统, 各个节点之间的通信和交互是必不可少的, 所以需要实现一套节点间的通信交互机制。
Hadoop实现了一套自己的RPC框架。采用了JavaNIO、Java动态代理以及protobuf等基础技术
RPC采用客户端/ 服务器模式, 请求程序就是一个客户端, 而服务提供程序就是一个服务器。 客户端首先会发送一个有参数的调用请求到服务器, 然后等待服务器发回响应信息。 在服务器端, 服务提供程序会保持睡眠状态直到有调用请求到达为止。 当一个调用请求到达后, 服务提供程序会执行调用请求, 计算结果, 向客户端发送响应信息, 然后等待下一个调用请求。 最后, 客户端成功地接收服务器发回的响应信息, 一个远程调用结束.
RPC框架工作原理示例图
client functions
请求程序,会像调用本地方法一样调用客户端stub程序(如图中①),然后接受stub程序的响应信息(如图中⑩)
client stub
客户端stub程序,表现得就像本地程序一样,但底层却会调用请求和参数序列化并通过通信模块发送给服务器(如图中②);客户端stub程序也会等待服务器的响应信息(如图中⑨),将响应信息反序列化并返回给请求程序(如图中⑩)
sockets
网络通信模块,用于传输RPC请求和响应(如图中的③⑧),可以基于TCP或UDP协议
server stub
服务端stub程序,会接收客户端发送的请求和参数(如图中④)并反序列化,根据调用信息触发对应的服务程序(如图中⑤),然后将服务程序的响应信息(如图⑥),并序列化并发回给客户端(如图中⑦)
server functions
服务程序,会接收服务端stub程序的调用请求(如图中⑤),执行对应的逻辑并返回执行结果(如图中⑥)
Hadoop RPC实现
HadoopRPC实现方式跟上图一样,代码位于hadoop-common中的 org.apache.hadoop.ipc 包下.
Hadoop RPC框架主要由三个类组成: RPC、 Client和Server类。
RPC类用于对外提供一个使用Hadoop RPC框架的接口,
Client类用于实现RPC客户端功能,
Server类则用于实现RPC服务器端功能。
在这里,我们先不写原理,先写一个demo, 然后跑起来. 测试一下效果.然后再说理论.
这个demo采用的是hadoop默认的RPC Engine : WritableRpcEngine
采用 proto协议在定义接口协议&实现方面会不一样, 后面章节会有写这两个rpc engine的调度实例
1.定义接口协议
/**
* 协议接口
*/
public interface ClicentNameNodeProtocol {
//1. 定义协议的ID
public static final long versionID = 1L;
/**
* 拿到元数据方法,协议通信前会访问元数据
*/
public String getMetaData(String path);
}
2.实现接口协议
/**
* 实现协议结构
*/
public class ClicentNameNodeImpl implements ClicentNameNodeProtocol {
public String getMetaData(String path) {
// 数据存放的路径,有多少块,块大小,校验和,存储在哪一台机器上
return path + ":3 - {BLOCK_1,BLOCK_2,BLOCK_3....";
}
}
3.创建Server服务, 并注册协议.启动RPC服务.
/**
* 启动RPC服务
*/
public class Server {
public static void main(String[] args) throws IOException {
//1. 构建RPC框架
RPC.Builder builder = new RPC.Builder(new Configuration());
//2. 绑定地址
builder.setBindAddress("localhost");
//3. 绑定端口
builder.setPort(7777);
//4. 绑定协议
builder.setProtocol(ClicentNameNodeProtocol.class);
//5. 调用协议实现类
builder.setInstance(new ClicentNameNodeImpl());
//6. 创建服务
RPC.Server server = builder.build();
//7. 启动服务
server.start();
}
}
4.创建Client服务,请求数据接口
/**
* 访问RPC服务
*/
public class Client {
public static void main(String[] args) throws IOException {
//1. 拿到RPC协议
ClicentNameNodeProtocol proxy = RPC.getProxy(ClicentNameNodeProtocol.class, 1L,
new InetSocketAddress("localhost", 7777), new Configuration());
//2. 发送请求
String metaData = proxy.getMetaData("/meta");
//3. 打印元数据
System.out.println(metaData);
}
}
5.测试结果
参考:
https://blog.csdn.net/DiDi_Tech/article/details/100919314
Hadoop 2.X HDFS源码剖析 -- 徐鹏