Hadoop中的RPC机制
1. RPC——远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。
2. RPC采用客户机/服务器模式。请求程序就是一个客户机,而服务提供程序就是一个服务器。首先,客户机调用进程发送一个有进程参数的调用信息到服务进程,然后等待应答信息。在服务器端,进程保持睡眠状态直到调用信息的到达为止。当一个调用信息到达,服务器获得进程参数,计算结果,发送答复信息,然后等待下一个调用信息,最后,客户端调用进程接收答复信息,获得进程结果,然后调用执行继续进行。
3. hadoop的整个体系结构就是构建在RPC之上的(见org.apache.hadoop.ipc)。
下面来看一张RPC调用关系的图:
我们假设loginController和loginService分别在客户端和服务端,它们之间的调用需要通过socket通信实现。RPC机制就是利用了动态代理、反射以及socket通信。通过该机制,我们在客户端只需要写红色框内的两行代码,即可以实现我们需要的功能。即得到代理对象,然后调用该对象的login()方法。接下来,我们把过程详细化:
客户端和服务端需要实现相同的业务接口,整个流程如图所示。
我们写一个简单的Demo来演示一下:
之前的jar包和配置文件需要提前准备好。
客户端代码:
LoginService接口:
package cn.darrenchan.hadoop.rpc; public interface LoginService { public static final long versionID = 1L; public String login(String username, String password); }
LoginController代码:
package cn.darrenchan.hadoop.rpc; import java.io.IOException; import java.net.InetSocketAddress; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.ipc.RPC; public class LoginController { public static void main(String[] args) throws IOException { // 这一行是在windows下运行才用到的 System.setProperty("hadoop.home.dir", "E:\\大数据教程Hadoop8天\\hadoop-2.4.1"); LoginService proxy = RPC .getProxy(LoginService.class, 1L, new InetSocketAddress( "weekend110", 10000), new Configuration()); String result = proxy.login("陈驰", "123456"); System.out.println(result); } }
服务端代码:
LoginService接口:
package cn.darrenchan.hadoop.rpc; public interface LoginService { public static final long versionID = 1L; public String login(String username, String password); }
LoginServiceImpl实现类:
package cn.darrenchan.hadoop.rpc; public class LoginServiceImpl implements LoginService { @Override public String login(String username, String password) { return username + " logged in successfully"; } }
Starter启动类:
package cn.darrenchan.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.Builder; import org.apache.hadoop.ipc.RPC.Server; public class Starter { public static void main(String[] args) throws HadoopIllegalArgumentException, IOException { Builder builder = new RPC.Builder(new Configuration()); //port is random builder.setBindAddress("weekend110").setPort(10000) .setProtocol(LoginService.class) .setInstance(new LoginServiceImpl()); Server server = builder.build(); server.start(); } }
运行先启动服务端,然后运行客户端去连接,最后的运行效果如图: