設計不受傳統網絡限制的 P2P 系統

設計不受傳統網絡限制的 P2P 系統
作者:chris  時間:2006-12-30 16:06:06  出處:Matrix  人氣:81
  隨着移動計算的普及和嵌入式可聯網微處理器的無處不在的應用,TCP/IP

終於顯露出它已經顯得過時。設計 Jxta 的初衷就是要突破當今基於 TCP/IP 的

網絡的限制,從而擴展因特網所能觸及的範圍。在 developerWorks 的討論

Jxta 的系列的這最後一篇文章中,Sing Li 舉例說明了體現這種擴展的系統,

並解決了一個實際問題。您將看到 Jxta 不受客戶機/服務器網絡的典型約束的

限制。請單擊本文頂部或底部的討論,在討論論壇與作者及其他讀者共享關於本

文的心得。
  
   到本系列文章的這裏爲止,我們仔細考察了 Jxta,一個 Java 參考實現的

新 P2P 平臺,是如何工作的。在第一部分中,我們瞭解了 Jxta 的互操作特徵

。Jxta 被定義爲一組互操作協議,可以跨硬件平臺、操作系統和編程語言實現

。我們也討論了 Jxta 的操作模型和包括對等機、對等組、服務和管道在內的許

多重要概念。在第二部分中,我們的着眼點是建立和運行 Jxta。我們探討了一

個 Jxta 應用程序 — Jxta shell — 並經歷了創建管道並從一個對等機發送消

息到另一個對等機的情形。在我們編寫 Jxta shell 擴展時,我們第一次獲得了

用 Jxta API 編程的經驗。迄今爲止,我們討論 Jxta 的方式都是從下到上的。

對於像我們這樣具有系統編程和網絡工程背景的人來說,這是再自然不過的。
  
   在本系列的這第三篇也即最後一篇文章中,我們要把事情顛倒過來。從那

些從事應用級設計和體系結構的人的角度來說,本文是自上而下看待 Jxta 的。

我們從一個特定的示例問題開始,對這個問題進行分析並設計出一個解決方案,

從而展示 Jxta 是如何自然地解決該問題的。
  
   隨着本文的進行,我們討論 Jxta 如何通過並列(juxtaposition)改變聯

網的前景展望,我們還提供一個 Jxta 服務和客戶機的設計和代碼。
  
   解決一個分佈式數據收集問題
   設想一下我們需要創建一個大規模的氣象數據收集和分析系統。在這個系

統中,我們有數百個氣象數據收集點;每個收集點配備一個微型氣象站,這些氣

象站將當前溫度(和其它大氣狀態)提供給一組數據集中器。收集器遍佈世界各

地;這些收集器並不是都直接連接到因特網,任何時候都可能有新的數據收集器

連接上來或脫開連接。在這個項目中,參與進來的收集器的確切數量經常在變化

;數據分析和處理基於區域平均值。
  
   開始時只有 10 個集中器。每個集中器監視來自許多個收集器的數據,這

些數據被實時提供給關係數據庫。隨後,來自關係數據庫的數據被提供給運行氣

象分析和預測的仿真模型的超級計算機並由它處理。集中器的數量和位置會發生

變化,但它們的行爲則大多更穩定。一旦安裝後,集中器就會保持運轉,除非碰

到系統失效。
  
   我們必須解決的問題:我們的系統如何能夠持續運轉,並能考慮到在幾乎

不影響整體性能的條件下,允許動態添加或除去收集器和集中器。
  
   初始分析:特定網絡的複雜性
   系統中的某些收集器可直接訪問因特網;其它的通過無線電傳輸技術進行

連接,它們處在惡劣的外部環境中。事實上,在這些基於無線電的收集器中,許

多都被設計成了節能的,以延長電池壽命;收集器的有效範圍僅夠與下一個最近

的收集器或基站聯繫。這些收集器中許多都不支持 TCP/IP,而是使用基本的分

組無線技術。一些更獨立的收集器僅僅靠其太陽能電池板獲得能量,並使用衛星

傳輸進行通信。還有另外一些收集器則連接到標準蜂窩電話上,用 SMS(short

message service,短消息服務)消息傳遞來發送消息。
  
   在項目的整個生命週期中,可用的收集器的數量會發生變化;在項目開始

時,我們無法預測將會構建到未來收集器中的連接類型,也無法預測收集器將使

用的技術。例如,在項目的某個階段,在一個超級計算機羣集內使用軟件仿真來

