1.RPC简介
Remote Procedure Call 远程过程调用协议
RPC——远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。
RPC采用客户机/服务器模式。请求程序就是一个客户机,而服务提供程序就是一个服务器。首先,客户机调用进程发送一个有进程参数的调用信息到服务进程,然后等待应答信息。在服务器端,进程保持睡眠状态直到调用信息的到达为止。当一个调用信息到达,服务器获得进程参数,计算结果,发送答复信息,然后等待下一个调用信息,最后,客户端调用进程接收答复信息,获得进程结果,然后调用执行继续进行。
hadoop的整个体系结构就是构建在RPC之上的(见org.apache.hadoop.ipc)
RPC类似于webservice,将服务发布为一个service。RPC与hadoop没有关系,如果需要我们可以在普通的项目中使用RPC机制,RPC存在commons包中。
2.首先了解Socket通信过程:(以webservice为例)
3.RPC机制(以登录为例介绍)
用到的技术:动态代理+反射+socket通信
4.RPC的例子,按照上面的思路实现登录
登录的Service部署在linux虚拟机中,以服务的形式发布(RPC发布),登录的Controller在windows中生成代理对象然后进行登录。
1.Linux中利用RPC机制发布server(发布service作为server)
LoginService .java (需要定义一个Long型的版本号)
package cn.qlq.rpc; import java.sql.SQLException; public interface LoginService { /** * service's verionID */ public static final long versionID=1L; /** * login method * @param username * @param password * @return * @throws SQLException */ public abstract String login(String username,String password)throws SQLException; }
LoginServiceImpl .java 实现类
package cn.qlq.rpc; import java.sql.SQLException; public class LoginServiceImpl implements LoginService { @Override public String login(String username, String password) throws SQLException { // TODO Auto-generated method stub return username+" logged successfully "; } }
发布一个service作为server的类。
1.创建builder
2.绑定地址,端口,需要发布的类的接口,类的实例对象
3.用builder.build()获取server
4.用server.start()发布server
package cn.qlq.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.Server; /** * publish loginService * * @author root * */ public class Publisher { public static void main(String[] a) throws HadoopIllegalArgumentException, IOException { Builder builder = new RPC.Builder(new Configuration()); builder.setBindAddress("192.168.2.130").setPort(888).setProtocol(LoginService.class) .setInstance(new LoginServiceImpl()); // create server and publish service Server server = builder.build(); server.start(); } }
2.Windows利用RPC机制生成代理对象然后访问上面发布的server
1.需要将接口复制到windows中;(注意,这里的LoginService 接口所在包必须与linux中一样,否则会报协议异常)
package cn.qlq.rpc; import java.sql.SQLException; /** * 登录的Service接口 * @author liqiang * */ public interface LoginService { /** * service's verionID */ public static final long versionID=1L; /** * login method * @param username * @param password * @return * @throws SQLException */ public abstract String login(String username,String password)throws SQLException; }
2.生成代理对象,访问server进行登录:
package cn.qlq.rpc; import java.io.IOException; import java.net.InetSocketAddress; import java.sql.SQLException; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.ipc.RPC; /** * 登录的controller,调用hadoop的RPC生成代理对象然后访问server * * @author liqiang * */ public class LoginController { public static void main(String[] args) throws IOException, SQLException { //1.生成代理对象 LoginService proxy = RPC.getProxy(LoginService.class, 1L, new InetSocketAddress("192.168.2.130", 10000),new Configuration()); //2.访问server String result = proxy.login("meinv", "111111"); System.out.println(result); } }
结果:
meinv logged successfully
注意:发布server的接扣的包必须与调用的接口所在包一样,否则会报未知协议异常。
总结:
RPC机制就像webservice一样,使得程序可以运行在不同的主机上,通过socket调用,RPC更简单。发布服务与调用服务都被封装为方法。
这样做的好处就是当我们修改了实现登录方法的代码之后不需要重新部署客户端代码,实现和接口分离。
我们也可以在普通的web项目中利用此机制,发布server实现功能共享。