JXTA 2: 具備高性能、海量伸縮性的 P2P 網絡

新的 JXTA 版本在實用性方面作了改變,更適合於現實世界網絡拓撲 html



Sing Li ( westmakaha@yahoo.com), 做家, Wrox Press

簡介: JXTA 2 是開放源代碼 P2P 網絡的第二個主要版本,它利用流行的、基於 Java 的參考實現做爲構建基礎。在設計方面進行了重要的修改,以得到更高的性能、海量伸縮性和可維護的 P2P 網絡。本文創建在 Sing Li 於兩年前發表的 JXTA 系列文章 Makng P2P interoperable的基礎上,爲您介紹了這個平臺上最新的重要改變。 java


自 JXTA 1.0 推出之後,開放源代碼點對點(P2P)和分佈式計算團體對它給予了熱情歡迎( developerWorks 上有關 JXTA 的早期討論,請參閱 參考資料)。在日益增加的獨立開放源代碼項目下聚集了衆多的 JXTA 團體,這些項目的目的就是爲了驗證由 JXTA 平臺開發小組所作出的聲明:即 JXTA 能夠並應該成爲將來互操做的 P2P 網絡應用程序的首選構建標準。 算法

從積累的經驗中學習 shell

在最近的兩年中,JXTA 平臺設計小組一直在幫助 JXTA 開發團體更好地理解基本設計概念,以及在使用 JXTA 平臺 API 提供的功能時的最佳實踐。應用程序開發團體的反饋和經驗爲小組提供了寶貴的意見和建議。這些反饋來源於現實生活中的部署工做,包括對平臺最初設計的侷限性、API 庫的笨拙或者矛盾之處的觀察,以及使 JXTA 更適合於構建現實世界 P2P 應用程序的特定要求。若是不先推出一個可工做的參考實現,那麼就不可能收集這些寶貴的積累經驗。所以第一個版本的 JXTA 很好地達到了它的目的。 數據庫

根據這些反饋意見,JXTA 平臺小組將主要精力放到了 JXTA 2 的設計和實現中的一組主要目標上。表 1 顯示了最主要的設計目標,以及 JXTA 2 實現如何知足這些設計目標的簡要說明(對於 JXTA 1 和 JXTA 2 之間的區別給予了強調)。 編程

表 1. JXTA2 的設計目標和實現 緩存

目標 JXTA 2 實現
在當今大多數典型的網絡配置上的海量伸縮性
  • JXTA 2 引入了彙集超級節點網絡(rendezvous super-peer network)的概念,經過減小傳播流量極大地改進了伸縮性(參見 Toward massive scalability) 
  • 在彙集超級節點網絡中實現共享資源分佈式索引(shared resource distributed index,SRDI),建立了鬆散一致性、故障恢復(fault resilient)、分佈式散列表(參見 Shared resource distributed index) 
  • 顯著改進了每個節點本地和整個網絡上的資源利用
  • 在實驗室中使用大型超級計算機模擬在很是大的 JXTA 2 網絡中的交互,並保證網絡的可伸縮性達到數十萬個節點
提升性能
  • 改進了本地節點級別和整個網絡上的資源分配和重用
  • 本地優化,包括對平臺內存佔用的嚴格控制,改進線程處理、消除協議堆棧中重複的多個緩存副本、提供對儲存在本地緩存中的公告(advertisement)的控制、不用執行發現就可得到與管道相關聯的管道公告,等等
  • 網絡資源改進,包括利用 TCP 鏈接的反向信道更好地使用現有的網絡鏈接、用於網絡地址轉換(NAT ―― 見側欄「 網絡地址轉換設備」)節點的新 TCP 中繼 、經過 SRDI 只傳播公告的索引而不是完整的公告、引入一種節省位的二進制在線(bit-saving binary on-the-wire)協議格式,等等 
  • 本地公告的儲存和索引如今是在一個定製的 Xindice btree 數據庫上執行,比之前的基於文件系統的存儲方案在性能上有了改進
  • HTTP 傳輸如今同時支持 1.0 和 1.1,能夠更有效地使用底層 TCP 鏈接
  • 公告中增長了路由線索(routing hint)支持,從而加速了路由解析