仿真數量巨大的收集器。我們的解決方案必須能適應所有收集器,不管是真正的

還是仿真的,現在的還是將來的。
  
   解決方案:並列(Juxtaposition)
   圖 1 顯示用來解決這個問題的高層次設計。
  
   圖 1. 解決數據收集問題
  

  

   請注意,並列 P2P 網絡用來適應網絡的多種不同情況,而集中器提供 P2P

網絡和傳統的客戶機/服務器網絡之間的連接,數據庫服務器和超級計算機駐留

在客戶機/服務器網絡。集中器充當兩個網絡之間的網橋 — 每個集中器在 P2P

網絡上具有動態特性,在客戶機/服務器網絡具有靜態特性。
  
   這個體系結構反映了 Jxta 對傳統系統的補充作用和提供並行於這些傳統

系統的增值的能力 — 通過並列(juxtaposition),Jxta 的名稱就源於這個詞

語。
  
   我們不想深入討論這裏的客戶機/服務器網絡的細節,因爲其中並沒有什

麼獨特之處;我們甚至可以使用 VPN 技術在因特網上運行它。有趣的部分在

P2P 網絡。圖 2 顯示了它的組成,它可隨將來的變化而變化。請注意其中用到

的多種不同技術。
  
   圖 2. 數據收集器網絡的組成
  
  

   在實現這個 P2P 網絡時,我們可以利用 Jxta,從而獲得以下優點:
  
   容易地添加或除去新的收集器或集中器,這得益於 Jxta 的統一分散尋址
  
   設計簡單性,這得益於 Jxta 的網絡虛擬化
  
   持續運轉,這得益於 Jxta 支持故障彈性
  
   免維護運轉,這得益於 Jxta 支持動態自我組織網絡
  
   支持跨越許多硬件平臺和編程語言的多種不同實現,支持所用的各種不同

通信協議讓我們來更詳細地研究一下其中幾個益處,並看看 Jxta 如何爲體系結

構的各個方面作出獨特的貢獻。
  
   統一分散尋址
   統一分散尋址的字面意思是,對等機可以爲自己生成一個 ID 並立即加入

到網絡,而不必與任何註冊人或中央認證機構聯繫,而當今的 DNS 則必須這樣

。這一特徵使我們任何時候都可以向網絡添加收集器和集中器。
  
   在本文附帶的代碼包中(您可以從參考資料下載它),我們提供了名爲

mdidgen 的實用程序,它可以用來爲新的 Jxta 服務和管道生成地址。(要更多

瞭解 mdidgen,請參閱旁註 mdidgen 實用程序。)您可以閱讀本系列的第一篇

文章,瞭解 Jxta ID 是如何用來對 Jxta 對象(例如:對等機、對等組、服務

和管道)進行統一尋址的。
  
   請注意,Jxta 網絡中的對等機不一定要有一個獨立的物理存在。在我們的

示例中,我們用一個超級計算機羣集來仿真數量巨大的收集器,每個收集器有它

自己的統一地址。這些仿真收集器的每一個在 P2P 網絡的其它部分看來都是一

個與那些具有物理存在的對等機沒有什麼差別的對等機。
  
   網絡虛擬化
   通過分散尋址爲所有收集器和集中器賦予網絡中唯一的標識後,它們立即

就成爲網絡中的對等機並開始彼此通信。儘管它們可能通過許多種不同的消息傳

遞機制進行相互聯繫,但在 Jxta 級別上,它們都只是一個虛擬網狀網絡中的節

點,如圖 3 所示。
  
   圖 3. 網絡虛擬化
  
  

   請注意,將收集器和對等機實際相互連接起來的所有不同的傳輸和尋址模

式都被虛擬化了,只留下一個網狀網絡,其中的每個對等機都與其它每一個對等

機相連接。Jxta 通過使用統一尋址模式和極遲綁定(very late binding),在

多個端點協議上添加一個智能消息路由層做到這一點。從本質上說,每一個端點

協議或傳輸協議棧都成爲虛擬 Jxta 網絡的一個驅動程序,將虛擬網絡映射到物

理網絡上。圖 4 顯示了這種設置。
  
   圖 4. 端點協議作爲驅動程序
  
  

   通信協議要成爲合格的端點協議,只需要它能夠在兩個物理節點之間發送

或接收 XML 消息。對傳輸可靠性或消息廣播支持沒有什麼要求。因而,最簡單

的分組無線協議也可以用作端點協議驅動程序,與像 TCP/IP 這樣的複雜多層協

