Java开发大型互联网分布式架构如何实现一个分布式RPC框架

啊叻?视频不见了?&nbsp>&nbsp
&nbsp>&nbsp
&nbsp>&nbsp
基于Java实现的RPC框架
摘要:前言今年7月份左右报名参加了阿里巴巴组织的高性能中间件挑战赛,这次比赛不像以往的比赛,是从一个工程的视角来比赛的。这个比赛有两个赛题,第一题是实现一个RPC框架,第二道题是实现一个Mom消息中间件。RPC题目如下一个简单的RPC框架RPC(RemoteProcedureCall)——远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,R
今年7月份左右报名参加了阿里巴巴组织的高性能中间件挑战赛,这次比赛不像以往的比赛,是从一个工程的视角来比赛的。 这个比赛有两个赛题,第一题是实现一个RPC框架,第二道题是实现一个Mom消息中间件。 RPC题目如下
一个简单的RPC框架
RPC(Remote Procedure Call )——远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。
框架——让编程人员便捷地使用框架所提供的功能,由于RPC的特性,聚焦于应用的分布式服务化开发,所以成为一个对开发人员无感知的接口代理,显然是RPC框架优秀的设计。
1.要成为框架:对于框架的使用者,隐藏RPC实现。
2.网络模块可以自己编写,如果要使用IO框架,要求使用netty-4.0.23.Final。
3.支持异步调用,提供future、callback的能力。
4.能够传输基本类型、自定义业务类型、异常类型(要在客户端抛出)。
5.要处理超时场景,服务端处理时间较长时,客户端在指定时间内跳出本次调用。
6.提供RPC上下文,客户端可以透传数据给服务端。
7.提供Hook,让开发人员进行RPC层面的AOP。
注:为了降低第一题的难度,RPC框架不需要注册中心,客户端识别-DSIP的JVM参数来获取服务端IP。
满足所有要求。 性能测试。
测试时会运行rpc-use-demo中的测试用例,测试的demo包由测试工具做好。
参赛者必须以com.alibaba.middleware.race.rpc.api.impl.RpcConsumerImpl为全类名,继承com.alibaba.middleware.race.rpc.api.RpcConsumer,并覆写所有的public方法。
参赛者必须以com.alibaba.middleware.race.rpc.api.impl.RpcProviderImpl为全类名,继承com.alibaba.middleware.race.rpc.api.RpcProvider,并覆写所有的public方法。
参赛者依赖公共maven中心库上的三方包,即可看到一个示例的demo,按照对应的包名,在自己的工程中建立对应的类(包名、类名一致)。
三方库里的代码起到提示的作用,可以作为参考,不要在最终的pom中依赖。
所以最终参赛者需要打出一个rpc-api的jar包,供测试工程调用。 (注意,参考完rpc-api的示例后,请从pom依赖中将其删除,避免依赖冲突)
测试Demo工程请参考Taocode SVN上的代码。
题目中推荐的网络框架使用Netty4来实现,这个RPC框架中需要实现的有 1. RPC客户端 2. RPC服务端
RPC客户端的实现
RPC客户端和RPC服务器端需要一个相同的接口类,RPC客户端通过一个代理类来调用RPC服务器端的函数RpcConsumerImpl的实现......package com.alibaba.middleware.race.rpc.api.import java.lang.reflect.InvocationHimport java.lang.reflect.Mimport java.lang.reflect.Pimport java.util.ArrayLimport java.util.HashMimport java.util.LinkedLimport java.util.Limport java.util.Mimport java.util.UUID;import java.util.concurrent.atomic.AtomicLimport com.alibaba.middleware.race.rpc.aop.ConsumerHimport com.alibaba.middleware.race.rpc.api.RpcCimport com.alibaba.middleware.race.rpc.async.ResponseCallbackLimport com.alibaba.middleware.race.rpc.context.RpcCimport com.alibaba.middleware.race.rpc.model.RpcRimport com.alibaba.middleware.race.rpc.model.RpcRimport com.alibaba.middleware.race.rpc.netty.RpcCimport com.alibaba.middleware.race.rpc.netty.RpcNettyCimport com.alibaba.middleware.race.rpc.tool.Tpublic class RpcConsumerImpl extends RpcConsumer implements InvocationHandler { private static AtomicLong callTimes = new AtomicLong(0L); private RpcC private List&RpcConnection& connection_ private Map&String,ResponseCallbackListener& asyncM private Class&?& interfaceC private S private ConsumerH public Class&?& getInterfaceClass() { return interfaceC } public String getVersion() { } public int getTimeout() { this.connection.setTimeOut(timeout); } public ConsumerHook getHook() { } RpcConnection select() { //Random rd=new Random(System.currentTimeMillis()); int d=(int) (callTimes.getAndIncrement()%(connection_list.size()+1)); if(d==0) else { return connection_list.get(d-1); } } public RpcConsumerImpl() { //String ip=System.getProperty(&SIP&); String ip=&127.0.0.1&; this.asyncMethods=new HashMap&String,ResponseCallbackListener&(); this.connection=new RpcNettyConnection(ip,8888); this.connection.connect(); connection_list=new ArrayList&RpcConnection&(); int num=Runtime.getRuntime().availableProcessors()/3 -2; for (int i = 0; i & i++) { connection_list.add(new RpcNettyConnection(ip, 8888)); } for (RpcConnection conn:connection_list) { conn.connect(); } } public void destroy() throws Throwable { if (null != connection) { connection.close(); } } @SuppressWarnings(&unchecked&) public &T& T proxy(Class&T& interfaceClass) throws Throwable { if (!interfaceClass.isInterface()) { throw new IllegalArgumentException(interfaceClass.getName() + & is not an interface&); } return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class&?&[] { interfaceClass }, this); } @Override public RpcConsumer interfaceClass(Class&?& interfaceClass) { // TODO Auto-generated method stub this.interfaceClass=interfaceC } @Override public RpcConsumer version(String version) { // TODO Auto-generated method stub this.version= } @Override public RpcConsumer clientTimeout(int clientTimeout) { // TODO Auto-generated method stub this.timeout=clientT } @Override public RpcConsumer hook(ConsumerHook hook) { // TODO Auto-generated method stub this.hook= } @Override public Object instance() { // TODO Auto-generated method stub try { return proxy(this.interfaceClass); } catch (Throwable e) { e.printStackTrace(); } } @Override public void asynCall(String methodName) { // TODO Auto-generated method stub asynCall(methodName, null); } @Override public &T extends ResponseCallbackListener& void asynCall( String methodName, T callbackListener) { this.asyncMethods.put(methodName, callbackListener); this.connection.setAsyncMethod(asyncMethods); for (RpcConnection conn:connection_list) { conn.setAsyncMethod(asyncMethods); } } @Override public void cancelAsyn(String methodName) { // TODO Auto-generated method stub this.asyncMethods.remove(methodName); this.connection.setAsyncMethod(asyncMethods); for (RpcConnection conn:connection_list) { conn.setAsyncMethod(asyncMethods); } } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub List&String& parameterTypes = new LinkedList&String&(); for (Class&?& parameterType : method.getParameterTypes()) { parameterTypes.add(parameterType.getName()); } RpcRequest request = new RpcRequest(); request.setRequestId(UUID.randomUUID().toString()); request.setClassName(method.getDeclaringClass().getName()); request.setMethodName(method.getName()); request.setParameterTypes(method.getParameterTypes()); request.setParameters(args); if(hook!=null) hook.before(request); RpcResponse response = try { request.setContext(RpcContext.props); response = (RpcResponse) select().Send(request,asyncMethods.containsKey(request.getMethodName())); if(hook!=null) hook.after(request); if(!asyncMethods.containsKey(request.getMethodName())&;&;response.getExption()!=null) { Throwable e=(Throwable) Tool.deserialize(response.getExption(),response.getClazz()); throw e.getCause(); } } catch (Throwable t) { //t.printStackTrace(); //throw new RuntimeException(t); } finally {// if(asyncMethods.containsKey(request.getMethodName())&;&;asyncMethods.get(request.getMethodName())!=null)// {// cancelAsyn(request.getMethodName());// } } if(response==null) { } else if (response.getErrorMsg() != null) { throw response.getErrorMsg(); } else { return response.getAppResponse(); } }}RpcCconsumer = (RpcConsumer) getConsumerImplClass().newInstance();consumer.someMethod();
因为consumer对象是通过代理生成的,所以当consumer调用的时候,就会调用invoke函数,我们就可以把这次本地的函数调用的信息通过网络发送到RPC服务器然后等待服务器返回的信息后再返回。
服务器实现
RPC服务器主要是在收到RPC客户端之后解析出RPC调用的接口名,函数名以及参数。package com.alibaba.middleware.race.rpc.api.import io.netty.channel.ChannelHandlerCimport io.netty.channel.ChannelInboundHandlerAimport java.lang.reflect.Mimport java.util.HashMimport java.util.Mimport net.sf.cglib.reflect.FastCimport net.sf.cglib.reflect.FastMimport com.alibaba.middleware.race.rpc.context.RpcCimport com.alibaba.middleware.race.rpc.model.RpcRimport com.alibaba.middleware.race.rpc.model.RpcRimport com.alibaba.middleware.race.rpc.serializer.KryoSimport com.alibaba.middleware.race.rpc.tool.ByteObjCimport com.alibaba.middleware.race.rpc.tool.ReflectionCimport com.alibaba.middleware.race.rpc.tool.T/** * 处理服务器收到的RPC请求并返回结果 * @author sei.zz * */public class RpcRequestHandler extends ChannelInboundHandlerAdapter { //对应每个请求ID和端口好 对应一个RpcContext的M private static Map&String,Map&String,Object&& ThreadLocalMap=new HashMap&String, Map&String,Object&&(); //服务端接口-实现类的映射表 private final Map&String, Object& handlerM KryoSerialization kryo=new KryoSerialization(); public RpcRequestHandler(Map&String, Object& handlerMap) { this.handlerMap = handlerM } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println(&active&); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { // TODO Auto-generated method stub System.out.println(&disconnected&); } //更新RpcContext的类容 private void UpdateRpcContext(String host,Map&String,Object& map) { if(ThreadLocalMap.containsKey(host)) { Map&String,Object& local=ThreadLocalMap.get(host); local.putAll(map);//把客户端的加进来 ThreadLocalMap.put(host, local);//放回去 for(Map.Entry&String, Object& entry:map.entrySet()){ //更新变量 RpcContext.addProp(entry.getKey(), entry.getValue()); } } else { ThreadLocalMap.put(host, map); //把对应线程的Context更新 for(Map.Entry&String, Object& entry:map.entrySet()){ RpcContext.addProp(entry.getKey(), entry.getValue()); } } } //用来缓存住需要序列化的结果 private static Object cacheName= private static Object cacheVaule= @Override public void channelRead( ChannelHandlerContext ctx, Object msg) throws Exception { RpcRequest request=(RpcRequest) String host=ctx.channel().remoteAddress().toString(); //更新上下文 UpdateRpcContext(host,request.getContext()); //TODO 获取接口名 函数名 参数 找到实现类 反射实现 RpcResponse response = new RpcResponse(); response.setRequestId(request.getRequestId()); try { Object result = handle(request); if(cacheName!=null&;&;cacheName.equals(result)) { response.setAppResponse(cacheVaule); } else { response.setAppResponse(ByteObjConverter.ObjectToByte(result)); cacheName= cacheVaule=ByteObjConverter.ObjectToByte(result); } } catch (Throwable t) { //response.setErrorMsg(t); response.setExption(Tool.serialize(t)); response.setClazz(t.getClass()); } ctx.writeAndFlush(response); } /** * 运行调用的函数返回结果 * @param request * @return * @throws Throwable */ private static RpcRequest methodCacheName= private static Object methodCacheValue= private Object handle(RpcRequest request) throws Throwable { String className = request.getClassName(); Object classimpl = handlerMap.get(className);//通过类名找到实现的类 Class&?& clazz = classimpl.getClass(); String methodName = request.getMethodName(); Class&?&[] parameterTypes = request.getParameterTypes(); Object[] parameters = request.getParameters();// Method method = ReflectionCache.getMethod(clazz.getName(),methodName, parameterTypes);// method.setAccessible(true); //System.out.println(className+&:&+methodName+&:&+parameters.length); if(methodCacheName!=null&;&;methodCacheName.equals(request)) { return methodCacheV } else { try { methodCacheName= if(methodMap.containsKey(methodName)) { methodCacheValue= methodMap.get(methodName).invoke(classimpl, parameters); return methodCacheV } else { FastClass serviceFastClass = FastClass.create(clazz); FastMethod serviceFastMethod = serviceFastClass.getMethod(methodName, parameterTypes); methodMap.put(methodName, serviceFastMethod); methodCacheValue= serviceFastMethod.invoke(classimpl, parameters); return methodCacheV } //return method.invoke(classimpl, parameters); } catch (Throwable e) { throw e.getCause(); } } } private Map&String,FastMethod& methodMap=new HashMap&String, FastMethod&(); @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { ctx.flush(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { //ctx.close(); //cause.printStackTrace(); ctx.close(); } }
handel函数通过Java的反射机制,找到要调用的接口类然后调用对应函数然后执行,然后返回结果到客户端,本次RPC调用结束。
本文地址http://blog.csdn.net/zhujunxxxxx ,如需转载请注明出处
以上是的内容,更多
的内容,请您使用右上方搜索功能获取相关信息。
若你要投稿、删除文章请联系邮箱:zixun-group@service.aliyun.com,工作人员会在五个工作日内给你回复。
云服务器 ECS
可弹性伸缩、安全稳定、简单易用
&40.8元/月起
预测未发生的攻击
&24元/月起
为您提供0门槛上云实践机会
你可能还喜欢
你可能感兴趣
阿里云教程中心为您免费提供
基于Java实现的RPC框架相关信息,包括
的信息,所有基于Java实现的RPC框架相关内容均不代表阿里云的意见!投稿删除文章请联系邮箱:zixun-group@service.aliyun.com,工作人员会在五个工作日内答复
售前咨询热线
支持与服务
资源和社区
关注阿里云
International博客分类:
早些天看Hadoop源码的时候了解到Hadoop分布式环境中各个组件间的通信采用的RPC,由于暂无时间深入分析Hadoop中的RPC实现方式。参考网上资料学习跟例子实现简易RPC框架。
一、什么是RPC
RPC(Remote Procedure Call Protocol)——协议,它是一种通过网络从远程程序上请求服务,而不需要了解底层网络技术的协议。假定某些的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI模型中,RPC跨越了和。RPC使得开发包括网络多程序在内的更加容易。JDK内部提供RMI实现RPC(仅限于JAVA对象的远程调用)。
二、利用RMI实现RPC
想要了解RMI详细知识请查看本人另一编blog《如何发布RMI服务》。
1、首先定义RMI服务器接口
package org.bird.
import java.io.S
import java.rmi.AccessE
import java.rmi.NotBoundE
import java.rmi.R
import java.rmi.RemoteE
public interface RMIServer extends Remote,Serializable {
static String DEFAULT_HOST = "127.0.0.1";
static int DEFAULT_PORT = 8888;
* 注册本地对象
* @param interfaceDefiner
* @param impl
* @throws InstantiationException
* @throws IllegalAccessException
public void registerLocalObject(Class&?& interfaceDefiner, Class&?& impl) throws RemoteException, InstantiationException, IllegalAccessE
* 注册远程对象
* @param interfaceDefiner
* @param impl
* @throws RemoteException
* @throws IllegalAccessException
* @throws InstantiationException
public void registerRemoteObject(Class&?& interfaceDefiner, Class&?& impl) throws RemoteException, InstantiationException, IllegalAccessE
* 卸载指定对象
* @param interfaceDefiner
* @throws RemoteException
* @throws NotBoundException
* @throws ClassNotFoundException
public void unregisterObject(Class&?& interfaceDefiner) throws RemoteException, NotBoundException, ClassNotFoundE
* 卸载所有对象
* @throws AccessException
* @throws RemoteException
* @throws NotBoundException
* @throws ClassNotFoundException
public void unregisterAllObjects() throws AccessException, RemoteException, NotBoundException, ClassNotFoundE
* 获取对象
* @param interfaceDefiner
public &T& T getObject(Class&T& interfaceDefiner) throws RemoteE
* @throws RemoteException
public void start() throws RemoteE
* 关闭服务器
* @param remote 是否同时关闭远程RMI服务
* @throws AccessException
* @throws RemoteException
* @throws NotBoundException
* @throws ClassNotFoundException
public void stop(boolean remote) throws AccessException, RemoteException, NotBoundException, ClassNotFoundE
* 关闭远程服务
* @throws RemoteException
public void remoteStop() throws RemoteE
* 判断服务器运行状态
* @throws RemoteException
public boolean isRunning() throws RemoteE
2、接着实现RMI服务器相关功能的实现类
package org.bird.
import java.rmi.AccessE
import java.rmi.ConnectE
import java.rmi.NotBoundE
import java.rmi.R
import java.rmi.RemoteE
import java.rmi.registry.LocateR
import java.rmi.registry.R
import java.rmi.server.UnicastRemoteO
import java.util.ArrayL
import java.util.HashM
import java.util.L
import java.util.M
import org.bird.rmi.support.L
public class RMIServerImpl extends UnicastRemoteObject implements RMIServer {
private static final long serialVersionUID = 1L;
private boolean isR
/** 本地主机RMI注册表 */
private Registry localRegistry =
/** 远程主机RMI注册表 */
private Registry remoteRegistry =
/** 远程服务器 */
private RMIServer remoteServer =
/** 缓存本地对象实例 */
private Map&String,Object& registeredLocalObjectMap = new HashMap&String,Object&();
/** 缓存远程对象实例 */
private Map&String,Remote& registeredRemoteObjectMap = new HashMap&String,Remote&();
public RMIServerImpl() throws RemoteException {
this(DEFAULT_HOST, DEFAULT_PORT);
public RMIServerImpl(int port) throws RemoteException {
this(DEFAULT_HOST, port);
public RMIServerImpl(String cip, int cport) throws RemoteException
registerLocalServer(cip, cport);
public RMIServerImpl(String cip,int cport, String sip, int sport) throws RemoteException
getRemoteServer(sip, sport);
registerLocalServer(cip, cport);
private void registerLocalServer(String cip, int cport) throws AccessException, RemoteException {
System.setProperty("java.rmi.server.hostname", cip);
if(localRegistry == null) {
localRegistry = LocateRegistry.getRegistry(cip, cport);
localRegistry.list();
} catch (Exception e) {
localRegistry = LocateRegistry.createRegistry(cport);//在本地主机创建并导出RMI注册表
} catch (RemoteException e1) {
throw new RuntimeException(e1);
localRegistry.rebind(getKey(cip, cport), this);
private void getRemoteServer(String sip, int sport) throws AccessException, RemoteException {
if(null == sip || "".equals(sip.trim())){
remoteRegistry = LocateRegistry.getRegistry(sip, sport);
remoteServer = (RMIServer) remoteRegistry.lookup(getKey(sip, sport));
} catch (ConnectException e) {
remoteRegistry =
throw new RemoteException("无法获取远程服务:" + getKey(sip, sport));
} catch (NotBoundException e) {
remoteRegistry =
throw new RemoteException("无法获取远程服务:" + getKey(sip, sport));
public void registerLocalObject(Class&?& interfaceDefiner,
Class&?& impl) throws InstantiationException, IllegalAccessException {
Object instance = impl.newInstance();
registeredLocalObjectMap.put(interfaceDefiner.getName(), instance);
System.out.println("注册本地对象:" + interfaceDefiner.getName());
public void registerRemoteObject(Class&?& interfaceDefiner, Class&?& impl)
throws RemoteException, InstantiationException, IllegalAccessException {
Object object = impl.newInstance();//反射实例化
if(!(object instanceof Remote)){
throw new ClassCastException("cannot be cast to java.rmi.Remote");
System.out.println("注册远程对象:" + interfaceDefiner.getName());
Remote instance = (Remote)
registeredRemoteObjectMap.put(interfaceDefiner.getName(), instance);
if (instance instanceof UnicastRemoteObject) {
localRegistry.rebind(interfaceDefiner.getName(), instance);//更新对此注册表中指定name的远程引用。
if(remoteServer != null) {
remoteServer.registerLocalObject(interfaceDefiner, impl);//对象实例直接推送到远程服务器端
Remote stub = UnicastRemoteObject.exportObject(instance, 0);
localRegistry.rebind(interfaceDefiner.getName(), stub);//更新对此注册表中指定name的远程引用。
if(remoteServer != null) {
remoteServer.registerLocalObject(interfaceDefiner, stub.getClass());//对象实例直接推送到远程服务器端
public void unregisterObject(Class&?& interfaceDefiner) throws AccessException, RemoteException, NotBoundException, ClassNotFoundException {
unregisterObject(interfaceDefiner.getName());
private void unregisterObject(String key) throws AccessException, RemoteException, NotBoundException, ClassNotFoundException {
if(registeredLocalObjectMap.containsKey(key)) {
registeredLocalObjectMap.remove(key);
System.out.println("注销本地对象:" + key);
}else if (registeredRemoteObjectMap.containsKey(key)) {
localRegistry.unbind(key);//移除RMI注册表中的绑定
Remote remote = registeredRemoteObjectMap.get(key);
if(remote != null) {
UnicastRemoteObject.unexportObject(remote, true);//从RMI中移除远程对象
registeredRemoteObjectMap.remove(key);
if(remoteServer != null) {
remoteServer.unregisterObject(Class.forName(key));//将推送到远程服务器上对象实例注销
System.out.println("注销远程对象:" + key);
public void unregisterAllObjects() throws AccessException, RemoteException, NotBoundException, ClassNotFoundException {
registeredLocalObjectMap.clear();//注销本地对象
List&String& keys = new ArrayList&String&();
for(String key : registeredRemoteObjectMap.keySet()) {
keys.add(key);
for(String key : keys) {
unregisterObject(key);
public &T& T getObject(Class&T& interfaceDefiner) throws RemoteException {
String key = interfaceDefiner.getName();
if(registeredLocalObjectMap.containsKey(key)) {
System.out.println("调用本地对象:" + interfaceDefiner.getName());
return (T) registeredLocalObjectMap.get(key);
if(registeredRemoteObjectMap.containsKey(key)) {
System.out.println("调用远程对象:" + interfaceDefiner.getName());
return (T) registeredRemoteObjectMap.get(key);
if(remoteServer != null) {
return remoteServer.getObject(interfaceDefiner);
public void start() throws RemoteException {
listener = new Listener(this);
this.isRuning =
listener.start();
public void stop(boolean remote) throws AccessException, RemoteException, NotBoundException, ClassNotFoundException {
unregisterAllObjects();
String[] names = localRegistry.list();
for(String name : names) {
localRegistry.unbind(name);
UnicastRemoteObject.unexportObject(localRegistry, true);
localRegistry =
if(remote && remoteServer != null){
remoteServer.remoteStop();
System.out.println("本地RMI服务器停止...");
System.exit(0);
public void remoteStop() throws RemoteException {
this.isRuning =
private String getKey(String name, int port) {
return name + "|" +
public boolean isRunning() {
return isR
3、然后再编写一个监听器用于监听服务器
package org.bird.rmi.
import java.rmi.AccessE
import java.rmi.NotBoundE
import java.rmi.RemoteE
import org.bird.rmi.RMIS
* RMI服务监听器
* @author liangjf
public class Listener extends Thread {
private RMIS
public Listener(RMIServer server) {
this.server =
public void run() {
System.out.println("RMI服务器启动...");
while(server.isRunning()) {
} catch (RemoteException e) {
e.printStackTrace();
server.stop(false);
} catch (AccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NotBoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
4、到目前一个简单的RPC框架就完成了。接着我们编写两个测试用例
package org.bird.rmi.test.
import java.rmi.R
import java.rmi.RemoteE
public interface Echo extends Remote {
public String sayHello(String name) throws RemoteE
package org.bird.rmi.test.
import java.rmi.R
import java.rmi.RemoteE
public interface Hello extends Remote {
public String sayHello(String name) throws RemoteE
package org.bird.rmi.test.
import java.rmi.RemoteE
public class EchoImpl implements Echo {
public EchoImpl() throws RemoteException {
public String sayHello(String name) {
return "Hello, " +
package org.bird.rmi.test.
import java.rmi.RemoteE
import java.rmi.server.UnicastRemoteO
public class RemoteHello extends UnicastRemoteObject implements Hello {
public RemoteHello() throws RemoteException {
// TODO Auto-generated constructor stub
private static final long serialVersionUID = 1L;
public String sayHello(String name) throws RemoteException {
return "Hello, " +
再编写一个服务器测试入口类
package org.bird.rmi.
import java.rmi.NotBoundE
import java.rmi.RemoteE
import org.bird.rmi.RMIS
import org.bird.rmi.RMIServerI
import org.bird.rmi.test.echo.E
import org.bird.rmi.test.echo.EchoI
import org.bird.rmi.test.echo.H
import org.bird.rmi.test.echo.RemoteH
public class MainServer {
* @param args
* @throws RemoteException
* @throws IllegalAccessException
* @throws InstantiationException
* @throws NotBoundException
public static void main(String[] args) throws RemoteException, InstantiationException, IllegalAccessException, NotBoundException {
RMIServer server = new RMIServerImpl(8888);
server.registerRemoteObject(Hello.class, RemoteHello.class);
server.registerRemoteObject(Echo.class, EchoImpl.class);
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
System.out.println("服务端JVM关闭...");
server.start();
最后写两个客户端的测试入口类
package org.bird.rmi.
import java.rmi.AccessE
import java.rmi.NotBoundE
import java.rmi.RemoteE
import org.bird.rmi.RMIS
import org.bird.rmi.RMIServerI
import org.bird.rmi.test.echo.H
public class MainClient1 {
* @param args
* @throws NotBoundException
* @throws RemoteException
* @throws ClassNotFoundException
* @throws IllegalAccessException
* @throws InstantiationException
* @throws InterruptedException
* @throws AccessException
public static void main(String[] args) throws RemoteException, NotBoundException, ClassNotFoundException, InstantiationException, IllegalAccessException, InterruptedException {
RMIServer client = new RMIServerImpl(RMIServer.DEFAULT_HOST, 9998, RMIServer.DEFAULT_HOST, RMIServer.DEFAULT_PORT);
Hello hello = client.getObject(Hello.class);
System.out.println(hello.sayHello("ljf"));
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
System.out.println("客户端1关闭.....");
client.stop(false);
package org.bird.rmi.
import java.rmi.AccessE
import java.rmi.NotBoundE
import java.rmi.RemoteE
import org.bird.rmi.RMIS
import org.bird.rmi.RMIServerI
import org.bird.rmi.test.echo.E
public class MainClient2 {
* @param args
* @throws NotBoundException
* @throws RemoteException
* @throws ClassNotFoundException
* @throws IllegalAccessException
* @throws InstantiationException
* @throws InterruptedException
* @throws AccessException
public static void main(String[] args) throws RemoteException, NotBoundException, ClassNotFoundException, InstantiationException, IllegalAccessException, InterruptedException {
RMIServer client = new RMIServerImpl(RMIServer.DEFAULT_HOST, 9999, RMIServer.DEFAULT_HOST, RMIServer.DEFAULT_PORT);
Echo echo = client.getObject(Echo.class);
System.out.println(echo.sayHello("飞飞"));
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
System.out.println("客户端2关闭.....");
client.stop(true);
5、测试用例编写完成后将RMIServer、RMIServerImpl、Listener、Echo、Hello、EchoImp、RemoteHello、MainServer这些类打包成可运行的server.jar;RMIServer、RMIServerImpl、Listener、Hello、MainClient1这些类打包成可以运行的client1.jar;RMIServer、RMIServerImpl、Listener、Echo、MainClient2这些类打包成可以运行的client2.jar
6、首先在命令行下运行server.jar7、再另打开一窗口运行client1.jar查看一下运行情况
8、另外再打开一个窗口运行client2.jar查看客户端与服务端的变化情况
总结:上面实现的RMI框架服务端与客户端可以相互调用(既是服务端也是客户端),可以注册本地对象或者注册远程对象,对象的调用就跟本地调用一样对上层使用者来说是完全透明的。
浏览: 19226 次
来自: 广西
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'}

我要回帖

更多关于 分布式互联网系统 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信