盡管我們已經(jīng)能夠訪問對話服務(wù)器,而且可以避免單一點故障,我們還必須為HttpSession建立一個封裝對象,而SessionWrapper就是這樣一個對象,而且,它還假定HttpSession的執(zhí)行也是串行化的。如果它不是串行化的,可以很方便地修改封裝對象將對話的信息轉(zhuǎn)移到一個哈希表中并在其他成員變量中保留其他信息(ID、創(chuàng)作時間等信息。)。
public interface SessionWrapper extends Memory { /** * 得到HttpSession的信息。 */ public HttpSession getSession(); }
public class SessionWrapperImpl implements SessionWrapper {
/**識別該對話的關(guān)鍵字 */ protected String _id; /** 當(dāng)前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的一個實例,當(dāng)前的SessionWrapper * 已經(jīng)建立了與對象相同的ID,則此方法返回的值為真。 */ public boolean equalsMemory(Memory m) { return (m instanceof SessionWrapper && _id != null && _id.equals(((SessionWrapper)m)._id)); }
/** * 得到HttpSession的信息。 */ public HttpSession getSession() { return _sess; } }
SessionWrapper類執(zhí)行了Memory的界面,因此,HttpSession對象的ID可以與遠(yuǎn)程對話的ID進(jìn)行比較。
最后需要創(chuàng)建read()、write()和delete(),以對遠(yuǎn)程對話進(jìn)行管理。我們向SessionManager類添加三個靜態(tài)類:
/** * 從在初始化時建立的Mnemosyne中得到HttpSession信息。 */ public static HttpSession getSession(String id) throws RemoteException { try { SessionWrapper result = (SessionWrapper)_Mnemosyne.read(new SessionWrapper(id), null); return result.getSession(); } catch (TransactionException ex) { // 由于沒有處理事物,因此不會有事務(wù)意外被放棄。 ex.printStackTrace(); } return null; }
/** * 在初始化時指定的Mnemosyne中保存對話信息。 */ public static void saveSession(HttpSession sess) throws RemoteException { try { _Mnemosyne.write(new SessionWrapper(sess), null); } catch (TransactionException ex) { file://由于沒有處理事物,因此不會有事務(wù)意外被放棄。 ex.printStackTrace(); } }
/** * 從在初始化時指定的Mnemosyne中刪除一個對話。 */ public static void removeSession(String id) throws RemoteException { try { _Mnemosyne.take(new SessionWrapper(id), null); } catch (TransactionException ex) { // /由于沒有處理事物,因此不會有事務(wù)意外被放棄。 ex.printStackTrace(); } }
在servlet中,可以以如下方式管理對話:
public void init(ServletConfig conf) throws ServletException { // 調(diào)用一個方法得到指示對話服務(wù)器位置的RMI URL清單 // 例如://server1.foo.com/MnemosyneImpl, //server2.foo.com/MnemosyneImpl,等 String[] urls = getURLs(conf); // Method to get the URLs from properties for the session servers SessionManager.initializeMnemosyne(urls) }
public void doGet(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
file:// 得到存貯在cookie中的對話,僅僅是為了得到其ID。 HttpSession baseSess = req.getSession() file://根據(jù)得到的ID,從Mnemosyne中得到真正的對話 HttpSession realSess = SessionManager.getSession(base.getId());
SessionManager.saveSession(realSess); }
結(jié)論
盡管這篇文章討論了一個分布式對話管理的例子,但我們可以將這一技術(shù)用于管理必須容忍任一節(jié)點出錯的分布式內(nèi)存管理系統(tǒng)中。Mnemosyne還可以用在成員不斷加入和離開的P2P應(yīng)用中。通過使用Mnemosyne,任何一個成員都可以與系統(tǒng)進(jìn)行快速同步,而無需要求為保持系統(tǒng)有效而必須保證某一結(jié)點不出故障。
|