• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            聲明一下:在reprinting欄目中的文章完全是轉(zhuǎn)載,來自互聯(lián)網(wǎng),本人完全是學(xué)習(xí)之用,如果,轉(zhuǎn)載侵犯了您的版權(quán),請(qǐng)給我聯(lián)系一下,我會(huì)作相應(yīng)處理。Email:gaoyuanxue118@gmail.com
            設(shè)計(jì)不受傳統(tǒng)網(wǎng)絡(luò)限制的 P2P 系統(tǒng)

            隨著移動(dòng)計(jì)算的普及和嵌入式可聯(lián)網(wǎng)微處理器的無處不在的應(yīng)用,TCP/IP 終于顯露出它已經(jīng)顯得過時(shí)。設(shè)計(jì) Jxta 的初衷就是要突破當(dāng)今基于 TCP/IP 的網(wǎng)絡(luò)的限制,從而擴(kuò)展因特網(wǎng)所能觸及的范圍。在 developerWorks 的討論 Jxta 的系列的這最后一篇文章中,Sing Li 舉例說明了體現(xiàn)這種擴(kuò)展的系統(tǒng),并解決了一個(gè)實(shí)際問題。您將看到 Jxta 不受客戶機(jī)/服務(wù)器網(wǎng)絡(luò)的典型約束的限制。請(qǐng)單擊本文頂部或底部的討論,在討論論壇與作者及其他讀者共享關(guān)于本文的心得。

            到本系列文章的 這里為止,我們仔細(xì)考察了 Jxta,一個(gè) Java 參考實(shí)現(xiàn)的新 P2P 平臺(tái),是如何工作的。在第一部分中,我們了解了 Jxta 的互操作特征。Jxta 被定義為一組互操作協(xié)議,可以跨硬件平臺(tái)、操作系統(tǒng)和編程語言實(shí)現(xiàn)。我們也討論了 Jxta 的操作模型和包括對(duì)等機(jī)、對(duì)等組、服務(wù)和管道在內(nèi)的許多重要概念。在第二部分中,我們的著眼點(diǎn)是建立和運(yùn)行 Jxta。我們探討了一個(gè) Jxta 應(yīng)用程序 — Jxta shell — 并經(jīng)歷了創(chuàng)建管道并從一個(gè)對(duì)等機(jī)發(fā)送消息到另一個(gè)對(duì)等機(jī)的情形。在我們編寫 Jxta shell 擴(kuò)展時(shí),我們第一次獲得了用 Jxta API 編程的經(jīng)驗(yàn)。迄今為止,我們討論 Jxta 的方式都是從下到上的。對(duì)于像我們這樣具有系統(tǒng)編程和網(wǎng)絡(luò)工程背景的人來說,這是再自然不過的。

            在本系列的這第三篇也即最后一篇文章中,我們要把事情顛倒過來。從那些從事應(yīng)用級(jí)設(shè)計(jì)和體系結(jié)構(gòu)的人的角度來說,本文是自上而下看待 Jxta 的。我們從一個(gè)特定的示例問題開始,對(duì)這個(gè)問題進(jìn)行分析并設(shè)計(jì)出一個(gè)解決方案,從而展示 Jxta 是如何自然地解決該問題的。

            隨著本文的進(jìn)行,我們討論 Jxta 如何通過并列(juxtaposition)改變聯(lián)網(wǎng)的前景展望,我們還提供一個(gè) Jxta 服務(wù)和客戶機(jī)的設(shè)計(jì)和代碼。

            解決一個(gè)分布式數(shù)據(jù)收集問題
            設(shè) 想一下我們需要?jiǎng)?chuàng)建一個(gè)大規(guī)模的氣象數(shù)據(jù)收集和分析系統(tǒng)。在這個(gè)系統(tǒng)中,我們有數(shù)百個(gè)氣象數(shù)據(jù)收集點(diǎn);每個(gè)收集點(diǎn)配備一個(gè)微型氣象站,這些氣象站將當(dāng)前溫 度(和其它大氣狀態(tài))提供給一組數(shù)據(jù)集中器。收集器遍布世界各地;這些收集器并不是都直接連接到因特網(wǎng),任何時(shí)候都可能有新的數(shù)據(jù)收集器連接上來或脫開連 接。在這個(gè)項(xiàng)目中,參與進(jìn)來的收集器的確切數(shù)量經(jīng)常在變化;數(shù)據(jù)分析和處理基于區(qū)域平均值。

            開始時(shí)只有 10 個(gè)集中器。每個(gè)集中器監(jiān)視來自許多個(gè)收集器的數(shù)據(jù),這些數(shù)據(jù)被實(shí)時(shí)提供給關(guān)系數(shù)據(jù)庫(kù)。隨后,來自關(guān)系數(shù)據(jù)庫(kù)的數(shù)據(jù)被提供給運(yùn)行氣象分析和預(yù)測(cè)的仿真模型的 超級(jí)計(jì)算機(jī)并由它處理。集中器的數(shù)量和位置會(huì)發(fā)生變化,但它們的行為則大多更穩(wěn)定。一旦安裝后,集中器就會(huì)保持運(yùn)轉(zhuǎn),除非碰到系統(tǒng)失效。

            我們必須解決的問題:我們的系統(tǒng)如何能夠持續(xù)運(yùn)轉(zhuǎn),并能考慮到在幾乎不影響整體性能的條件下,允許動(dòng)態(tài)添加或除去收集器和集中器。

            初始分析:特定網(wǎng)絡(luò)的復(fù)雜性
            系 統(tǒng)中的某些收集器可直接訪問因特網(wǎng);其它的通過無線電傳輸技術(shù)進(jìn)行連接,它們處在惡劣的外部環(huán)境中。事實(shí)上,在這些基于無線電的收集器中,許多都被設(shè)計(jì)成 了節(jié)能的,以延長(zhǎng)電池壽命;收集器的有效范圍僅夠與下一個(gè)最近的收集器或基站聯(lián)系。這些收集器中許多都不支持 TCP/IP,而是使用基本的分組無線技術(shù)。一些更獨(dú)立的收集器僅僅靠其太陽能電池板獲得能量,并使用衛(wèi)星傳輸進(jìn)行通信。還有另外一些收集器則連接到標(biāo)準(zhǔn) 蜂窩電話上,用 SMS(short message service,短消息服務(wù))消息傳遞來發(fā)送消息。

            在項(xiàng)目的整個(gè)生命周期中, 可用的收集器的數(shù)量會(huì)發(fā)生變化;在項(xiàng)目開始時(shí),我們無法預(yù)測(cè)將會(huì)構(gòu)建到未來收集器中的連接類型,也無法預(yù)測(cè)收集器將使用的技術(shù)。例如,在項(xiàng)目的某個(gè)階段, 在一個(gè)超級(jí)計(jì)算機(jī)群集內(nèi)使用軟件仿真來仿真數(shù)量巨大的收集器。我們的解決方案必須能適應(yīng)所有收集器,不管是真正的還是仿真的,現(xiàn)在的還是將來的。

            解決方案:并列(Juxtaposition)
            圖 1 顯示用來解決這個(gè)問題的高層次設(shè)計(jì)。

            圖 1. 解決數(shù)據(jù)收集問題

            image請(qǐng) 注意,并列 P2P 網(wǎng)絡(luò)用來適應(yīng)網(wǎng)絡(luò)的多種不同情況,而集中器提供 P2P 網(wǎng)絡(luò)和傳統(tǒng)的客戶機(jī)/服務(wù)器網(wǎng)絡(luò)之間的連接,數(shù)據(jù)庫(kù)服務(wù)器和超級(jí)計(jì)算機(jī)駐留在客戶機(jī)/服務(wù)器網(wǎng)絡(luò)。集中器充當(dāng)兩個(gè)網(wǎng)絡(luò)之間的網(wǎng)橋 — 每個(gè)集中器在 P2P 網(wǎng)絡(luò)上具有動(dòng)態(tài)特性,在客戶機(jī)/服務(wù)器網(wǎng)絡(luò)具有靜態(tài)特性。

            這個(gè)體系結(jié)構(gòu)反映了 Jxta 對(duì)傳統(tǒng)系統(tǒng)的補(bǔ)充作用和提供并行于這些傳統(tǒng)系統(tǒng)的增值的能力 — 通過并列(juxtaposition),Jxta 的名稱就源于這個(gè)詞語。

            我們不想深入討論這里的客戶機(jī)/服務(wù)器網(wǎng)絡(luò)的細(xì)節(jié),因?yàn)槠渲胁]有什么獨(dú)特之處;我們甚至可以使用 VPN 技術(shù)在因特網(wǎng)上運(yùn)行它。有趣的部分在 P2P 網(wǎng)絡(luò)。圖 2 顯示了它的組成,它可隨將來的變化而變化。請(qǐng)注意其中用到的多種不同技術(shù)。

            圖 2. 數(shù)據(jù)收集器網(wǎng)絡(luò)的組成


            image在實(shí)現(xiàn)這個(gè) P2P 網(wǎng)絡(luò)時(shí),我們可以利用 Jxta,從而獲得以下優(yōu)點(diǎn):

            容易地添加或除去新的收集器或集中器,這得益于 Jxta 的統(tǒng)一分散尋址


            設(shè)計(jì)簡(jiǎn)單性,這得益于 Jxta 的網(wǎng)絡(luò)虛擬化


            持續(xù)運(yùn)轉(zhuǎn),這得益于 Jxta 支持故障彈性


            免維護(hù)運(yùn)轉(zhuǎn),這得益于 Jxta 支持動(dòng)態(tài)自我組織網(wǎng)絡(luò)


            支持跨越許多硬件平臺(tái)和編程語言的多種不同實(shí)現(xiàn),支持所用的各種不同通信協(xié)議
            讓我們來更詳細(xì)地研究一下其中幾個(gè)益處,并看看 Jxta 如何為體系結(jié)構(gòu)的各個(gè)方面作出獨(dú)特的貢獻(xiàn)。

            統(tǒng)一分散尋址
            統(tǒng)一分散尋址的字面意思是,對(duì)等機(jī)可以為自己生成一個(gè) ID 并立即加入到網(wǎng)絡(luò),而不必與任何注冊(cè)人或中央認(rèn)證機(jī)構(gòu)聯(lián)系,而當(dāng)今的 DNS 則必須這樣。這一特征使我們?nèi)魏螘r(shí)候都可以向網(wǎng)絡(luò)添加收集器和集中器。

            在 本文附帶的代碼包中(您可以從參考資料下載它),我們提供了名為 mdidgen 的實(shí)用程序,它可以用來為新的 Jxta 服務(wù)和管道生成地址。(要更多了解 mdidgen,請(qǐng)參閱旁注 mdidgen 實(shí)用程序。)您可以閱讀本系列的第一篇文章,了解 Jxta ID 是如何用來對(duì) Jxta 對(duì)象(例如:對(duì)等機(jī)、對(duì)等組、服務(wù)和管道)進(jìn)行統(tǒng)一尋址的。

            請(qǐng)注意,Jxta 網(wǎng)絡(luò)中的對(duì)等機(jī)不一定要有一個(gè)獨(dú)立的物理存在。在我們的示例中,我們用一個(gè)超級(jí)計(jì)算機(jī)群集來仿真數(shù)量巨大的收集器,每個(gè)收集器有它自己的統(tǒng)一地址。這些仿 真收集器的每一個(gè)在 P2P 網(wǎng)絡(luò)的其它部分看來都是一個(gè)與那些具有物理存在的對(duì)等機(jī)沒有什么差別的對(duì)等機(jī)。

            網(wǎng)絡(luò)虛擬化
            通過分散尋址為所有收集器和集中器賦予網(wǎng)絡(luò)中唯一的標(biāo)識(shí)后,它們立即就成為網(wǎng)絡(luò)中的對(duì)等機(jī)并開始彼此通信。盡管它們可能通過許多種不同的消息傳遞機(jī)制進(jìn)行相互聯(lián)系,但在 Jxta 級(jí)別上,它們都只是一個(gè)虛擬網(wǎng)狀網(wǎng)絡(luò)中的節(jié)點(diǎn),如圖 3 所示。

            圖 3. 網(wǎng)絡(luò)虛擬化


            image請(qǐng) 注意,將收集器和對(duì)等機(jī)實(shí)際相互連接起來的所有不同的傳輸和尋址模式都被虛擬化了,只留下一個(gè)網(wǎng)狀網(wǎng)絡(luò),其中的每個(gè)對(duì)等機(jī)都與其它每一個(gè)對(duì)等機(jī)相連接。 Jxta 通過使用統(tǒng)一尋址模式和極遲綁定(very late binding),在多個(gè)端點(diǎn)協(xié)議上添加一個(gè)智能消息路由層做到這一點(diǎn)。從本質(zhì)上說,每一個(gè)端點(diǎn)協(xié)議或傳輸協(xié)議棧都成為虛擬 Jxta 網(wǎng)絡(luò)的一個(gè)驅(qū)動(dòng)程序,將虛擬網(wǎng)絡(luò)映射到物理網(wǎng)絡(luò)上。圖 4 顯示了這種設(shè)置。

            圖 4. 端點(diǎn)協(xié)議作為驅(qū)動(dòng)程序


            image通 信協(xié)議要成為合格的端點(diǎn)協(xié)議,只需要它能夠在兩個(gè)物理節(jié)點(diǎn)之間發(fā)送或接收 XML 消息。對(duì)傳輸可靠性或消息廣播支持沒有什么要求。因而,最簡(jiǎn)單的分組無線協(xié)議也可以用作端點(diǎn)協(xié)議驅(qū)動(dòng)程序,與像 TCP/IP 這樣的復(fù)雜多層協(xié)議并列。這也解釋了為什么 HTTP 和 TCP/IP 在 Jxta 協(xié)議棧內(nèi)都是同一級(jí)別的端點(diǎn)協(xié)議,盡管它們的物理級(jí)別非常不同。HTTP 是一個(gè)受支持的端點(diǎn)協(xié)議,因?yàn)橹灰斜匾湍軌虼┰奖M可能多的防火墻,從而獲取從一個(gè) Jxta 對(duì)等機(jī)傳送到另一個(gè)的消息。

            Jxta 網(wǎng)絡(luò)中的每個(gè)對(duì)等機(jī)可以同時(shí)支持多個(gè)端點(diǎn)協(xié)議,Jxta 虛擬網(wǎng)絡(luò)機(jī)制會(huì)以一種盡可能遲的方式將虛擬化的統(tǒng)一網(wǎng)絡(luò)地址映射到物理網(wǎng)絡(luò)地址(在 Jxta 中稱為網(wǎng)絡(luò)端點(diǎn))。從本質(zhì)上說,一個(gè)對(duì)等機(jī)對(duì)應(yīng)于一組物理端點(diǎn),其中的每個(gè)物理端點(diǎn)可以在完全不同的物理通信協(xié)議上實(shí)現(xiàn)。較高級(jí)別的虛擬化和路由服務(wù)隱藏 了這一點(diǎn)。許多人或許能看出這就是多協(xié)議路由器的一個(gè)非常高級(jí)的形式 — 正是這相同的設(shè)備使當(dāng)今的因特網(wǎng)成為現(xiàn)實(shí)。這一概念的發(fā)展將把我們帶向一個(gè)更加普遍的因特網(wǎng),這是再自然不過的了。

            讓我們更詳細(xì)地研究一下圖 5 所示的示例。對(duì)等機(jī) A 是網(wǎng)絡(luò)中的一個(gè)收集器,它試圖通過一系列中介收集器(對(duì)等機(jī) B、C 和 D)將其數(shù)據(jù)發(fā)送到集中器(對(duì)等機(jī) E)。在圖中每個(gè)對(duì)等機(jī)的下面是該對(duì)等機(jī)所支持的一組協(xié)議。

            圖 5. Jxta 路由示例


            image因?yàn)閷?duì)等機(jī) A 不直接連接到對(duì)等機(jī) E,所以它的消息必須通過中介對(duì)等機(jī) B、C 和 D 進(jìn)行路由。Jxta 將自動(dòng)對(duì)消息進(jìn)行路由:

            使用 TCP/IP 從對(duì)等機(jī) A 到對(duì)等機(jī) B


            使用分組無線協(xié)議從對(duì)等機(jī) B 到對(duì)等機(jī) C


            使用 SMS 從對(duì)等機(jī) C 到對(duì)等機(jī) D


            使用 HTTP 從對(duì)等機(jī) D 到對(duì)等機(jī) E
            對(duì) 等機(jī) E 將在它創(chuàng)建的管道上接收來自對(duì)等機(jī) A 的消息,完全未覺察 Jxta 為它所執(zhí)行的復(fù)雜工作。請(qǐng)注意,對(duì)等機(jī) C 到對(duì)等機(jī) D 的路徑是非對(duì)稱的;Jxta 就是專門設(shè)計(jì)來處理這種狀況的。如果有條消息要從對(duì)等機(jī) E 發(fā)送回對(duì)等機(jī) A,則 Jxta 將使用撥號(hào)調(diào)制解調(diào)器 PPP 自動(dòng)地從對(duì)等機(jī) D 路由到對(duì)等機(jī) C。

            故障彈性
            盡管上面所描述的路由功能已經(jīng)令人非常驚奇,但更為重要的是, Jxta 必須能夠適合 P2P 網(wǎng)絡(luò)不斷變化的拓?fù)浣Y(jié)構(gòu)。特別是它必須能夠處理充當(dāng)消息路由代理的 P2P 對(duì)等機(jī)與生俱來的不可靠性。在我們的例子中,如果中繼收集器不可用,那么,依賴另一個(gè)收集器來路由它的消息的收集器將不能進(jìn)行通信。

            當(dāng) 有對(duì)等機(jī)加入或離開網(wǎng)絡(luò)時(shí),Jxta 要能夠?qū)崟r(shí)對(duì)消息進(jìn)行重路由。再考慮一下圖 5 中的路由示例。請(qǐng)?jiān)O(shè)想一下,由于某些原因,就在對(duì)等機(jī) A 已經(jīng)發(fā)送出消息(現(xiàn)在正在傳輸)而尚未到達(dá)對(duì)等機(jī) C 時(shí),對(duì)等機(jī) C 和對(duì)等機(jī) D 之間的衛(wèi)星鏈路卻斷了。Jxta 必須能夠動(dòng)態(tài)地通過某些替代路徑(可能是通過另一組中間節(jié)點(diǎn))將該消息重路由到對(duì)等機(jī) E。這種動(dòng)態(tài)重路由是基于最大努力(best-effort)完成的;偶而有這樣的情況,如果沒有可能的路由(除非中介傳輸支持持久隊(duì)列),則消息可能會(huì) 被丟失。由于這種重路由能夠改換實(shí)際用來到達(dá)對(duì)等機(jī) E 的端點(diǎn)協(xié)議(例如:從 HTTP 到 TCP/IP),所以,要一直達(dá)到路由的最后一個(gè)跳數(shù)時(shí),對(duì)等機(jī)到物理端點(diǎn)的綁定才會(huì)發(fā)生。這就是 Jxta 的極遲綁定的本質(zhì)。

            在對(duì)等組級(jí)別上(請(qǐng)參閱本系列的第一篇文章了解有關(guān)對(duì)等組的更多知識(shí)),Jxta 通過支持對(duì)等組服務(wù) — 在對(duì)等組內(nèi)總是可用的、冗余地實(shí)現(xiàn)的服務(wù) — 支持故障彈性。

            動(dòng)態(tài)自我組織網(wǎng)絡(luò)
            當(dāng)具有統(tǒng)一虛擬網(wǎng)絡(luò) ID 的對(duì)等機(jī)插入到 Jxta 網(wǎng)絡(luò)中時(shí),它必須這樣來自我引導(dǎo):

            定位本地對(duì)等機(jī)并發(fā)現(xiàn)它們的功能


            發(fā)現(xiàn)可用的對(duì)等組并加入其中一個(gè)


            發(fā)現(xiàn)對(duì)等組中可用的服務(wù)并開始使用它們
            我 們從本系列的第二篇文章中了解到,這一切都是在消息級(jí)別上通過發(fā)布、中繼、中介高速緩存和搜索稱為廣告的不同類型的消息完成的。Jxta 的 Java 參考實(shí)現(xiàn)有一個(gè)解析器和使發(fā)布-高速緩存-搜索(publish-cache-search)過程簡(jiǎn)便的集中服務(wù)層。

            Jxta 中的對(duì)等組的作用是作為網(wǎng)絡(luò)分區(qū)(network-partitioning)機(jī)制,確保廣告只被中繼到能夠使用這些廣告的組成員。不同的對(duì)等組可以包含對(duì)等機(jī)和對(duì)等組服務(wù)的不同組合,充當(dāng)功能性的捆束機(jī)制。對(duì)等組也可以起到特定應(yīng)用程序的認(rèn)證域的作用。

            mdidgen 實(shí)用程序


            實(shí) 用類 com.ibm.jxta.mdidgen 可以用來以分散方式為 Jxta 對(duì)象生成統(tǒng)一地址。它生成一個(gè)新的 ModuleClassID、一個(gè)相應(yīng)的 ModuleSpecID 和一個(gè)與某個(gè)組(在啟動(dòng)時(shí)被讀取的配置文件中指定)關(guān)聯(lián)的新 PipeID。所生成的這些 ID 是立即可以使用的 Java 聲明形式,并且立即可以插入到您的代碼中。這就是我們?yōu)? ModuleSpecAdvertisement 和集中器服務(wù)管道生成 ID 的方式。

            設(shè)計(jì) Jxta 服務(wù)和 Jxta 客戶機(jī)
            讓我們回到氣象站示例上來。從概念上說,集中器實(shí)現(xiàn)必須:

            讀取并處理適當(dāng)?shù)呐渲梦募@個(gè)文件告訴集中器加入到哪個(gè) Jxta 組。(樣本代碼包中包含有我們示例的配置文件。)


            啟動(dòng) Jxta。


            加入到配置文件所指定的組。


            進(jìn)行搜索,以判斷集中器服務(wù)的服務(wù)廣告是否存在;如果不存在,就創(chuàng)建一個(gè)并發(fā)布它。


            創(chuàng)建一條相應(yīng)于該服務(wù)的輸入管道。


            在管道等待來自收集器的消息。


            一旦消息到達(dá),就處理它并存儲(chǔ)到 RDBMS 中。


            回到第 6 步。
            這個(gè)邏輯在 com.ibm.jxta.Concentrator 類中實(shí)現(xiàn)。您可以從參考資料部分下載這個(gè)類及所有來自本文的代碼。

            收集器實(shí)現(xiàn)必須:

            讀取并處理上述配置文件。


            啟動(dòng) Jxta。


            加入到配置文件所指定的組。


            發(fā)現(xiàn)集中器服務(wù)的服務(wù)廣告;如果服務(wù)廣告不可用,我們就無法繼續(xù)。


            從服務(wù)廣告抽取管道信息。


            每隔一段時(shí)間收集數(shù)據(jù)。


            創(chuàng)建包含收集器位置和數(shù)據(jù)的消息。


            通過管道將消息發(fā)送到集中器服務(wù)。


            回到第 6 步。
            上述邏輯在 com.ibm.jxta.Collector 類中實(shí)現(xiàn)。

            將公共任務(wù)分解到 DwJxtaPeer 超類
            有很多任務(wù)對(duì)收集器和集中器角色都是公共的。為了消除不必要的代碼重復(fù)并使將來的維護(hù)更簡(jiǎn)單,讓我們把這些公共任務(wù)分解出來放入名為 com.ibm.jxta.DWJxtaPeer 的超類。

            其中一個(gè)公共任務(wù)是執(zhí)行 ModuleSpecAdvertisement 的發(fā)現(xiàn)(請(qǐng)參閱旁注 JXTA 中的服務(wù)廣告了解關(guān)于這個(gè)廣告的更多知識(shí))。這由清單 1 中的 findModuleSpecAdv() 方法執(zhí)行:

            清單 1. findModuleSpecAdv()
            protected ModuleSpecAdvertisement findModuleSpecAdv() {
            return (ModuleSpecAdvertisement) findAdv("ModuleSpecAdvertisement",
            "Name",ModuleSpecName, new ModuleSpecAdvValidator(), false );
            }



            請(qǐng)注意,findModuleSpecAdv() 調(diào)用另一個(gè)名為 findAdv() 的通用方法,我們用這個(gè)方法發(fā)現(xiàn)廣告。findAdv() 的參數(shù)是:

            參數(shù) 描述
            AdvType 廣告類型的字符串描述 — 例如,PipeAdvertisement。
            Attr 搜索廣告時(shí)要匹配的標(biāo)記 — 例如,Name。
            Value 與所指定的屬性匹配的值。
            Validator 一個(gè)實(shí)現(xiàn) FindValidate 接口的對(duì)象。這個(gè)接口有一個(gè)方法 checkAdv(),當(dāng)找到一條廣告時(shí),這個(gè)方法就被用來立即對(duì)這條廣告進(jìn)行驗(yàn)證。
            LocalOnly 一個(gè)布爾標(biāo)志,表明該發(fā)現(xiàn)是否只應(yīng)在本地執(zhí)行,還是跨網(wǎng)絡(luò)在遠(yuǎn)程執(zhí)行。

            如清單 2 所示,該方法的第一部分通過使用組的發(fā)現(xiàn)服務(wù)的 getLocalAdvertisement() 方法,僅根據(jù)本地廣告高速緩存執(zhí)行對(duì)廣告的發(fā)現(xiàn)。請(qǐng)注意對(duì) validator.checkAdv() 調(diào)用,用來對(duì)所找到的任何廣告進(jìn)行驗(yàn)證。

            清單 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



            如果該發(fā)現(xiàn)是本地的,則邏輯就在這里停止。否則,我們就發(fā)送一條查詢到網(wǎng)絡(luò),執(zhí)行遠(yuǎn)程發(fā)現(xiàn)。發(fā)現(xiàn)服務(wù)將把所找到的任何廣告都存儲(chǔ)到本地高速緩存。我們只要給點(diǎn)時(shí)間就可以讓遠(yuǎn)程發(fā)現(xiàn)發(fā)生。在清單 3 中,循環(huán)大約持續(xù)了五秒鐘:

            清單 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("");



            此時(shí),已發(fā)現(xiàn)的任何廣告都應(yīng)可在本地高速緩存中找到。在清單 4 中,我們?cè)俅螆?zhí)行一個(gè)本地檢查。

            清單 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;
            }



            超類中的另兩個(gè)公共方法的描述在下表中;您可以作為練習(xí)完成對(duì)它們的分析。

            方法 描述
            PublishModuleSpecAdv() 如果發(fā)現(xiàn)過程沒有為服務(wù)找到現(xiàn)有的 ModuleSpecAdvertsiement,則這個(gè)方法被集中器調(diào)用。這個(gè)方法將創(chuàng)建一個(gè)服務(wù)(根據(jù)我們所生成的、固定的服務(wù) ID)。這條廣告將在本地和遠(yuǎn)程發(fā)布。僅在集中器第一次啟動(dòng)時(shí),當(dāng)配置改變時(shí),或者在本地高速緩存被清除后,才有創(chuàng)建廣告的必要。
            JoinGroupIfExists() 這個(gè)方法為收集器和集中器所調(diào)用;它嘗試加入到一個(gè)已命名的子組(subgroup),這個(gè)子組是全局 NetPeerGroup(缺省情況下大家都在這個(gè)組)的子(child)組。

            請(qǐng)看一下清單 5,它是 DwJxtaPeer 類的常數(shù)聲明部分的一部分:

            清單 5. 模塊 ID 定義
            public static final String ClassID =
            "urn:jxta:uuid-EE99266A1DE84E3DB34D9CC842EC889105";
            public static final String SpecID =
            "urn:jxta:uuid-EE99266A1DE84E3DB34D9CC842EC8891B9EB13ECA6FE44DDA112B5F5E357763006";


            Jxta 中的服務(wù)廣告


            服務(wù)廣告概念分解成一組相互聯(lián)系的廣告(共三條):
            ModuleClassAdvertiseent
            ModuleSpecAdvertisement
            MdouleImplAdvertisement

            為了減小在系統(tǒng)中循環(huán)的廣告的大小,也為了將服務(wù)的通用類(例如:銀行)、該類的特定規(guī)范(例如:存款和提款 API)和該服務(wù)(例如:API 基于 Java 的實(shí)現(xiàn))的實(shí)現(xiàn)之間的關(guān)系規(guī)格化,這樣做都是必要的。

            應(yīng)用程序或 Jxta 服務(wù)不必使用所有這些廣告,只要使用它所需要的就行了。在我們的系統(tǒng)中,我們只需要ModuleSpecAdvertisement,我們用它將服務(wù)連到管道上,并使這條廣告是遠(yuǎn)程可發(fā)現(xiàn)的。

            ModuleClassID 和 ModuleSpecID 用 mdidgen 實(shí)用程序生成并以硬編碼方式置于模塊中;它們與一個(gè)集中器服務(wù)的 ID 相對(duì)應(yīng)。所有的集中器都知道這個(gè)服務(wù)的 ID,而且這個(gè) ID 一旦生成就一直保持不變,所以組中的收集器肯定能夠找到這個(gè)集中器服務(wù)。因?yàn)樯? ModuleSpecID 時(shí)需要 ModuleClassID,所以這里有 ModuleClassID。為了輕松生成這些 ID,我們使用一個(gè)名為 AdvCooker 的庫(kù),它是 W.R. Bauer(vasha@jxta.org)創(chuàng)建的名為 jxta-wire 的 Jxta 項(xiàng)目的一部分。

            網(wǎng)絡(luò)中運(yùn)行的所有集中器實(shí)例將對(duì)同一個(gè)集中器對(duì)等組服務(wù)(通過使用相同的 ModuleSpecID 和偵聽廣播管道的同一個(gè)邏輯實(shí)例)作出應(yīng)答。這種冗余實(shí)現(xiàn)將確保集中器服務(wù)在對(duì)等組中始終可用。

            集中器:一個(gè) Jxta 對(duì)等組服務(wù)
            我們來看一下 com.ibm.jxta.Concentrator 實(shí)現(xiàn)。我們已經(jīng)提到過,它繼承(擴(kuò)展)自 DwJxtaPeer 類。這里是逐個(gè)方法地對(duì) Concentrator 進(jìn)行的描述:

            方法 描述
            init() 它應(yīng)該是該類被調(diào)用的第一個(gè)方法。這個(gè)方法調(diào)用私有 jxtaInit() 方法,然后創(chuàng)建輸入集中器服務(wù)管道的一個(gè)實(shí)例。
            process() 這個(gè)方法進(jìn)入一個(gè)無限循環(huán)。它在輸入集中器服務(wù)管道上偵聽傳入的收集器數(shù)據(jù)提交。對(duì)每一個(gè)提交,它都調(diào)用 processData() 對(duì)數(shù)據(jù)進(jìn)行處理。
            findPipeAdv() 這個(gè)方法對(duì)服務(wù)管道廣告執(zhí)行本地發(fā)現(xiàn)(也就是說,它檢查本地高速緩存)。
            jxtaInit() 這個(gè)方法首先讀取配置文件并設(shè)定我們想要加入到的組。接著,它啟動(dòng) Jxta 和 NetPeerGroup 網(wǎng)絡(luò),然后調(diào)用超類的 joinGroupIfExist() 加入到指定的組。接著,如果能夠,它就從本地高速緩存檢索服務(wù)管道廣告;否則,它將創(chuàng)建一個(gè)新的服務(wù)管道廣告(通過使用 createInputPipeAdvIfNotExist())。最后,它執(zhí)行發(fā)現(xiàn),看看是否可以找到 ModuleSpecAdvertisement;如果不能找到,它就創(chuàng)建一個(gè)并發(fā)布它。
            processData() 這個(gè)方法是占位符。在實(shí)際的項(xiàng)目中,它將使用后端客戶機(jī)/服務(wù)器網(wǎng)絡(luò)將所收集到的數(shù)據(jù)提交給 RDBMS(可能使用 JDBC)。
            createInputPipeAdvIfNotExist() 這個(gè)助手方法首先檢查高速緩存,看看服務(wù)管道廣告是否可用。如果不可用,它將創(chuàng)建該廣告并將它存儲(chǔ)到高速緩存中。在任一種情況下都返回正確的廣告。

            靜態(tài)類型定義如下:


            public static String servicePipeID =
            "urn:jxta:uuid-969610EE8945417CA56F9771197EE3965207E4C303154E7EB5878751AE22761804";




            這 是由 mdidgen 實(shí)用程序生成的管道 ID。它是該服務(wù)管道的統(tǒng)一地址,被所有集中器使用。它是一條廣播管道,因而偵聽消息的所有集中器都應(yīng)接收到那些來自收集器的消息。收集器從作為 ModuleSpecAdvertisement 的一部分的管道廣告中獲得這個(gè)管道 ID;收集器通過發(fā)現(xiàn)過程找到該廣告。

            收集器:編寫 Jxta 客戶機(jī)邏輯的代碼
            最后,我們來看一下 com.ibm.jxta.Collector 類的本地方法。

            方法 描述
            init() 它應(yīng)該是從這個(gè)類中調(diào)用的第一個(gè)方法。這個(gè)方法調(diào)用私有 jxtaInit(),然后創(chuàng)建用來將所收集到的數(shù)據(jù)發(fā)送到集中器服務(wù)的輸出管道。
            process() 這個(gè)方法有一個(gè)無限循環(huán),這個(gè)循環(huán)首先調(diào)用 collectData() 獲得測(cè)量的數(shù)據(jù),接著,創(chuàng)建一條 Jxta 消息并沿集中器服務(wù)管道將它發(fā)送到正在等待的集中器。循環(huán)內(nèi)每次采樣都延遲一段固定時(shí)間。
            jxtaInit() 這個(gè)方法首先讀取配置文件并對(duì)我們想要加入到的組進(jìn)行設(shè)置,接著確定收集器的位置。接著,它啟動(dòng) Jxta 和 NetPeerGroup 網(wǎng)絡(luò),然后調(diào)用超類的 joinGroupIfExist() 加入到指定的組。接著,它執(zhí)行發(fā)現(xiàn),看看是否可以找到相應(yīng)于眾所周知的集中器服務(wù)的 ModuleSpecAdvertisement;如果找不到,則退出。一旦找到了 ModuleSpecAdvertisment,它就將抽取集中器服務(wù)管道廣告并為輸出管道的創(chuàng)建做好準(zhǔn)備。
            collectData() 這個(gè)方法是一個(gè)占位符,用于實(shí)際的數(shù)據(jù)收集。在實(shí)際的項(xiàng)目中,這個(gè)方法將訪問各種數(shù)據(jù)輸入通道(可能使用輸入/輸出端口或本機(jī)代碼)并將所收集到的數(shù)據(jù)返回給調(diào)用者。

            實(shí)際運(yùn)轉(zhuǎn) Jxta:在您自己的機(jī)器上測(cè)試這個(gè)動(dòng)態(tài)網(wǎng)絡(luò)
            本文附帶的源代碼包中有一個(gè)便于您實(shí)驗(yàn)的目錄結(jié)構(gòu)。下面的目錄在 code 子目錄下:

            目錄 描述
            lib 來自 Jxta 核心最新穩(wěn)定版的所有 jar 文件,用于 Jxta shell 的所有 jar 文件以及來自 jxta-wire 項(xiàng)目的 jxta-wire.jar 文件都放在這里。(請(qǐng)參閱參考資料了解關(guān)于 Jxta shell 和 jxta-wire 的更多信息。)
            src 包含我們系統(tǒng)的源代碼。
            classes 包含我們系統(tǒng)的編譯好的類文件。
            shell1 第一個(gè)實(shí)驗(yàn)?zāi)夸洝N覀儗⒃谶@個(gè)目錄創(chuàng)建一個(gè)帶有一個(gè)集中器的 shell。我們還將在這里充分考查 mdidgen 實(shí)用程序。
            shell2 設(shè)置為網(wǎng)絡(luò)中的第二個(gè)對(duì)等機(jī)。這將運(yùn)行另一個(gè)集中器。
            shell3 設(shè)置為網(wǎng)絡(luò)中的第三個(gè)對(duì)等機(jī)。這將運(yùn)行一個(gè)收集器。

            要編譯這些代碼,您需要安裝 JDK 1.3 或更新版本。在 code 目錄時(shí),執(zhí)行 MAKEIT.BAT 批處理文件。這將編譯代碼并在 classes 目錄中創(chuàng)建類文件。

            接著,運(yùn)行 MAKEJAR.BAT 批處理文件。這將創(chuàng)建一個(gè)包含所有代碼的 dwjxta.jar 文件;將它放到 lib 目錄,為實(shí)驗(yàn)做好準(zhǔn)備。

            現(xiàn)在,請(qǐng)啟動(dòng)三個(gè)不同的命令窗口。將它們的目錄分別改到 shell1、shell2 和 shell3。

            在 shell1 目錄中編輯 runshell.bat 文件,將您在配置期間用來設(shè)置安全性的用戶標(biāo)識(shí)和密碼反映出來(密碼必須至少八個(gè)字符長(zhǎng))。編輯 runconc.bat 和 mdidgen.bat 文件,同樣要有這個(gè)用戶標(biāo)識(shí)和密碼。

            使用 runshell.bat 運(yùn)行這個(gè) shell,并按以下所示配置這個(gè)對(duì)等機(jī):

            對(duì)等機(jī)名: node1
            傳輸: TCP/IP 啟用,HTTP 禁用,選中作為集中點(diǎn),無中繼
            所用 TCP 端口: 9701
            安全性用戶名和密碼: 如在批處理文件中所定制

            因?yàn)槲覀兊南到y(tǒng)假設(shè)已經(jīng)創(chuàng)建了一個(gè)用于操作的組,所以我們需要在該 shell 中創(chuàng)建這個(gè)組。在這個(gè) shell 中時(shí),使用以下命令創(chuàng)建 dwtest 組:


            Jxta> myadv = mkadv -g dwtest
            Jxta> mygrp = mkpgrp -d myadv dwtest



            這將創(chuàng)建我們將使用的 dwtest 組。您可以這樣來確認(rèn)它已經(jīng)被創(chuàng)建:


            Jxta>groups
            group0: name = dwtest



            現(xiàn)在您可以退出該 shell。

            現(xiàn)在,請(qǐng)使用 mdidgen.bat 文件試驗(yàn)統(tǒng)一地址(ID)的分散生成。當(dāng)您運(yùn)行這個(gè)文件時(shí),應(yīng)得到類似這樣的輸出:

            清單 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";



            請(qǐng)注意所生成的 ModuleClassID、ModuleSpecID 和 PipeID。這就是我們獲得在集中器服務(wù)用到的 ID 的辦法。

            通過執(zhí)行 runconc.bat 文件啟動(dòng)集中器。這將讀取 dwConfig 文件,這個(gè)文件告訴集中器加入到 dwtest 組。您的輸出應(yīng)與此有些相似:

            清單 7. 1 號(hào)集中器(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...



            到這里,集中器實(shí)例就建立好了,并且為接收來自收集器的數(shù)據(jù)做好了準(zhǔn)備。

            現(xiàn)在,到 shell2 命令窗口中編輯 runconc.bat 文件,將您的安全性用戶標(biāo)識(shí)和密碼反映出來。接著,使用 runconc.bat 文件運(yùn)行集中器實(shí)例。在配置過程中設(shè)置以下參數(shù):

            對(duì)等機(jī)名: node2
            傳輸: TCP/IP 啟用,HTTP 禁用,無集中點(diǎn),無中繼
            所用 TCP 端口: 9702
            安全性用戶名和密碼: 如在批處理文件中所定制

            如果一切都正確運(yùn)行,則您應(yīng)看到與此相似的輸出:

            清單 8. 2 號(hào)集中器(來自 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...



            請(qǐng)注意,集中器的 ModuleSpecAdvertisement 被找到了,所以這個(gè)集中器實(shí)例不必另外創(chuàng)建一個(gè) ModuleSpecAdvertisement。現(xiàn)在它也在等待來自收集器的輸入。

            最 后,到 shell3 命令窗口中編輯 runcoll.bat 文件,將您的安全性用戶標(biāo)識(shí)和密碼反映出來。接著,使用 runcoll.bat 文件運(yùn)行收集器實(shí)例。這個(gè)實(shí)例將使用 shell3 目錄中的 dwColConfig 文件,該文件告訴收集器應(yīng)加入到 dwtest 組,這個(gè)組的位置是“Timbuktu North”。在配置過程中設(shè)置以下參數(shù):

            對(duì)等機(jī)名: node3
            傳輸: TCP/IP 啟用,HTTP 禁用,無集中點(diǎn),無中繼
            所用 TCP 端口: 9703
            安全性用戶名和密碼: 如在批處理文件中所定制

            這個(gè)收集器實(shí)例將開始查找 ModuleSpecAdvertisement 并且應(yīng)該能找到。然后,它將創(chuàng)建一條管道與已經(jīng)運(yùn)行的集中器通信。您應(yīng)看到與此相似的輸出:

            清單 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...



            請(qǐng)注意,數(shù)據(jù)被收集起來并定期發(fā)送到集中器服務(wù)。當(dāng)數(shù)據(jù)穿過 P2P 網(wǎng)絡(luò)以及兩個(gè)集中器接收這些數(shù)據(jù)并進(jìn)行處理時(shí),請(qǐng)注意觀察。

            高難度的應(yīng)用模式
            我 們的氣象收集示例說明了這樣一個(gè)應(yīng)用模式:在一般的方面,它使用普遍流行的應(yīng)用 P2P 系統(tǒng);從特定的方面,它使用 Jxta。這個(gè)模式包含兩個(gè)耦合極其松散的群體:消費(fèi)者和生產(chǎn)者。當(dāng)消費(fèi)者想要生產(chǎn)者所生產(chǎn)的產(chǎn)品時(shí),消費(fèi)者不愿作出堅(jiān)定的許諾,也不愿受限于特定生產(chǎn) 者。在這種想法背后可能有幾個(gè)現(xiàn)實(shí)動(dòng)機(jī)。消費(fèi)者可能想:

            可以在任意時(shí)間進(jìn)行選擇,以選擇最佳的可用生產(chǎn)者


            降低對(duì)某個(gè)生產(chǎn)者的成功或失敗的依賴風(fēng)險(xiǎn)


            從非常龐大的動(dòng)態(tài)社區(qū)中選擇,這種社區(qū)的大小和拓?fù)浣Y(jié)構(gòu)在物理上是難于管理的
            當(dāng) 消費(fèi)者群體和生產(chǎn)者群體出現(xiàn)交迭時(shí),這種模式變得十分有趣,當(dāng)前可用的、流行的、世界范圍內(nèi)的文件共享系統(tǒng)就例證了這一點(diǎn)。與傳統(tǒng)的聯(lián)網(wǎng)技術(shù)不同,P2P 系統(tǒng)從一開始就是設(shè)計(jì)來適應(yīng)這種應(yīng)用模式的。特別地,與使用傳統(tǒng)的客戶機(jī)/服務(wù)器技術(shù)進(jìn)行設(shè)計(jì)時(shí),必須提供的復(fù)雜的解決方案不同,Jxta 使得創(chuàng)建這些系統(tǒng)既容易又輕松。

            超越 TCP/IP 的聯(lián)網(wǎng)
            為了真正突出 Jxta 帶來的價(jià)值,我選擇了全球氣象信息收集系統(tǒng)作為一個(gè)示例。然而,這個(gè)問題及解決方案具有許多業(yè)務(wù)模式(business scenario)的典型特征,這些業(yè)務(wù)情形如移動(dòng)銷售隊(duì)伍自動(dòng)化、商品貿(mào)易、內(nèi)容分發(fā)和企業(yè)到企業(yè)電子商務(wù)等等,可以列出很多。您可以同時(shí)使用 P2P 網(wǎng)絡(luò)和傳統(tǒng)的客戶機(jī)/服務(wù)器網(wǎng)絡(luò),從而構(gòu)建大大超出當(dāng)今靜態(tài)邊界的新型網(wǎng)絡(luò)解決方案。開放源代碼的 Jxta 平臺(tái)將是這些新型解決方案的實(shí)現(xiàn)工具。我希望本系列已經(jīng)激起您探索 Jxta 提供的可能性的愿望。

            from-ibm developer

            posts - 4, comments - 8, trackbacks - 0, articles - 2

            Copyright © heart in the world

            国产精品一区二区久久| 久久青青国产| 人人狠狠综合久久亚洲| 国产精品久久久久久久久久影院 | 青青青青久久精品国产h| 久久国产精品一区| 久久夜色精品国产噜噜噜亚洲AV| 97久久婷婷五月综合色d啪蜜芽| 国产精品青草久久久久婷婷| 国产精品日韩深夜福利久久 | 久久精品夜夜夜夜夜久久| 国产精品美女久久久免费| 人人狠狠综合88综合久久| 久久精品视频网| 久久无码国产专区精品| 99久久99久久精品国产| 69久久精品无码一区二区| 欧美精品丝袜久久久中文字幕 | 久久久久亚洲AV成人片| 久久久久婷婷| 97久久精品午夜一区二区| 久久精品国产精品亚洲艾草网美妙| 久久午夜夜伦鲁鲁片免费无码影视 | 国产亚洲美女精品久久久| 久久精品国产亚洲av影院| 亚洲日本久久久午夜精品| 久久人人超碰精品CAOPOREN| 久久久久综合网久久| 一本一本久久A久久综合精品 | 久久精品国产亚洲AV嫖农村妇女| 亚洲国产成人久久综合一区77| 四虎国产永久免费久久| 久久精品国产网红主播| 亚洲AV无码久久精品狠狠爱浪潮 | 亚洲国产精品无码久久SM| 久久亚洲精品无码VA大香大香| 久久久久亚洲AV无码专区网站| 久久综合成人网| 99久久这里只精品国产免费| 久久精品aⅴ无码中文字字幕不卡| 久久久国产亚洲精品|