改進的開發人員友好性 對 API 作了大量從新設計和改進,使得 API 更容易理解並具備更多的一致性。主要的 API 改變包括:
  • 消息建立和處理
  • 消息元素操做
  • 提升了異步發現處理的靈活性
  • 編程式配置器(configurator)支持
  • 明確而清晰地分離開了中繼、彙集、路由器和傳輸功能
  • 統一了描述當前網絡中存在的防火牆、中繼和代理元素的術語
  • 組 ID 的 ID 工廠 ( 之前這是一項繁重的任務,須要手工建立 )
  • JxtaSocket提供了節點之間的基於流的 API,相似於 Java 平臺的套接字 API 
  • JxtaBiDiPipe提供了雙向的管道能力,用於在節點之間傳遞消息
改進可靠性 對節點的自適應行爲進行了更改,從而改進了整個網絡的可靠性(由於彙集和中繼對網絡可靠性來講是最關鍵的服務,因此大多數更改是圍繞它們進行的):
  • 在彙集鏈接上的容錯
  • 在中繼鏈接上的容錯
  • 彙集的動態發現和跟蹤
  • 中繼的動態發現和跟蹤
  • 若是在固定的時間內沒有找到彙集,則邊緣節點自動成爲彙集
提升可管理性 支持對節點的詳細遠程監視。在 JXTA 2 中內建了普遍的測試和計量能力。這是基準測試的關鍵,也是使網絡調整和性能 / 伸縮性改進成爲可能的關鍵。還提供了一個 GUI 監視實用程序。它標誌着使 JXTA 節點更具可管理性和更容易管理這一長期計劃的開始。
兼容移動 爲 Java 2 mobile edition (JXME)的 JXTA 實現提供了代理能力。

網絡地址轉換設備

一個 網絡地址轉換設備(NAT)使多臺計算機和終端能夠經過一個網絡地址鏈接到 Internet (經過轉換輸出包上的網絡地址並對輸入包上的地址從新進行轉換)。家庭用戶或者遠程工做的業務用戶普遍使用這些設備,它們常被稱爲 高速 Internet 路由器或者 Internet 共享設備服務器

在本文中,咱們將詳細考察在 JXTA 2 中使海量伸縮性成爲可能的關鍵改變。咱們還將完成一些使用新的平臺配置 API 的實際編碼,爲 JXTA shell 建立一個寂靜啓動裝置(能夠在本身的 JXTA 應用程序中重用的裝置)。最後,咱們將探討幾個新的 shell 命令,並看一下在 JXTA 2 網絡中是如何索引和定位資源的。 網絡

回頁首 數據結構

邁向海量伸縮性

現實世界的網絡拓撲隨着時間而不斷髮展。它的演變經常受到外部基礎設施和經濟因素的影響,這些一般是軟件系統設計者沒法直接控制的。JXTA 1 採起了單純的和至關理論化的方式使用底層物理網絡拓撲。相反,JXTA 2 採起了更多編程式的方式設計覆蓋網絡,它在今天最多見的網絡拓撲上能夠有更高的性能和伸縮性。

JXTA 2 推出了 彙集超級節點網絡的概念:動態而自適應地將 P2P 網絡成員劃分爲邊緣節點(edge peer)和彙集節點(rendezvous peer)。傳播只發生在更穩定的(且成員數更少的)彙集節點中。這種限制極大地加強了伸縮性,並下降了網絡範圍內消息風暴或者泛洪的可能性。

讓咱們更深刻地看一下這種新重疊網絡(overlay network)的實現。

邊緣節點與彙集超級節點的對比

在 JXTA 2 中,邊緣節點本質上是易變的,有可能頻繁地加入和退出。JXTA 2 網絡中大多數節點都會是邊緣節點。一個邊緣節點不轉發查詢請求,它可能維護、也可能不維護本身的本地公告緩存。大多數邊緣節點將維護一個本地緩存,並須要使用 JXMEJxtaProxy的服務(有關 JXME 的更多內容請參閱 參考資料)。

雖然一些邊緣節點與彙集網絡直接鏈接,可是許多邊緣節點是經過做爲中繼的中間節點或者 JxtaProxy鏈接到彙集網絡的。 要參與 P2P 網絡,一個邊緣節點只需知道如何到達單個彙集節點。一般,一個邊緣節點維護一個已知彙集節點的列表(稱爲 種子彙集節點),並參與新彙集節點的動態發現,這使得該節點能夠故障切換到備用匯集節點,並加強整個網絡的可靠性。

