RPC是远程过程调用(Remote Procedure Call),即远程调用其他虚拟机中运行的java object。RPC是一种客户端/服务器模式,那么在使用时包括服务端代码和客户端代码,还有我们调用的远程过程对象。简单的理解可以看下图:
Hadoop的RPC主要是通过Java的动态代理与反射实现,代理类是由java.lang.reflect.Proxy类在运行期时根据接口,采用Java反射功能动态生成的,并且结合java.lang.reflect.InvocationHandler来处理客户端的请求,当用户调用这个动态生成的实现类时,实际上是调用了InvocationHandler实现类的invoke方法。RPC源代码在org.apache.hadoop.ipc下,有以下几个主要类:
Client: 客户端,连接服务器、传递函数名和相应的参数、等待结果;
Server:服务器端,主要接受Client的请求、执行相应的函数、返回结果;
VersionedProtocol:通信双方所遵循契约的父接口;
RPC:RPC通信机制,主要是为通信的服务方提供代理。
我们可以看到,客户端和服务端进行通信,双方必须遵循一个契约。这个契约就是规定了双方之间可以干什么和不能干什么。
现在我们暂时做太多原理上的解释和源码上的分析,后面我会一一讲解,现在我们通过一个小例子来体会一下Hadoop的RPC。
我们暂时不使用hadoop给我们提供的契约,我们自己定义一个契约。我的服务端的程序是写在linux环境中的,项目名称叫做hadoop-rpc-server.客户端程序是写在windows环境中的,项目的命中叫做hadoop-rpc-client.同时ServerClientProtocol契约服务端和客户端双发必须都持有。
一、服务端
契约接口:
package com.npf.hadoop.rpc;
public interface LoginService {
public static final long versionID = 1L;
public String login(String username,String password);
}
契约接口的实现类:
package com.npf.hadoop.rpc;
public class LoginServiceImpl implements LoginService {
@Override
public String login(String username, String password) {
return username+" login successfully.";
}
}
package com.npf.hadoop.rpc;
import java.io.IOException;
import org.apache.hadoop.HadoopIllegalArgumentException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.ipc.RPC;
import org.apache.hadoop.ipc.RPC.Server;
public class ServerStart {
public static void main(String[] args) throws HadoopIllegalArgumentException, IOException {
RPC.Builder builder = new RPC.Builder(new Configuration());
builder.setInstance(new LoginServiceImpl()).setBindAddress("uatciti").setPort(9999).setProtocol(LoginService.class);
Server server = builder.build();
server.start();
}
}
运行ServerStart程序,就说明我们的服务器已经启动了。
二、客户端
契约接口,和服务端一模一样。
package com.npf.hadoop.rpc;
public interface LoginService {
public static final long versionID = 1L;
public String login(String username, String password);
}
调用服务器提供的服务:
package com.npf.hadoop.rpc;
import java.io.IOException;
import java.net.InetSocketAddress;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.ipc.RPC;
public class UserLoginController {
public static void main(String[] args) throws IOException {
Configuration conf = new Configuration();
LoginService proxy = RPC.getProxy(LoginService.class, 1L,new InetSocketAddress("uatciti", 9999), conf);
String result = proxy.login("zhangsan", "123456");
System.out.println(result);
}
}
运行结果: