Hadoop RPC 机制以及源码分析

什么是RPC
RPC(Remote Procedure Call)—远程过程调用,是一种用于构建基于C/S(客户端/服务器)的分布式应用程序技术,调用者和被调用者可能在同一台服务器也不能不在同一台服务器,使用RPC可以使调用远程方法像调用本地方法一样简单,而且网络通信是透明的,不需要知道通信细节。

RPC调用的流程

1、服务消费方(client)调用以本地调用方式调用服务;
2、client stub找到服务地址,并将消息发送到服务端;
3、server stub收到消息后进行解码;
4、server stub根据解码结果调用本地的服务;
5、本地服务执行并将结果返回给server stub;
6、server stub将返回结果打包序列化成消息并发送至消费方;
7、client stub接收到消息,并进行解码;
8、服务消费方得到最终结果。

RPC调用需要解决的问题
函数ID(callID)、序列化和反序列化、网络传输
函数ID
在本地调用中,通过函数指针来指定函数体,调用add函数,编译器会自动通过函数指针确定add函数在内存中的位置。但是在RPC中,无法通过函数指针来完成调用,因为它们的内存地址可能是完全不同的。所以调用方和被调用方同时需要维护一个{函数<->ID}的映射表,来保证调用到正确的函数。
序列化和反序列化
序列化是指将结构化对象转化为字节流以便在网络上传输或者写到磁盘上进行永久存储的过程,序列化方式的优劣很大程序上影响了RPC的性能,市场上也有Protobuf、Thrift、Avro等成熟的序列化解决方案供选择,序列化框架的选择主要看以下三点:
1、通用性:能否支持复杂的数据结构,如map等
2、性能:包含时间复杂度和空间复杂度
3、可扩展性:能否很好的应对公司业务的发展
网络传输
函数的调用方和被调用方通常是通过网络连接的,也就是说函数ID、序列化之后的字节流都需要通过网络传输,因此并不局限于某种网络协议,只要可以完成传输即可。比如有的RPC框架使用TCP协议、有的使用HTTP

RPC在hadoop中的应用
Hadoop V2中的RPC采用的是自己独立开发的协议,其核心内容包含服务端,客户端,交互协议。源码内容都在hadoop-common-project项目的org.apache.hadoop.ipc包下面
客户端代码编写:

package cn.itcast.hadoop.rpc;
import java.io.IOException;
import java.net.InetSocketAddress;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.ipc.RPC;
public class RPCClient {
	public static void main(String[] args) throws IOException {
		Configuration conf = new Configuration();
		BizProtocol proxy = RPC.getProxy(BizProtocol.class, 10010, new InetSocketAddress("192.168.9.1", 9527), conf);
		String result = proxy.sayHi("tomcat");
		System.out.println(result);
		RPC.stopProxy(proxy);
	}
}

客户端对象通过RPC.getProxy()的方式来获取,通过动态代理的方式创建出BizProtocol接口的实现,然后调用其中的方法,10010为版本号,需要和服务端序列化时的版本号保持一致,new InetSocketAddress()为服务端注册的IP和端口,需要代理这个服务端的服务,代理里面的对象,执行相应的方法。
服务端代码编写:

package cn.itcast.hadoop.rpc;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.ipc.ProtocolSignature;
import org.apache.hadoop.ipc.RPC;
import org.apache.hadoop.ipc.RPC.Server;
import java.io.IOException;
public class RPCServer implements BizProtocol {
	public String sayHi(String name) {
		return "Hi ~ " + name;
	}
	public static void main(String[] args) throws Exception {
		Configuration conf = new Configuration();
		Server server = new RPC.Builder(conf).setInstance(new RPCServer()).setProtocol(BizProtocol.class).setBindAddress("192.168.9.1").setPort(9527).build();
		server.start();
	}
}

服务端对象通过new RPC.Builder().builder()的方式来获取,setInstance()为注册的对象,setProtocol()方法为开放的接口,setBindAddress()为注册的IP,setPort为注册的端口。
接口定义:

public interface BizProtocol{
	//版本号,默认情况下,不同版本号的RPC Client和Server之间不能相互通信
	public static final long versionID = 10010L;	
	public String sayHi(String name);	
}

有的人说定义的实体类要继承VersionedProtocol类,但是我没有继承,重写里面的两个方法,功能也没有问题。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值