彙集節點通常變化較少而且更穩定(即當它們鏈接到網絡上後,它們就停留在那裏並保持鏈接)。能夠想到,任什麼時候候在 JXTA 網絡中邊緣節點的數量要比彙集節點多得多。彙集節點在本質上是直接鏈接節點,這意味着它們不該該須要中繼或者 JxtaProxy,以鏈接到網絡中另外一個彙集節點。每個彙集節點都是彙集超級節點網絡中的成員(在特定的 JXTA 組環境中)。彙集節點把沒法根據本身的索引緩存進行解析的查詢轉發給其餘彙集節點,它們參與維護網絡中全部可訪問資源的一個鬆散一致的 分佈式散列表(DHT)。每個彙集節點維護一個網絡中全部已知彙集節點的動態視圖,並能夠在網絡拓撲改變時鏈接或者故障切換到另外一個彙集節點。

每一個 JXTA 節點均可以假定爲邊緣節點或者彙集節點。事實上,一個邊緣節點若是不能在一個延長的時間(extended period of time)內鏈接到任何彙集節點,那麼它能夠自適應地變爲一個彙集節點。網絡中全部彙集節點也能夠發出查詢,意味着邊緣節點功能其實是彙集節點功能的一個徹底子集。通常來講,在 JXTA 2 網絡中應用的是自適應式和編程式的對稱方法,它受底層物理網絡拓撲以及定製的用戶配置影響。

共享資源分佈式索引

JXTA 2 網絡的操做依賴於其解析分佈式查詢的能力(有關這一律唸的更多內容,請參閱側欄「 P2P 網絡的實質」)。在 JXTA 2 中,彙集超級節點網絡造成了鬆散一致的 DHT,從而解析分佈式查詢。

JXTA 2 使用了一種稱爲 共享資源分佈式索引(shared resource distributed index SRDI) 的分佈式算法,以建立並維護網絡中資源的一個整體索引。在 JXTA 中,資源是用公告形式的元數據(實質上就是 XML 文檔)來描述的。經過一組特定的屬性,用 SRDI 在網絡範圍索引這些公告。維護的分佈式索引相似於一個散列表,其索引的屬性做爲散列鍵,而散列值映射回包含實際公告的源節點。於是能夠在彙集網絡上任何地方根據這些屬性進行查詢。這樣,經過定位具備所需公告的節點,SRDI 就能夠答覆在網絡中的公告查詢。例如,一個節點可能向具備數千個節點的網絡發送叫作 「 LotteryService的管道」的查詢。SRDI 能夠快速地對這種查詢進行解析,並使保存有「 LotteryService管道」公告的節點給出回覆。

在 SRDI 中,再也不須要遠程發佈任何公告。發佈的只是儲存在節點上的公告的索引。這個索引信息經過單個鏈接的彙集節點「推出」到 DHT(彙集超級網絡)。

鬆散一致的 DHT

JXTA 2 網絡的做用是一個持續可用的、網絡範圍內的、動態的、分佈式的數據結構:這是一個虛擬的散列表,包含了整個 JXTA 組中全部已發佈公告的索引。一個邊緣節點能夠在任什麼時候候經過提供一組屬性(表中的散列鍵)來查詢散列表。該查詢是由網絡(其實是彙集超級節點網絡)經過將該散列鍵混編爲所需的值(即包含所請求公告的節點)來進行解析的,如圖 1 所示:


圖 1. 彙集超級節點網絡做爲鬆散一致的 DHT 
圖 1. 彙集超級節點網絡做爲鬆散一致的 DHT  

在圖 1 中,邊緣節點 1 (EP1) 建立了一個管道,並在本地儲存其公告。經過 SRDI 更新這個索引,DHT 如今就知道了這個公告。以後,邊緣節點 2 (EP2) 對 EP1 的管道進行查詢。彙集超級節點網絡解析這個查詢,並通知 EP1 對該公告的請求。結果,EP1 會將所請求的公告做爲響應發送給 EP2。

要建立這個 DHT,每一個節點在本地緩存公告,全部本地存儲的公告都已索引。索引推送到彙集節點(在任什麼時候侯,JXTA 2 邊緣節點只鏈接到一個彙集節點)。彙集超級節點網絡維護包含混合索引的 DHT。查詢老是發送到彙集節點,如圖 2 所示:


圖 2. 在的彙集超級節點網絡(起 DHT 做用)中進行查詢解析 
 