議並列。這也解釋了爲什麼 HTTP 和 TCP/IP 在 Jxta 協議棧內都是同一級別的

端點協議,儘管它們的物理級別非常不同。HTTP 是一個受支持的端點協議,因

爲只要有必要,它就能夠穿越儘可能多的防火牆,從而獲取從一個 Jxta 對等機

傳送到另一個的消息。
  
   Jxta 網絡中的每個對等機可以同時支持多個端點協議,Jxta 虛擬網絡機

制會以一種儘可能遲的方式將虛擬化的統一網絡地址映射到物理網絡地址(在

Jxta 中稱爲網絡端點)。從本質上說,一個對等機對應於一組物理端點,其中

的每個物理端點可以在完全不同的物理通信協議上實現。較高級別的虛擬化和路

由服務隱藏了這一點。許多人或許能看出這就是多協議路由器的一個非常高級的

形式 — 正是這相同的設備使當今的因特網成爲現實。這一概念的發展將把我們

帶向一個更加普遍的因特網,這是再自然不過的了。
  
   讓我們更詳細地研究一下圖 5 所示的示例。對等機 A 是網絡中的一個收

集器,它試圖通過一系列中介收集器(對等機 B、C 和 D)將其數據發送到集中

器(對等機 E)。在圖中每個對等機的下面是該對等機所支持的一組協議。
  
   圖 5. Jxta 路由示例
  
 

   因爲對等機 A 不直接連接到對等機 E,所以它的消息必須通過中介對等機

B、C 和 D 進行路由。Jxta 將自動對消息進行路由:
  
   使用 TCP/IP 從對等機 A 到對等機 B
  
   使用分組無線協議從對等機 B 到對等機 C
  
   使用 SMS 從對等機 C 到對等機 D
  
   使用 HTTP 從對等機 D 到對等機 E
   對等機 E 將在它創建的管道上接收來自對等機 A 的消息,完全未覺察

Jxta 爲它所執行的複雜工作。請注意,對等機 C 到對等機 D 的路徑是非對稱

的;Jxta 就是專門設計來處理這種狀況的。如果有條消息要從對等機 E 發送回

對等機 A,則 Jxta 將使用撥號調制解調器 PPP 自動地從對等機 D 路由到對等

機 C。
  
   故障彈性
   儘管上面所描述的路由功能已經令人非常驚奇,但更爲重要的是,Jxta 必

須能夠適合 P2P 網絡不斷變化的拓撲結構。特別是它必須能夠處理充當消息路

由代理的 P2P 對等機與生俱來的不可靠性。在我們的例子中,如果中繼收集器

不可用,那麼,依賴另一個收集器來路由它的消息的收集器將不能進行通信。
  
   當有對等機加入或離開網絡時,Jxta 要能夠實時對消息進行重路由。再考

慮一下圖 5 中的路由示例。請設想一下,由於某些原因,就在對等機 A 已經發

送出消息(現在正在傳輸)而尚未到達對等機 C 時,對等機 C 和對等機 D 之

間的衛星鏈路卻斷了。Jxta 必須能夠動態地通過某些替代路徑(可能是通過另

一組中間節點)將該消息重路由到對等機 E。這種動態重路由是基於最大努力(

best-effort)完成的;偶而有這樣的情況,如果沒有可能的路由(除非中介傳

輸支持持久隊列),則消息可能會被丟失。由於這種重路由能夠改換實際用來到

達對等機 E 的端點協議(例如:從 HTTP 到 TCP/IP),所以,要一直達到路由

的最後一個跳數時,對等機到物理端點的綁定纔會發生。這就是 Jxta 的極遲綁

定的本質。
  
   在對等組級別上(請參閱本系列的第一篇文章瞭解有關對等組的更多知識

),Jxta 通過支持對等組服務 — 在對等組內總是可用的、冗餘地實現的服務

— 支持故障彈性。
  
   動態自我組織網絡
   當具有統一虛擬網絡 ID 的對等機插入到 Jxta 網絡中時,它必須這樣來

自我引導:
  
   定位本地對等機並發現它們的功能
  
   發現可用的對等組並加入其中一個
  
   發現對等組中可用的服務並開始使用它們
   我們從本系列的第二篇文章中瞭解到,這一切都是在消息級別上通過發佈

、中繼、中介高速緩存和搜索稱爲廣告的不同類型的消息完成的。Jxta 的 Java

參考實現有一個解析器和使發佈-高速緩存-搜索(publish-cache-search)過程

