利用语言与平台特性改进RMI分布计算框架 |
时间:2011-04-23 作者:秩名 |
|
|
客户端使用远程引用调用方法,作为Stub/Skeleton的经典步骤,客户端的调用“代理“给Stub,可以在HelloWorldImp_Stub.java中看到ref.invoke(this, _fld$method_hit_0, null,0x9339f0d6bc98fe87L),然后Stub与JRMP引擎交互,由JRMP引擎来负责编组(返回时自然就是解列)远程引用,调用方法,方法参数等,并与服务器端JRMP通信,传递调用相关信息。服务器端JRMP引擎将获得的信息递交给Skeleton,Skeleton负责解列,并且从ObjectTable中获得远程对象,将调用“分发“给它执行,HelloWorldImp_Skel.java中可见public void dispatch(Remote remote, RemoteCall remotecall,int i, long l),然后编组返回结果,沿相反的途径回传到客户端。
上面已经基本将核心步骤讲述了。可以参看图2。
图2
3Java语言的几种特性
3.1 Java的Serialization特性
Serialization特性是在JDK 1.1中增添的,一个对象只要implementsSerializable,
就可以实现”持久化”。持久化能力表示对象可以写入介质,然后再从介质中读出并在内存中恢复原状态的能力。对象的这种能力对于网络应用非常的重要。因为它可以支持对象在网络传输过程中,屏蔽系统的差异。我们关注的是接口中的ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException方法,它是用于在对象反序列化时,如果你希望用其它的对象来替代原先的对象,你就可以在这里实施。
3.2 Java的Dynamic ClassLoading特性
这就是所谓的“代码移动”基础。它是Java最大的特色之一。它允许代码从网络下载执行。经典的应用是著名的Applet。Java类库中相关类的继承树为:java.lang.Object->java.lang.ClassLoader->java.security.SecureClassLoader->java.net.UrlClassLoader和java.lang.Object->java.rmi.server.RmiClassLoader。ClassLoader提供多种形式的类加载功能,特别是基于网络获得字节流,在本地从新映射类定义并加载的能力。UrlClassLoader提供基于网络url集的类加载。RmiClassLoader提供了一个statci功能函数集,一般由Rmi Runtime使用以在Rmi编组解列时实现注释类路径信息、基于网络的类加载等等特性。
3.3Java的Dynamic Proxy特性
Dynamic Proxy特性是在JDK 1.3中添加的,它遵循Proxy模式的思想。一个DynamciProxy可“代理”一组interface的实现,并且将实际方法调用代理给一个InvocationHandler实施。通过这种特性,我们可以方便的实现很多经典的应用,如为一组对象提供一个入口,从而实现在不改变类设计的情况下增加新的功能或者实现拦截器等等。
4利用上述Java特性改进RMI模型实施
就目前来说,RMI解决方案一般作为企业分布架构的基础。当然,企业级应用中,安全性、事务性、系统日记等性征都是很必要的,那么我们就设想是否可以在RMI层实施这些特性,从而建立设计更优秀、功能更强大、扩展性更强、维护更方便的企业级系统。经过探索,利用上述Java特性我们实现了这一构想,设计出Interceptor(拦截器)-RMI框架。图3
图3
需要解决的核心问题和相应的解决方案如下:
1.为了客户端从服务器端下载Stub并能够安装拦截器,我们需要替换掉服务器端默认的类加载器,用DynamicClassLoader替代。
public classDynamicClassLoader extends URLClassLoader{
/*… … … … */
protectedClass findClass(String name) throws ClassNotFoundException{
if(name.endsWith('_Stub')){
name = name.substring(0,name.length()-5);
Class cl = loadClass(name);
currentClass.set(cl.getInterfaces()[0]);
returnDynamicRemoteStub.class;
}else{ returnsuper.findClass(name); }
}
这样,我们在加载远程对象的时候,可以使用自己的ClassLoader,来动态替换Stub。
2. 那么DynamicRemoteStub是什么呢?
public class DynamicRemoteStub extends RemoteStub{
/*… … … … */
ObjectreadResolve() throws ObjectStreamException
{
if(cl == null) return this;
DynamicStubHandlerstubHandler = new DynamicStubHandler();
Objectproxy = Proxy.newProxyInstance(cl.getClassLoader(),
new Class[] { cl },
stubHandler);
stubHandler.setProxy(this);
cl= null;
returnproxy;
}
}
这里我们需要注意的是readResolve,它是在对象序列化的时候调用,实施一定的方法,用其它的对象来代替原来解序列的对象。我们在这里实施这一行为返回代理,在于为客户端添加拦截器。
3. 那么代理的处理者InvocationHandler是什么?就是DynamicStubHandler:
public classDynamicStubHandler implements
InvocationHandler,java.io.Serializable{
/*… … … … */
//InvocationHandler implementation
publicObject invoke(Object proxy,
Method method,
Object[] args) throws Throwable{
returnstub.getRef().invoke(stub, method, args, getHash(method));
}
}
/*… … … … */
我们可以看到,returnstub.getRef().invoke(stub, method, args,
getHash(method)),通过它,客户端在经过任意个拦击器调用后,最后实施将远程对象的调用。
4. 服务器端的拦截器实施。
HelloWorld hw = newHelloWorldImpl();
UnicastRemoteObject.exportObject(hw);
hw = (HelloWorld)Proxy.newProxyInstance(HelloWorld.class.getClassLoader(),
new Class[] { HelloWorld.class },
new LogProxy(hw));
UnicastRemoteObject.exportObject(hw);
/* …… … … */
hw = (HelloWorld) Proxy.newProxyInstance(hw.getClass().getClassLoader(),
new Class[] { HelloWorld.class },
2/3 首页 上一页 1 2 3 下一页 尾页 |
|
|
|