圖 2 中顯示的步驟以下:

  1. EP1 建立一個管道,並在本地儲存其公告。
  2. 在本地更新索引,所作的更改推送到已鏈接的彙集節點(R1)。
  3. 經過 SRDI 索引的傳播,接收更新的彙集節點(R1)複製新的索引信息到超級節點網絡中選擇的彙集節點(R3 和 R5)。(有關此選擇和複製過程的更多信息,請參閱 Rendezvous peerview and RPV walker)。
  4. 而後,EP2 查詢 EP1 的管道。這個查詢發送到與它唯一鏈接的彙集節點 ―― R4。
  5. R4 混編查詢的屬性,並將請求重定向到超級節點網絡中的另外一個彙集節點 ―― R3。
  6. 收到經過 R1 傳來的 EP1 的索引更新後,R3 當即將 EP2 的請求通知給 EP1。
  7. EP1 直接向 EP2 發送包含所請求的管道公告。這時,查詢獲得瞭解析。
  8. 而後,EP2 可能會決定存儲管道公告,循環從新開始。

至止,咱們已經描述了由 JXTA 2 彙集網絡維護的 DHT,它好像老是以一種完美的一致性方式維護的。這在目前是不可能的,由於在 P2P 網絡中,經過相互協做來實現 DHT 的一組彙集節點可能會出現加入和退出現象(儘管不像邊緣節點那樣頻繁)。當彙集節點離開時,它所維護的一組索引就會在必定時間內沒法使用(直到可靠的節點再次發佈它)。基於一種自適應性的方式,JXTA 2 能夠維護一個鬆散一致的 DHT,它能夠處理 P2P 網絡中節點的易變特性。

JXTA 2 採起的方式保證了 DHT 在忽然分離的網絡(即因爲鏈接節點的消失而產生的節點孤島)以及新合併的網絡(即出現了將之前分離的節點孤島鏈接起來的鏈接節點)中也能夠繼續工做。JXTA 2 的方法包括了一個 彙集節點查看(rendezvous peerview,RPV) 和一個插入式彙集節點遍歷器(rendezvous walker)。

RPV 和 RPV 遍歷器

RPV 是由超級節點網絡中每個彙集節點維護的。RPV 是該節點的已知彙集節點列表,按各個彙集節點的唯一節點 ID 排序。在 DHT 算法中使用的散列函數在每個節點上都是相同的,它用於肯定一個(本地不能解析的)查詢請求應該轉發到哪個彙集節點。

全部變得不可達的彙集節點都會從節點的 RPV 中刪除。超級節點網絡中每個彙集節點都按期向其 RPV 中隨機選擇的彙集節點發送其已知彙集節點的隨機子集。這樣作是爲了保證 RPV 最終覆蓋整個網絡,並適應底層物理網絡所發生的任何分離或者合併。注意,在任何給定時間,由網絡中不一樣彙集節點所維護的 RPV 可能彼此不一樣。

爲了維護 DHT,基於一個固定的散列函數,SRDI 會將收到的索引信息存儲到所選擇的彙集節點上。爲了應付鬆散一致的特色,這個索引信息冗餘地複製到 RPV 中相鄰的其餘彙集節點上(回顧一下,RPV 是一個已知彙集節點的有序列表,按全局唯一節點 ID 排序)。這能夠保證即便目標彙集節點出現崩潰,仍然頗有可能在查詢時對這一索引信息進行成功地混編。

在解析查詢時,散列函數是針對彙集節點本身的 RPV 執行的。由於可能有多個現有的彙集節點斷開鏈接,或者多個新的彙集節點加入超級節點網絡,因此若是散列沒有當即解析這個查詢,就引入一個 RPV 遍歷器,並將查詢轉發給有限數量的其餘彙集節點。這種限定範圍遍歷器所使用的算法被設計爲「插入式的」,也能夠根據特定的網絡方案進行定製。圖 3 解釋了索引信息的冗餘儲存。


圖 3. SRDI ――索引信息的冗餘儲存 
 

在這個圖中,散列函數將收到的索引信息映射到 R5。從邊緣節點收到這個索引信息的彙集節點 R1 將索引信息發送給 R5,並複製給 R4 和 R6,以增長索引信息的可用性。假設 R3 收到了匹配這條存儲索引的查詢,那麼執行的散列會將查詢發送給 R3 的 RPV 中的 R5。不過,若是此時 R5 不存在,那麼 RPV 將會收縮,並將原來 R5 駐留的空間關閉。這意味着之前的 R6 將成爲新的 R5。