簡便的集中服務層。
  
   Jxta 中的對等組的作用是作爲網絡分區(network-partitioning)機制,

確保廣告只被中繼到能夠使用這些廣告的組成員。不同的對等組可以包含對等機

和對等組服務的不同組合,充當功能性的捆束機制。對等組也可以起到特定應用

程序的認證域的作用。
  
   mdidgen 實用程序
  
   實用類 com.ibm.jxta.mdidgen 可以用來以分散方式爲 Jxta 對象生成統

一地址。它生成一個新的 ModuleClassID、一個相應的 ModuleSpecID 和一個與

某個組(在啓動時被讀取的配置文件中指定)關聯的新 PipeID。所生成的這些

ID 是立即可以使用的 Java 聲明形式,並且立即可以插入到您的代碼中。這就

是我們爲 ModuleSpecAdvertisement 和集中器服務管道生成 ID 的方式。
  
   設計 Jxta 服務和 Jxta 客戶機
   讓我們回到氣象站示例上來。從概念上說,集中器實現必須:
  
   讀取並處理適當的配置文件,這個文件告訴集中器加入到哪個 Jxta 組。

(樣本代碼包中包含有我們示例的配置文件。)
  
   啓動 Jxta。
  
   加入到配置文件所指定的組。
  
   進行搜索,以判斷集中器服務的服務廣告是否存在;如果不存在,就創建

一個併發布它。
  
   創建一條相應於該服務的輸入管道。
  
   在管道等待來自收集器的消息。
  
   一旦消息到達,就處理它並存儲到 RDBMS 中。
  
   回到第 6 步。
   這個邏輯在 com.ibm.jxta.Concentrator 類中實現。您可以從參考資料部

分下載這個類及所有來自本文的代碼。
  
   收集器實現必須:
  
   讀取並處理上述配置文件。
  
   啓動 Jxta。
  
   加入到配置文件所指定的組。
  
   發現集中器服務的服務廣告;如果服務廣告不可用,我們就無法繼續。
  
   從服務廣告抽取管道信息。
  
   每隔一段時間收集數據。
  
   創建包含收集器位置和數據的消息。
  
   通過管道將消息發送到集中器服務。
  
   回到第 6 步。
   上述邏輯在 com.ibm.jxta.Collector 類中實現。
  
   將公共任務分解到 DwJxtaPeer 超類
   有很多任務對收集器和集中器角色都是公共的。爲了消除不必要的代碼重

復並使將來的維護更簡單,讓我們把這些公共任務分解出來放入名爲

com.ibm.jxta.DWJxtaPeer 的超類。
  
   其中一個公共任務是執行 ModuleSpecAdvertisement 的發現(請參閱旁註

JXTA 中的服務廣告瞭解關於這個廣告的更多知識)。這由清單 1 中的

findModuleSpecAdv() 方法執行:
  
   清單 1. findModuleSpecAdv()
   protected ModuleSpecAdvertisement findModuleSpecAdv() {
    return (ModuleSpecAdvertisement) findAdv

("ModuleSpecAdvertisement",
      "Name",ModuleSpecName, new ModuleSpecAdvValidator(), false

);
   }
  
   請注意,findModuleSpecAdv() 調用另一個名爲 findAdv() 的通用方法,

我們用這個方法發現廣告。findAdv() 的參數是:
  
   參數 描述
   AdvType 廣告類型的字符串描述 — 例如,PipeAdvertisement。
   Attr 搜索廣告時要匹配的標記 — 例如,Name。
   value 與所指定的屬性匹配的值。
   Validator 一個實現 FindValidate 接口的對象。這個接口有一個方法

checkAdv(),當找到一條廣告時,這個方法就被用來立即對這條廣告進行驗證。
   LocalOnly 一個布爾標誌,表明該發現是否只應在本地執行,還是跨網絡

在遠程執行。
  
   如清單 2 所示,該方法的第一部分通過使用組的發現服務的

getLocalAdvertisement() 方法,僅根據本地廣告高速緩存執行對廣告的發現。

