。下面的SessionManager类中的initializeMnemosyne()方法可以显示出这一切是如何完成的:
public static void initializeMnemosyne(String[] rmiURLs)
{
// 设置当机服务器的处理程序
FailoverHandler fh = new FailoverHandler(null, rmiURLs);
// 得到Mnemosyne. 的一个实例
_Mnemosyne =
(Mnemosyne)Proxy.newProxyInstance(Mnemosyne.class.getClassLoader(),
new Class[] { Mnemosyne.class },
fh );
}
如果用Proxy类获取Mnemosyne的实例,所有的方法调用必须通过FailoverHandler的 invoke()方法进行。当有方法访问Mnemosyne时,FailoverHandler将试着调用该方法访问一个远程对象。如果方法调用失败(例如服务器关机),FailoverHandler将从提供给构造器的URL清单中再取得下一个URL,这样就会无缝地转向下一个对话服务器。
// 建立远程加载类的URL清单
public FailoverHandler(Remote delegate, String[] delegateURLS)
{
this.delegateURLS = delegateURLS;
// 如果这个URL无效,则获取下一个有效的URL
try {
this.delegate =
((delegate == null)?getNextValidDelegate():delegate);
} catch (RemoteException ex) {
// 如果发生远程意外错误,则该URL不能使用,向调用者发送一个 //IllegalArgumentException事件
throw new IllegalArgumentException("Remote URLs could not "
+ "be found");
}
}
public Object invoke(Object proxy,
Method method,
Object[] arguments)
throws Throwable
{
while(true)
{
try
{
file:// 尝试对获得的最后一个URL调用被调用的方法
return method.invoke(delegate, arguments);
}
catch(InvocationTargetException invocationTargetException)
{
file://如果获得的URL无效,则取下一个URL
try
{
throw invocationTargetException.getTargetException();
}
catch(RemoteException remoteException)
{
delegate = getNextValidDelegate();
}
}
}
}
file://从构造器中的URL清单中获得下一个URL
protected Remote getNextValidDelegate() throws RemoteException
{
for(int i = 0; i < delegateURLS.length;i++)
{
try
{
return Naming.lookup(delegateURLS[i]);
}
catch(Exception exception)
{
}
}
throw new RemoteException("All lookup failed");
}
分布式对话服务器的管理(5)
时间:2010-12-26
当使用FailoverHandler对象时,从一个对话服务器向另一个对话服务器的转换对于调用Mnemosyne的任何用户端机器都是透明的。
尽管我们已经能够访问对话服务器,而且可以避免单一点故障,我们还必须为HttpSession建立一个封装对象,而SessionWrapper就是这样一个对象,而且,它还假定HttpSession的执行也是串行化的。如果它不是串行化的,可以很方便地修改封装对象将对话的信息转移到一个哈希表中并在其他成员变量中保留其他信息(ID、创作时间等信息。)。
public interface SessionWrapper extends Memory
{
/**
* 得到HttpSession的信息。
*/
public HttpSession getSession();
}
public class SessionWrapperImpl implements SessionWrapper
{
/**识别该对话的关键字 */
protected String _id;
/** 当前HttpSession的信息。 */
protected HttpSession _sess;
/**
* 建立ID,但没有建立对话的其他信息,可用于通过read寻找一个对话。
*/
public SessionWrapper(String id) {
_id = id;
}
/**
* 建立一个带对话的SessionWrapper。其ID与对话的ID相同。
*/
public SessionWrapper(HttpSession sess) {
_sess = sess;
_id = sess.getId();
}
/**
* 如果Memory对象是SessionWrapper的一个实例,当前的SessionWrapper
* 已经建立了与对象相同
|