若是 R6 沒有所需的索引信息,那麼網絡的拓撲可能有了重大的改變。在這種狀況下,RPV 遍歷算法就要發揮做用了。遍歷器將在 RPV 列表中上下遍歷以查找該信息。

咱們將在下面實際配置和使用一個彙集超級節點網絡。在這以前,咱們須要看一看 JXTA 2 中的一些 API 和 shell 的改進。

回頁首

配置器 API 的主要改進

API 的一個主要改進之處是在對自動配置的支持方面。如今終於可使用平臺 API 經過編程建立 PlatformConfig 文件(節點公告),並啓動 JXTA 平臺。這意味着之前使人眼花繚亂的衆多用戶配置參數徹底能夠隱匿無論。

有多個 API 用於進行自動配置,能夠根據您的特定須要選用。大多數與配置相關的 API 在 net.jxta.util.config 包中。net.jxta.util.config.Configurator類是普通的包裝器類,用於簡化 JXTA 2 配置編程,在許多狀況下它已經足夠了。在內部,net.jxta.util.config.Configurator 類使用同一包中的更低級的類來完成其工做。

在即將發佈的 JXTA 2.2 中(在寫做本文時還沒有發佈),這些配置 API 將統一到一個外部的 net.jxta.ext.config包中。特定角色(如邊緣節點、彙集節點、中繼)的節點配置文件將進一步方便了經過編程來進行配置。

配置的核心目標是建立一個描述要啓動的節點的節點公告。這個節點公告在默認狀況下保存在與 PlatformConfig 文件相同的 .jxta 目錄中。

回頁首

爲寂靜啓動對 JXTA 配置進行編程

爲了進行咱們的試驗,咱們須要啓動總共六個 JXTA 節點,其中五個是彙集節點,一個是邊緣節點。爲了方便您複製這個網絡,咱們將在一臺計算機上運行全部這六個節點。在之前,這須要花費很大的力氣來描述全部須要在 JXTA GUI 中手工輸入的配置參數 ―― 這種描述輕易就能夠達到本文的整個長度。

爲了繞過這種複雜性,咱們將建立一個名爲 com.ibm.devworks.jxta2.shell.ShellStarter的 starter 類。這個類將:

  1. 讀取命令行參數,用唯一的名稱和傳輸參數來配置彙集節點或者邊緣節點。
  2. 用 net.jxta.util.config包建立節點公告,並存儲它。
  3. 用新的配置啓動 shell。

步驟 1 和 2 只有在沒有找到現有節點公告的狀況下才執行。

清單 1 顯示 com.ibm.devworks.jxta2.shell.ShellStarter類的部分代碼。參閱 參考資料一節,能夠下載完整的代碼。


清單 1. 拷貝收集器中的廉價內存分配
public class ShellStarter { 
 private static final String TLS_PRINCIPAL_PROP = "net.jxta.tls.principal"; 
    private static final String TLS_PASSWORD_PROP = "net.jxta.tls.password"; 
    private static final String ADDR_SEP = ":"; 
    private static final String PORT_PRE = "97"; 
    ...    
    public ShellStarter() { 
    } 
    
    public static void main(String[] args) throws Exception { 
     ...  
     String tpFname = 
       PlatformConfigurator.getPlatformConfigFileName(); 
     File tpFile = 
       new File(PlatformConfigurator.getPlatformConfigFileName()); 
     
     // only perform config if not already configured 
     if (!tpFile.exists())   {          
     tcpAddress = args[1]; 
     rdvNode = args[3]; 
     int rdvNodeNum = Integer.parseInt(rdvNode);     
     myPort = Integer.parseInt(PORT_PRE + args[2] + PORT_POST); 
     Vector rdvList = new Vector(); 
     if (rdvNodeNum < 10) 
        rdvList.add(TCP_PRE + tcpAddress + ADDR_SEP + PORT_PRE 
          + rdvNode + PORT_POST); 
     
     pa = PlatformConfigurator.createTcpEdge( 
     args[0], // peername 
     "A dwPeer - " + args[0], // description 
     tcpAddress, // ip 
     myPort,  // ports 
     rdvList    , // rdvs 
     USER_NAME, 
     USER_PASS 
     ); 
     // disable multicast 
      // pass in to preserve settings 
     TcpConfigurator tc = new TcpConfigurator(pa); 
     tc.setMulticastState(false); 
     // enable incoming connection 
     tc.setServer(tcpAddress); 
     tc.setServerEnabled(true); 
     tc.save(pa);   // save to pa only, not file 
     
     // configure the rendezvous 
     if (isRdv) { 
      // pass in to preserve rdv settings created by PlatformConfig 
     RdvConfigurator rdv = new RdvConfigurator(pa); 
     rdv.setIsRendezVous(true); 
     rdv.save(pa); 
     
     } 
     PlatformConfigurator.save(pa); 
     } // if config exists 
     System.setProperty(TLS_PRINCIPAL_PROP, USER_NAME); 
     System.setProperty(TLS_PASSWORD_PROP, USER_PASS); 
     Boot.main(args); 
    
     } 
 }