請注意對 validator.checkAdv() 調用,用來對所找到的任何廣告進行驗證。
  
   清單 2. findAdv(),第 1 部分
    protected Advertisement findAdv(String advType, String attr,

String val,
      FindValidate validator, boolean localOnly) {
       Enumeration enum = null;
       System.out.println("Looking for " + advType + ", please

wait...");
       // First look in the local storage
       try {
         enum = discovery.getLocalAdvertisements

(DiscoveryService.ADV,
        attr, val);
  
        } catch (Exception e) {
        }
  
       if ((enum != null) && (enum.hasMoreElements())) {
           Advertisement adv = null;
           while (enum.hasMoreElements()) {
             try {
               adv = (Advertisement) enum.nextElement();
               if( validator.checkAdv(adv))
                   return adv;
               } catch(Exception e) {
               continue;
                }
              } // while
          } // if
  
   如果該發現是本地的,則邏輯就在這裏停止。否則,我們就發送一條查詢

到網絡,執行遠程發現。發現服務將把所找到的任何廣告都存儲到本地高速緩存

。我們只要給點時間就可以讓遠程發現發生。在清單 3 中,循環大約持續了五

秒鐘:
  
   清單 3. findAdv(),第 2 部分
       if (localOnly)
        return null;
  
       System.out.println("  cannot find it locally, trying

remote");
       // Now, search remote
       discovery.getRemoteAdvertisements(null,

DiscoveryService.ADV,
           attr, val, 2, null);
  
       // Wait a bit in order to get an answer.
       int i=0;
       while (true) {
       try {
          if (i>MAXRETRIES){
           System.out.print(".");
           break;
         }
         Thread.sleep(WaitingTime);
         i++;
       } catch (Exception e) {
       }
       System.out.println("");
  
   此時,已發現的任何廣告都應可在本地高速緩存中找到。在清單 4 中,我

們再次執行一個本地檢查。
  
   清單 4. findadv(),第 3 部分
      // Look in the local storage again
       try {
         enum = discovery.getLocalAdvertisements

(DiscoveryService.ADV,
             attr, val);
  
         if ((enum != null) && (enum.hasMoreElements())) {
           Advertisement adv = null;
  
           while (enum.hasMoreElements()) {
             try {
               adv = (Advertisement) enum.nextElement();
                if( validator.checkAdv(adv))
                   return adv;
               } catch(Exception e) {
               continue;
             }
           } // while
         }
       } catch (Exception e) {
       }
      }
       return null;
     }
  
   超類中的另兩個公共方法的描述在下表中;您可以作爲練習完成對它們的

分析。
  
   方法 描述
   PublishModuleSpecAdv() 如果發現過程沒有爲服務找到現有的

ModuleSpecAdvertsiement,則這個方法被集中器調用。這個方法將創建一個服

務(根據我們所生成的、固定的服務 ID)。這條廣告將在本地和遠程發佈。僅

在集中器第一次啓動時,當配置改變時,或者在本地高速緩存被清除後,纔有創

建廣告的必要。
   JoinGroupIfExists() 這個方法爲收集器和集中器所調用;它嘗試加入到

一個已命名的子組(subgroup),這個子組是全局 NetPeerGroup(缺省情況下

大家都在這個組)的子(child)組。
  
   請看一下清單 5,它是 DwJxtaPeer 類的常數聲明部分的一部分:
  
   清單 5. 模塊 ID 定義
   public static final String ClassID =
   "urn:jxta:uuid-EE99266A1DE84E3DB34D9CC842EC889105";
   public static final String SpecID =
   "urn:jxta:uuid-

EE99266A1DE84E3DB34D9CC842EC8891B9EB13ECA6FE44DDA112B5F5E357763006";
  
   Jxta 中的服務廣告
   服務廣告概念分解成一組相互聯繫的廣告(共三條):
   ModuleClassAdvertiseent
   ModuleSpecAdvertisement
   MdouleImplAdvertisement
  
   爲了減小在系統中循環的廣告的大小,也爲了將服務的通用類(例如:銀

行)、該類的特定規範(例如:存款和提款 API)和該服務(例如:API 基於

Java 的實現)的實現之間的關係規格化,這樣做都是必要的。
  
   應用程序或 Jxta 服務不必使用所有這些廣告,只要使用它所需要的就行

了。在我們的系統中,我們只需要ModuleSpecAdvertisement,我們用它將服務

連到管道上,並使這條廣告是遠程可發現的。
  
   ModuleClassID 和 ModuleSpecID 用 mdidgen 實用程序生成並以硬編碼方

式置於模塊中;它們與一個集中器服務的 ID 相對應。所有的集中器都知道這個

服務的 ID,而且這個 ID 一旦生成就一直保持不變,所以組中的收集器肯定能

夠找到這個集中器服務。因爲生成 ModuleSpecID 時需要 ModuleClassID,所以

這裏有 ModuleClassID。爲了輕鬆生成這些 ID,我們使用一個名爲 AdvCooker

的庫,它是 W.R. Bauer([email protected])創建的名爲 jxta-wire 的 Jxta 項

目的一部分。
  
   網絡中運行的所有集中器實例將對同一個集中器對等組服務(通過使用相

同的 ModuleSpecID 和偵聽廣播管道的同一個邏輯實例)作出應答。這種冗餘實

現將確保集中器服務在對等組中始終可用。
  
   集中器:一個 Jxta 對等組服務
   我們來看一下 com.ibm.jxta.Concentrator 實現。我們已經提到過,它繼

承(擴展)自 DwJxtaPeer 類。這裏是逐個方法地對 Concentrator 進行的描述


  
   方法 描述
   init() 它應該是該類被調用的第一個方法。這個方法調用私有 jxtaInit

() 方法,然後創建輸入集中器服務管道的一個實例。
   process() 這個方法進入一個無限循環。它在輸入集中器服務管道上偵聽

傳入的收集器數據提交。對每一個提交,它都調用 processData() 對數據進行

處理。
   findPipeAdv() 這個方法對服務管道廣告執行本地發現(也就是說,它檢

查本地高速緩存)。
   jxtaInit() 這個方法首先讀取配置文件並設定我們想要加入到的組。接着

,它啓動 Jxta 和 NetPeerGroup 網絡,然後調用超類的 joinGroupIfExist()

加入到指定的組。接着,如果能夠,它就從本地高速緩存檢索服務管道廣告;否

則,它將創建一個新的服務管道廣告(通過使用

createInputPipeAdvIfNotExist())。最後,它執行發現,看看是否可以找到

ModuleSpecAdvertisement;如果不能找到,它就創建一個併發布它。
   processData() 這個方法是佔位符。在實際的項目中,它將使用後端客戶

機/服務器網絡將所收集到的數據提交給 RDBMS(可能使用 JDBC)。
   createInputPipeAdvIfNotExist() 這個助手方法首先檢查高速緩存,看看

服務管道廣告是否可用。如果不可用,它將創建該廣告並將它存儲到高速緩存中

。在任一種情況下都返回正確的廣告。
  
   靜態類型定義如下:
  
   public static String servicePipeID =
   "urn:jxta:uuid-

969610EE8945417CA56F9771197EE3965207E4C303154E7EB5878751AE22761804";
  
   這是由 mdidgen 實用程序生成的管道 ID。它是該服務管道的統一地址,

被所有集中器使用。它是一條廣播管道,因而偵聽消息的所有集中器都應接收到

那些來自收集器的消息。收集器從作爲 ModuleSpecAdvertisement 的一部分的

管道廣告中獲得這個管道 ID;收集器通過發現過程找到該廣告。
  
   收集器:編寫 Jxta 客戶機邏輯的代碼
   最後,我們來看一下 com.ibm.jxta.Collector 類的本地方法。
  
   方法 描述
   init() 它應該是從這個類中調用的第一個方法。這個方法調用私有

jxtaInit(),然後創建用來將所收集到的數據發送到集中器服務的輸出管道。
   process() 這個方法有一個無限循環,這個循環首先調用 collectData()

獲得測量的數據,接着,創建一條 Jxta 消息並沿集中器服務管道將它發送到正

在等待的集中器。循環內每次採樣都延遲一段固定時間。
   jxtaInit() 這個方法首先讀取配置文件並對我們想要加入到的組進行設置

,接着確定收集器的位置。接着,它啓動 Jxta 和 NetPeerGroup 網絡,然後調

用超類的 joinGroupIfExist() 加入到指定的組。接着,它執行發現,看看是否

可以找到相應於衆所周知的集中器服務的 ModuleSpecAdvertisement;如果找不

到,則退出。一旦找到了 ModuleSpecAdvertisment,它就將抽取集中器服務管

道廣告併爲輸出管道的創建做好準備。
   collectData() 這個方法是一個佔位符,用於實際的數據收集。在實際的

項目中,這個方法將訪問各種數據輸入通道(可能使用輸入/輸出端口或本機代

碼)並將所收集到的數據返回給調用者。
  
   實際運轉 Jxta:在您自己的機器上測試這個動態網絡
   本文附帶的源代碼包中有一個便於您實驗的目錄結構。下面的目錄在 code

子目錄下:
  
   目錄 描述
   lib 來自 Jxta 核心最新穩定版的所有 jar 文件,用於 Jxta shell 的所

有 jar 文件以及來自 jxta-wire 項目的 jxta-wire.jar 文件都放在這裏。(

請參閱參考資料瞭解關於 Jxta shell 和 jxta-wire 的更多信息。)
   src 包含我們系統的源代碼。
   classes 包含我們系統的編譯好的類文件。
   shell1 第一個實驗目錄。我們將在這個目錄創建一個帶有一個集中器的

shell。我們還將在這裏充分考查 mdidgen 實用程序。
   shell2 設置爲網絡中的第二個對等機。這將運行另一個集中器。
   shell3 設置爲網絡中的第三個對等機。這將運行一個收集器。
  
   要編譯這些代碼,您需要安裝 JDK 1.3 或更新版本。在 code 目錄時,執

行 MAKEIT.BAT 批處理文件。這將編譯代碼並在 classes 目錄中創建類文件。
  
   接着,運行 MAKEJAR.BAT 批處理文件。這將創建一個包含所有代碼的

dwjxta.jar 文件;將它放到 lib 目錄,爲實驗做好準備。
  
   現在,請啓動三個不同的命令窗口。將它們的目錄分別改到 shell1、

shell2 和 shell3。
  
   在 shell1 目錄中編輯 runshell.bat 文件,將您在配置期間用來設置安

全性的用戶標識和密碼反映出來(密碼必須至少八個字符長)。編輯

runconc.bat 和 mdidgen.bat 文件,同樣要有這個用戶標識和密碼。
  
   使用 runshell.bat 運行這個 shell,並按以下所示配置這個對等機:
  
   對等機名: node1
   傳輸: TCP/IP 啓用,HTTP 禁用,選中作爲集中點,無中繼
   所用 TCP 端口: 9701
   安全性用戶名和密碼: 如在批處理文件中所定製
  
   因爲我們的系統假設已經創建了一個用於操作的組,所以我們需要在該

shell 中創建這個組。在這個 shell 中時,使用以下命令創建 dwtest 組:
  
   Jxta> myadv = mkadv -g dwtest
   Jxta> mygrp = mkpgrp -d myadv dwtest
  
   這將創建我們將使用的 dwtest 組。您可以這樣來確認它已經被創建:
  
   Jxta>groups
   group0: name = dwtest
  
   現在您可以退出該 shell。
  
   現在,請使用 mdidgen.bat 文件試驗統一地址(ID)的分散生成。當您運

行這個文件時,應得到類似這樣的輸出:
  
   清單 6. mdidgen.bat 的輸出
   remote group discovery message sent
   group joined successfully
   public static final String ClassID =
   "urn:jxta:uuid-DCDD418FCC194040AA13A52A334B967105";
   public static final String SpecID =
   "urn:jxta:uuid-

DCDD418FCC194040AA13A52A334B96716C515B975C2941AD9FBC90178B6918A806";
   public static final String PipeID =
   "urn:jxta:uuid-

2184CACA259B42E0A866AEA788A923054C519D304E07415195B0917C81238FD004";
  
   請注意所生成的 ModuleClassID、ModuleSpecID 和 PipeID。這就是我們

獲得在集中器服務用到的 ID 的辦法。
  
   通過執行 runconc.bat 文件啓動集中器。這將讀取 dwConfig 文件,這個

文件告訴集中器加入到 dwtest 組。您的輸出應與此有些相似:
  
   清單 7. 1 號集中器(runconc.bat)的輸出
   Starting Jxta...
   Joining default NetPeerGroup...
   Attempting to join group: dwtest
   remote group discovery message sent
   group joined successfully
   group dwtest joined successfully
   Look for previously created Pipe Adv, create one if not exist
   Looking for PipeAdvertisement, please wait...
   Previously published pipe advertisement not found, creating a new

one.
   Locally caching the new pipe advertisement...
   Checking to see if MSA previously published...
   Looking for ModuleSpecAdvertisement, please wait...
    cannot find it locally, trying remote
   ... MSA not found, need to create it
   Creating new MSA
   Locally and remotely publish the MSA
   Creating pipe for data collection...
   pipe created successfully
   Waiting for data from collector...
  
   到這裏,集中器實例就建立好了,並且爲接收來自收集器的數據做好了準

備。
  
   現在,到 shell2 命令窗口中編輯 runconc.bat 文件,將您的安全性用戶

標識和密碼反映出來。接着,使用 runconc.bat 文件運行集中器實例。在配置

過程中設置以下參數:
  
   對等機名: node2
   傳輸: TCP/IP 啓用,HTTP 禁用,無集中點,無中繼 所用 TCP 端口:

9702安全性用戶名和密碼: 如在批處理文件中所定製如果一切都正確運行,則

您應看到與此相似的輸出:
   清單 8. 2 號集中器(來自 Shell2 的 runconc.bat 輸出)
   Starting Jxta...
   Joining default NetPeerGroup...
   Attempting to join group: dwtest
   remote group discovery message sent
   group joined successfully
   group dwtest joined successfully
   Look for previously created Pipe Adv, create one if not exist
   Looking for PipeAdvertisement, please wait...
   Checking to see if MSA previously published...
   Looking for ModuleSpecAdvertisement, please wait...
   .. found previously published MSA
   Creating pipe for data collection...
   pipe created successfully
   Waiting for data from collector...
  
   請注意,集中器的 ModuleSpecAdvertisement 被找到了,所以這個集中器

實例不必另外創建一個 ModuleSpecAdvertisement。現在它也在等待來自收集器

的輸入。
  
   最後,到 shell3 命令窗口中編輯 runcoll.bat 文件,將您的安全性用戶

標識和密碼反映出來。接着,使用 runcoll.bat 文件運行收集器實例。這個實

例將使用 shell3 目錄中的 dwColConfig 文件,該文件告訴收集器應加入到

dwtest 組,這個組的位置是“Timbuktu North”。在配置過程中設置以下參數


  
   對等機名: node3
   傳輸: TCP/IP 啓用,HTTP 禁用,無集中點,無中繼
   所用 TCP 端口: 9703
   安全性用戶名和密碼: 如在批處理文件中所定製
  
   這個收集器實例將開始查找 ModuleSpecAdvertisement 並且應該能找到。

然後,它將創建一條管道與已經運行的集中器通信。您應看到與此相似的輸出:
  
   清單 9. 收集器(來自 Shell3 的 runcoll.bat 的輸出)
   Reading config file, dwColConfig, and processing...
    group to join will be dwtest
    collector location is Timbuktu North
   Starting Jxta...
   Joining default NetPeerGroup...
   Attempting to join group: dwtest
   remote group discovery message sent
   group joined successfully
   group dwtest joined successfully
   Searching for collector's MSA...
   Looking for ModuleSpecAdvertisement, please wait...
    cannot find it locally, trying remote
   .. found collector's MSA
   Extracting pipe adv from MSA...
   Connecting to concentrator network...
   pipe created successfully
   ... collecting data....
   ... data collected, sending to concentrator
   waiting until next sample...
   ... collecting data....
   ... data collected, sending to concentrator
   waiting until next sample...
  
   請注意,數據被收集起來並定期發送到集中器服務。當數據穿過 P2P 網絡

以及兩個集中器接收這些數據並進行處理時,請注意觀察。
  
   高難度的應用模式
   我們的氣象收集示例說明了這樣一個應用模式:在一般的方面,它使用普

遍流行的應用 P2P 系統;從特定的方面,它使用 Jxta。這個模式包含兩個耦合

極其鬆散的羣體:消費者和生產者。當消費者想要生產者所生產的產品時,消費

者不願作出堅定的許諾,也不願受限於特定生產者。在這種想法背後可能有幾個

現實動機。消費者可能想:
  
   可以在任意時間進行選擇,以選擇最佳的可用生產者降低對某個生產者的

成功或失敗的依賴風險
  
   從非常龐大的動態社區中選擇,這種社區的大小和拓撲結構在物理上是難

於管理的當消費者羣體和生產者羣體出現交迭時,這種模式變得十分有趣,當前

可用的、流行的、世界範圍內的文件共享系統就例證了這一點。與傳統的聯網技

術不同,P2P 系統從一開始就是設計來適應這種應用模式的。特別地,與使用傳

統的客戶機/服務器技術進行設計時,必須提供的複雜的解決方案不同,Jxta

使得創建這些系統既容易又輕鬆。
  
   超越 TCP/IP 的聯網
   爲了真正突出 Jxta 帶來的價值,我選擇了全球氣象信息收集系統作爲一

個示例。然而,這個問題及解決方案具有許多業務模式(business scenario)

的典型特徵,這些業務情形如移動銷售隊伍自動化、商品貿易、內容分發和企業

到企業電子商務等等,可以列出很多。您可以同時使用 P2P 網絡和傳統的客戶

機/服務器網絡,從而構建大大超出當今靜態邊界的新型網絡解決方案。開放源

代碼的 Jxta 平臺將是這些新型解決方案的實現工具。我希望本系列已經激起您

探索 Jxta 提供的可能性的願望。
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章