在清單 1 中,突出顯示的代碼展現瞭如何使用 net.jxta.util.config.PlatformConfigurator 類來準備一個節點公告,該節點公告將用於寂靜啓動 shell 的一個實例,而無需調用 GUI 配置器。咱們首先用若干命令行參數調用幫助器方法PlatformConfigurator.createTcpEdge()建立一個邊緣節點。不過,邊緣節點在默認狀況下啓用多播(multicast),所以咱們要在單機環境中禁用它。咱們用 net.jxta.util.config.TcpConfigurator類關閉多播狀態。咱們還使用同一個 TcpConfigurator啓用進入的 TCP 鏈接。最後,咱們檢查命令行是否指定了這是一個彙集節點。若是是的話,咱們就使用net.jxta.util.config.RdvConfigurator實例將節點設置爲彙集節點。還要注意 net.jxta.tls.principal 和net.jxta.tls.password系統屬性的設置,以繞過登陸提示。

ShellStarter的命令行使用如下的參數:

ShellStarter <peer name> <local IP or hostname> <port index> 
  <rdv port index> [edge | rdv]

咱們建立的全部邊緣節點和彙集節點都運行在同一臺主機上,可是它們使用不一樣的 TCP 端口。參數 <port index>代表節點將運行在 97?1 端口,其中「?」是索引。這使咱們能夠在 970一、97十一、9721 等端口上配置多達 10 個節點和彙集節點。例如,要在 9711 端口上用節點名 rdv一、IP 地址 192.168.23.17 建立一個彙集節點,咱們使用下面的命令行:

ShellStarter rdv1 192.168.23.17 1 99 rdv

注意使用端口索引 99 以代表這個彙集節點沒有其餘已知的種子彙集節點。

要在 9701 端口上建立名爲 peer一、具備同一 IP 的邊緣節點,並以上面的彙集節點爲種子,使用如下的命令行:

ShellStarter peer1 192.168.23.17 0 1 edge

對於 rendezvous, 在 test 目錄中有五個啓動目錄 —— 分別爲 rdv1 到 rdv5。還有一個稱爲 peer1 的節點啓動目錄。每個目錄包含一個 runshell.bat 文件,它有針對 ShellStarter的相應參數。您將須要編輯這些文件以修改 IP 地址。圖 4 顯示了這個網絡的配置。


圖 4. 佈置一個試驗用的 JXTA 2 網絡 
 

JXTA 2 中的新 shell 命令

在 JXTA 2 shell 發佈中,有幾個新命令。其中對開發者最有用的是 kdb命令。能夠在平臺運行的時候,用這個命令打開和關閉不一樣 JXTA 組件的調試日誌。

kdb命令是菜單驅動的,可用於設置 16 個組件中任何一個的日誌優先級(結果是生成的調試信息量差異很大)。

新的 route命令可用於顯示或者操做 JXTA 路由表信息。

JXTA 2 shell 中另外一個有用的命令是新的 rdv命令,它特別有助於理解彙集超級節點網絡是如何操做的。這個命令有許多選項,在咱們的試驗過程當中對其中一些選項進行了探索。

要啓動這個系統,首先從一到五按順序啓動全部彙集節點。必定要等每個彙集節點徹底啓動後再啓動下一個,而後再啓動 peer1。

回頁首

觀察 RPV 和遍歷器的活動

使用 rdv命令(參見側欄「 JXTA 2 中的新 shell 命令」),能夠看到由任何一個彙集節點維護的 RPV。

rdv -rpv

做爲例子,下面的代碼片斷顯示了 rdv1 給出的結果:

rdv5 
 rdv4 
 rdv3 
 rdv2

RPV 順序反映了節點的 JXTA 節點 ID 順序。咱們如今能夠觀察 RPV walker 的活動了。 rdv命令有一個運行字符串索引服務的選項(只用於測試和診斷)。要啓動這個服務,在全部六個節點上運行下面的命令:

rdv -start

如今,在其中一個彙集節點上建立一個字符串。在咱們的例子中,咱們在 rdv4 上建立「treasure」:

JXTA> rdv -add treasure

您能夠用下面的 list 選項來確認 rdv4 如今包含這個字符串:

JXTA> rdv -list treasure

如今,讓咱們看一下 RPV 遍歷器的活動。在 peer1上搜索如下的字符串:

JXTA>rdv -search treasure 
 Sending test message 
 rdv has sent search query for treasure 
 JXTA>rdv received from : jxta://uuid-59616261646162614A78746150325 
 03369170C5E92004D0DB2E48AAA571741C803 
                        found: treasure

馬上就在 rdv4上找到了 treasure 字符串。能夠在 rdv4上鍵入 whoami 驗證這個節點 ID 確實就是 rdv4。

看一下 rdv4shell 窗口,您將看到回覆確實是直接從 rdv4發出的:

Replying search query= treasure 
 send reply  sent

在其餘的彙集節點上,您會看到轉發這個查詢的證據:

Forwarding search query= treasure

下面是所發生的過程:當查詢「treasure」時,就調用匯集節點遍歷器,「遍歷」彙集超級節點網絡。做爲一臺彙集節點客戶機,這個請求被傳遞給惟一鏈接的彙集節點 ―― rdv1。從 rdv1 開始的「遍歷」引發了對查詢的傳播。每個沒有「treasure」字符串的彙集節點都經過遍歷器轉發這個請求給其餘已知的彙集節點(轉發次數不超過任意設置的生存時間 / 跳數限制值 10,並受循環檢測控制),直到這個請求到達 rdv4。收到這個查詢後,rdv4 直接回復給 peer1。

回頁首

觀察 SRDI 的活動

使用 rdvshell 命令,能夠容易地試驗 RPV 和彙集節點的遍歷機制。要實際看到 SRDI 的活動,咱們能夠設置 SRDI 消息日誌機制的LOG級別爲 DEBUG,並引發一些 SRDI 活動(即一個節點上建立一個公告)。

爲了不來自診斷字符串索引服務的僞消息,首先要關閉這個服務。關閉從 rdv1 到 rdv5 以及 peer1 的服務:

rdv -stop

而後在每個節點上,用 kdb命令將 SRDI 消息的 LOG級別設置爲 DEBUG:

JXTA>kdb 
 KDB Main Menu 
 1   Change LOG configuration 
 q   Quit 
 MAIN> 1 
 LOG Menu 
 1   Global          2   EndpointRouter 
 3   Endpoint        4   HTTP 
 5   TCP             6   TLS 
 7   Rendezvous      8   Discovery 
 9   Resolver        10  Pipe 
 11  Relay           12  Messengers 
 13  Messages        14  Quota Listener 
 15  SRDI            16  CM 
 q   Quit 
 LOG> 15 
 Level [w,i,f,d,e,q or ?])> d 
 LOG Menu 
 1   Global          2   EndpointRouter 
 3   Endpoint        4   HTTP 
 5   TCP             6   TLS 
 7   Rendezvous      8   Discovery 
 9   Resolver        10  Pipe 
 11  Relay           12  Messengers 
 13  Messages        14  Quota Listener 
 15  SRDI            16  CM 
 q   Quit 
 LOG>

如今,咱們將在 peer1 上建立一個公告,它會致使 SRDI 索引信息被推送到 rdv1,並隨後複製到 DHT 中。建立公告的最容易方式是建立一個新的 peergroup(其實是一個 peergoup 公告):

newpgrp -n supergroup

若是再看 rdv1 輸出的消息,您將會看到相似於下面的 SRDI 消息:

<DEBUG 14:36:07,078 Srdi:521> Pushing deltas in group NetPeerGroup 
 <DEBUG 14:36:07,078 Srdi:494> waiting 30000ms before sending 
 deltas in group NetPeerGroup

當散列和冗餘索引複製發生時,其餘彙集節點可能也會收到由 rdv1 發送的其餘 SRDI 消息。

回頁首

結束語

P2P 網絡對當今計算的影響是深遠的,而且已經有大量的計算用戶受到其影響。不要期望在徹底隔離的條件下設計一個可行的 P2P 應用程序建立環境。對用戶反饋、連續需求分析、從新考慮設計和設計迭代的考慮,是建立一個可以使用的設計環境的重要因素。JXTA 聽從了這種理念。在第二代版本中,JXTA 根據其早期使用者羣體的現實需求進行了改進和調整。

經過編程式地將重疊網絡分爲經過核心 彙集節點互連的邊緣節點,在今天常見的網絡拓撲上部署 JXTA 2 更容易了。同時緩解了在「平面的」體系結構中常見的消息廣播風暴和洪流的問題。

JXTA 2 的核心 彙集節點網絡實現了鬆散一致的 DHT。在 P2P 網絡上可用的全部資源均可在這個 DHT 的幫助下索引並動態獲取。由 DHT 維護的索引是 SRDI。與初版相比,再也不在網絡中傳播公告了,相反,在須要時只傳播索引信息。這種方法顯著地改進了可用網絡帶寬的使用,而代價只是在查詢解析時計算量稍有增長。

另外一個正在完善的領域是 JXTA 平臺 API。全功能節點配置 API 如今可使用了,它容許開發人員建立寂靜啓動的應用程序,而無需啓動 JXTA 的默認(一般是使人困惑的)節點配置器。咱們在建立寂靜 shell 啓動腳本進行試驗時使用了這個 API。使用新的 shell 命令 rdv,咱們能夠觀察彙集超級節點網絡的活動。經過使用新的 kdbshell 命令設置 DEBUG 日誌級別,還能夠觀察 SRDI 消息傳遞和操做。

建立可伸縮的、高性能的而且(最重要的) 可以使用的P2P 網絡須要不懈地追求。JXTA 2 是在正確的方向上邁出的重要一步。


參考資料

  • 您能夠參閱本文在 developerWorks 全球站點上的 英文原文

  • 下載本文的 源代碼。 


  • 有關 JXTA 平臺的第一個版本的信息,參閱一樣由 Sing Li 撰寫的 Making P2P interoperable 系列文章:
    • 「 第一部分: 介紹和發展歷史 」 提供了對 Project JXTA 的概述,並講述了在無需使用多餘的策略或者強制使用特定的應用程序操做模型的狀況下,如何啓用和方便 P2P 應用程序的簡單構建。
    • 「 第二部分: The JXTA command shell」 帶您親身體驗 JXTA shell。您將研究它的命令集,並經過用 Java 編程語言編寫本身的自定義命令來擴展其能力。第三部分:「Creating JXTA systems」 展現了 JXTA 對 TCP/IP 網絡的擴展,並示範了 JXTA 不侷限於典型的客戶機 / 服務器網絡。



  • 訪問官方的 JXTA community,能夠找到最新的規範、文檔、源代碼和二進制文件。 


  • Bernard Traversat et al 所寫的白皮書「 Project JXTA 2.0 Super-Peer Virtual Network」 (Project JXTA,2003 年 5 月)很是詳細地描述了彙集超級節點網絡的內部機制。 


  • 在 Michael Juntao Yuan 的「 Mobile P2P messaging, Part 2: Develop mobile extensions to generic P2P networks」(developerWorks,2003 年 1 月)一文中,能夠看到如何部署 JXME 並將移動設備變成 JXTA 和 Jabber 客戶機。 


  • 更多 JXME 的內容,可參閱 Roman Vichr 的「 Tips & tricks: JXTA」( developerWorks,2002 年 4 月)中關於移動設備的內容。 


  • Anne Zieger 在她的「 Peer-to-peer communications using XML」( developerWorks,2002 年 4 月)一文中分析了 JXTA。 


  • Todd Sundsted 的 developerWorks系列文章「 The practice of peer-to-peer computing」(2001 年 3 月 - 2002 年 1 月)提供了有關基本 P2P 計算原理的背景閱讀材料。 


  • 在 developerWorks Java 技術專區 能夠找到關於 Java 編程各個方面的數百篇文章。 

原文地址:http://www.ibm.com/developerworks/cn/java/j-jxta2/index.html#2

相關文章
相關標籤/搜索