色婷婷狠狠18禁久久YY,CHINESE性内射高清国产,国产女人18毛片水真多1,国产AV在线观看

如何從頭開(kāi)始構(gòu)建類(lèi)似BitTorrent的P2P網(wǎng)絡(luò)

如何從頭開(kāi)始構(gòu)建類(lèi)似BitTorrent的P2P網(wǎng)絡(luò)?

由于我們對(duì) P2P 網(wǎng)絡(luò)和分布式系統(tǒng)感興趣,因此我們決定開(kāi)始用 Ruby 從頭開(kāi)始構(gòu)建自己的類(lèi)似 BitTorrent(BT)的系統(tǒng)。目前可用的版本是我們發(fā)布的 alpha 測(cè)試版本,提供了一個(gè)有效的概念驗(yàn)證:完整的分布式路由表,節(jié)點(diǎn)間的通信和基本的文件傳輸。在本文末列出了未來(lái)要新增的功能,我們將會(huì)繼續(xù)改進(jìn) Xorro。

本文記錄了我們構(gòu)建 Xorro P2P 的過(guò)程。希望讀者閱讀本文后能對(duì) P2P 系統(tǒng)有更深一層的認(rèn)識(shí)。

Xorro P2P 運(yùn)行界面

研究

作為嚴(yán)格意義上的 P2P 系統(tǒng)的最終用戶(hù),我們開(kāi)始了開(kāi)發(fā)旅程,面臨著非常陡峭的學(xué)習(xí)曲線。我們必須進(jìn)行大量的研究來(lái)了解 P2P 相關(guān)的歷史和內(nèi)部組成。我們進(jìn)行了搜集和閱讀 P2P 相關(guān)資料,從舊到新依次有:Napster、Gnutella、Freenet。BitTorrent、IPFS……

集中式系統(tǒng) vs 去中心化系統(tǒng)

需要理解的一個(gè)重要概念是集中式和去中心化系統(tǒng)之間的區(qū)別。第一代和第二代網(wǎng)絡(luò)架構(gòu)的比較有助于描述這兩者之間的區(qū)別。

Napster:集中式系統(tǒng)

Napster 是一種 P2P 文件共享服務(wù),主要用于傳輸音樂(lè)文件,在 1999~2001 年非常流行,據(jù)估計(jì),在鼎盛時(shí)期大約有 8000 萬(wàn)注冊(cè)用戶(hù)。Napster 的工作原理是讓所有節(jié)點(diǎn)都連接到中央索引服務(wù)器,該服務(wù)器包含所有關(guān)于誰(shuí)擁有哪些文件的信息。

集中式 P2P 網(wǎng)絡(luò)的一個(gè)示例

因?yàn)槠浔旧頌榧惺降慕Y(jié)構(gòu),Napster 中央服務(wù)器很容易遭受到攻擊,以及文件傳送的方式備受爭(zhēng)議,營(yíng)運(yùn)兩年后在法院的判決下被迫關(guān)閉。除此之外,中央索引服務(wù)器還意味著存在單點(diǎn)故障,以及缺乏可擴(kuò)展性。

BitTorrent、Gnutella、Freenet:去中心化系統(tǒng)

下一代 P2P 網(wǎng)絡(luò)通過(guò)采用去中心化的模式避免了與 Napster 相同的命運(yùn)。

在像 BitTorrent 這樣的去中心化系統(tǒng)中,每臺(tái)計(jì)算機(jī) / 節(jié)點(diǎn)都充當(dāng)客戶(hù)端和服務(wù)器,維護(hù)自己的文件查找索引片段。節(jié)點(diǎn)可以通過(guò)其他節(jié)點(diǎn)來(lái)查找文件的位置,免除了對(duì)中央服務(wù)器的依賴(lài)。

去中心化 P2P 網(wǎng)絡(luò)的一個(gè)示例

P2P 文件共享系統(tǒng)的深入介紹

了解新一代 P2P 系統(tǒng)的優(yōu)點(diǎn)后,我們繼續(xù)深入研究它們的特性。幸運(yùn)的是,P2P 網(wǎng)絡(luò)是已經(jīng)發(fā)展一段時(shí)間的技術(shù),因此網(wǎng)上有許多資源可供我們利用。其中分布式哈希表(distributed hash tables ,DHT)是 P2P 網(wǎng)絡(luò)中最重要的技術(shù),因此分布式哈希表是當(dāng)前 P2P 網(wǎng)絡(luò)的基礎(chǔ)。我們花了很多時(shí)間進(jìn)行閱讀及研究白皮書(shū)、規(guī)范文檔、博文和 Stackflow 問(wèn)答,在開(kāi)始編程之前,我們要確保對(duì)分布式哈希表有深刻的了解。

我們找到的有用資源的列表在這里: https://xorro-p2p.github.io/resources/

功能的選擇

BitTorrent 主要功能

經(jīng)過(guò)比較許多 P2P 網(wǎng)絡(luò)之后,我們最終鎖定了 BitTorrent 的一組功能,作為我們開(kāi)發(fā)應(yīng)用的第一個(gè)版本的藍(lán)本。這些功能將在下文中將進(jìn)一步詳細(xì)描述。

分布式哈希表(DHT)

文件切分

節(jié)點(diǎn)既作為客戶(hù)端又作為服務(wù)器

演示

在深入了解 Xorro P2P 的實(shí)現(xiàn)細(xì)節(jié)之前,請(qǐng)先查看下面的動(dòng)圖,該動(dòng)圖解說(shuō)了文件下載過(guò)程的實(shí)際情況。

首先,清單文件(即 BT 種子,下同)會(huì)被下載,然后依據(jù)種子中列出的文件切分信息下載各個(gè)文件切片。下載完所有的切片后,將它們重新合并回原始文件。

分布式哈希表的實(shí)現(xiàn)

先評(píng)估幾種分布式哈希表的優(yōu)缺點(diǎn):Chord、Pastry、Apache Cassandra、Kademlia 等等,再以此為考量作為我們選擇的依據(jù)。我們最終決定就其普及率、最簡(jiǎn)單的遠(yuǎn)程過(guò)程調(diào)用和信息的自動(dòng)傳播等優(yōu)點(diǎn),選擇了 Kademlia。

事實(shí)證明,由于大量的新概念:節(jié)點(diǎn)、路由表、桶(buckets)、異或距離、路由算法、遠(yuǎn)程過(guò)程調(diào)用(remote procedure calls,RPC)……,使得 Kademlia 的實(shí)施極具挑戰(zhàn)性。雖然當(dāng)時(shí)網(wǎng)上已經(jīng)有一些 Ruby 的實(shí)現(xiàn),但我們只依據(jù)規(guī)范和白皮書(shū),因?yàn)槲覀円獜念^開(kāi)始構(gòu)建分布式哈希表。

Kademlia

一個(gè) Kademlia 網(wǎng)絡(luò)由許多節(jié)點(diǎn)組成。

每一個(gè)節(jié)點(diǎn)都有:

具有唯一的 160 位 ID。

維護(hù)包含其他節(jié)點(diǎn)聯(lián)系信息的路由表。

維護(hù)較大的分布式哈希表中那些自己的段。

通過(guò) 4 個(gè)遠(yuǎn)程過(guò)程調(diào)用與其他節(jié)點(diǎn)通信。

每個(gè)節(jié)點(diǎn)的路由表被劃分為“桶”,每個(gè)桶包含與當(dāng)前節(jié)點(diǎn)的特定“距離”的節(jié)點(diǎn)的聯(lián)系信息。我們會(huì)在后面更詳細(xì)介紹關(guān)于距離的概念。

每個(gè)聯(lián)系信息都包含其他節(jié)點(diǎn)的 ID、IP 地址和端口號(hào)。

由于 Xorro 是一個(gè)文件共享應(yīng)用程序,因此分布式哈希表段將包含 key/value 對(duì),其中,每個(gè) key 是一個(gè)文件的 ID,對(duì)應(yīng)的 value 是文件的位置。

Kademlia 規(guī)范中描述的節(jié)點(diǎn)構(gòu)成。

節(jié)點(diǎn)通信

Kademlia 節(jié)點(diǎn)發(fā)送和響應(yīng)有四種基本的遠(yuǎn)程過(guò)程調(diào)用。

PING

與互聯(lián)網(wǎng)控制消息協(xié)議(Internet Control Message Protocol,ICMP)中的 Ping 非常相似,它是用于驗(yàn)證另一個(gè)節(jié)點(diǎn)是否仍處于活動(dòng)狀態(tài)。

FIND NODE

發(fā)送此遠(yuǎn)程過(guò)程調(diào)用時(shí)要找到特定節(jié)點(diǎn)的 ID。此遠(yuǎn)程過(guò)程調(diào)用的接收節(jié)點(diǎn)在自己的路由表中查找,并返回一組最接近正在查找的 ID 的聯(lián)系節(jié)點(diǎn)。

FIND VALUE

發(fā)送此遠(yuǎn)程過(guò)程調(diào)用時(shí)要帶有要定位的特定文件 ID。如果接收節(jié)點(diǎn)在自己的分布式哈希表段中找到這個(gè) ID,它將返回響應(yīng)的 Value(URL)。反之,則接收節(jié)點(diǎn)返回最接近文件 ID 的聯(lián)系節(jié)點(diǎn)列表。

STORE

此遠(yuǎn)程過(guò)程調(diào)用用于在接收節(jié)點(diǎn)的分布式哈希表段中存儲(chǔ) key/value 對(duì)(file_id/location)。

每次成功完成遠(yuǎn)程過(guò)程調(diào)用后,發(fā)送節(jié)點(diǎn)和接收節(jié)點(diǎn)都會(huì)在各自的路由表中插入或更新彼此的聯(lián)系信息。

尋找對(duì)等點(diǎn)和文件

一個(gè)節(jié)點(diǎn)如何在 Kademlia 網(wǎng)絡(luò)中找到其他節(jié)點(diǎn)或者文件呢?我們可以用現(xiàn)實(shí)生活中的例子來(lái)舉例。

如果某個(gè)人想找到另一個(gè)不認(rèn)識(shí)的人,他可能會(huì)采取以下步驟:

他可以詢(xún)問(wèn)離目標(biāo)人物更近的朋友。也許這些朋友和目標(biāo)人物在同一個(gè)行業(yè)工作,或者在同一個(gè)城市居住。

如果其中一個(gè)朋友知道目標(biāo)人物在哪里,那么就可以提供目標(biāo)人物的聯(lián)系信息,這樣查找就完成了。

如果這些朋友都不認(rèn)識(shí)目標(biāo)人物,他們可以給你提供可能認(rèn)識(shí)目標(biāo)人物的朋友的聯(lián)系信息。

然后你再詢(xún)問(wèn)這些人,看看他們是否知道目標(biāo)人物,重復(fù)這一過(guò)程,直到找到目標(biāo)人物,或者達(dá)到某種停止查找的條件。

Kademlia 節(jié)點(diǎn)在執(zhí)行查找時(shí)就遵循類(lèi)似的模式。

如果一個(gè)節(jié)點(diǎn)要從網(wǎng)絡(luò)中檢索一條信息(一個(gè)文件),它將發(fā)送 FIND VALUE 的遠(yuǎn)程過(guò)程調(diào)用到它自己的聯(lián)系節(jié)點(diǎn)子集,這些聯(lián)系節(jié)點(diǎn)的 ID 與它要查找的文件的 ID“最為接近”。如果任何接收節(jié)點(diǎn)在其分布式哈希表段中有這個(gè) ID,則它們將返回相應(yīng)的 value,否則,它們將返回更接近所查詢(xún)的 value 的節(jié)點(diǎn)列表。

下一個(gè)要討論的問(wèn)題是如何在 Kademlia 網(wǎng)絡(luò)中確定“距離”。

距離的計(jì)算

Kademlia 將節(jié)點(diǎn)之間的距離定義為節(jié)點(diǎn) ID 的“按位異或”(XOR)。XOR 運(yùn)算比較兩個(gè)輸入值:如果這些輸入相同,則結(jié)果為 false(0);如果輸入不同,則結(jié)果為 true(1)。兩個(gè)數(shù)字的異或是通過(guò)在這兩個(gè)數(shù)字的二進(jìn)制表示中找到每一位的 XOR 來(lái)計(jì)算的。

例如,下圖假設(shè) 4 位密鑰空間中的節(jié)點(diǎn) ID 為 11(只有 0~15 的的 ID 是可能的)。為證明這個(gè)概念,我們使用一些其他 ID 來(lái)計(jì)算 11 的 XOR。

在第一個(gè)例子中,我們計(jì)算節(jié)點(diǎn) ID 11 和節(jié)點(diǎn) ID 10 的 XOR 結(jié)果。兩個(gè) ID 的前三位是相同的,只有最后一位不同。ID 11 和 ID 10 進(jìn)行 XOR 運(yùn)算的結(jié)果是二進(jìn)制的 0001,或者十進(jìn)制的 1。

接下來(lái)我們計(jì)算 ID 11 和 ID 12 的 XOR 結(jié)果,只有第一位是相同的,而其他部分都是不同的。ID 11 和 ID 12 的 XOR 運(yùn)算的結(jié)果是二進(jìn)制的 0111,或十進(jìn)制的 7。

我們最后的一個(gè)例子是計(jì)算 ID 11 和 ID 4 的 XOR 結(jié)果。這里所有的位都不相同,結(jié)果是二進(jìn)制的 1111,十進(jìn)制為 15。

從這些結(jié)果中,你會(huì)注意到 Kademlia 的 XOR 度量的一個(gè)重要特征:如果節(jié)點(diǎn) ID 和當(dāng)前節(jié)點(diǎn)的 ID 的二進(jìn)制表示所共有的位相同個(gè)數(shù)越多,那么計(jì)算得到的 XOR 結(jié)果就越小。

Kademlia 網(wǎng)絡(luò)和路由表

Kademlia 中的每個(gè)節(jié)點(diǎn)都可以看做是二叉樹(shù)中的葉子。下面我們?cè)?4 位密鑰空間中畫(huà)出所有可能的 ID:0~15,從根(root)出發(fā),每一步往左則在該位上新增一個(gè)“0”,往右則在該位上新增一個(gè)“1”。

與 Kademlia 網(wǎng)絡(luò)相關(guān)的二叉樹(shù)最重要的特性是 O(log n) 查找時(shí)間。在 Kademlia 網(wǎng)絡(luò)中查找節(jié)點(diǎn)或文件是非常有效率的過(guò)程。

如前所述,路由表將聯(lián)系節(jié)點(diǎn)進(jìn)行分組并存儲(chǔ)到桶中,每個(gè)桶中包含一定距離的節(jié)點(diǎn)。這個(gè)距離就是“共享位長(zhǎng)度”,它是通過(guò)節(jié)點(diǎn) ID 與當(dāng)前 ID 進(jìn)行 XOR 運(yùn)算得到結(jié)果來(lái)得到的。

從下圖我們將看到這些桶是如何在一個(gè) 4 位密鑰空間中以 ID 11 的節(jié)點(diǎn)中組織的。其 ID 與當(dāng)前節(jié)點(diǎn)共享前 3 位前綴的節(jié)點(diǎn)存儲(chǔ)在一個(gè)桶中,而 ID 與當(dāng)前節(jié)點(diǎn)共享前 2 位前綴的節(jié)點(diǎn)存儲(chǔ)在另一個(gè)桶中,以此類(lèi)推。

文件切分和檢索

文件切分是將文件切分成更小的片段,命名為切片,并將 files/names 記錄在一個(gè)清單文件(即種子)中,這樣它們就可以按照適當(dāng)?shù)捻樞驒z索和重新合并。

文件切分提高了 P2P 網(wǎng)絡(luò)的分布性和可靠性,因?yàn)槎鄠€(gè)節(jié)點(diǎn)可以存儲(chǔ)共享文件的部分或全部切片。如果包含切片下載信息的節(jié)點(diǎn)離線了,此時(shí)可以從不同的源檢索該切片信息。

文件切分還可以節(jié)省網(wǎng)絡(luò)帶寬,共享潛在大文件的負(fù)載分布在許多節(jié)點(diǎn)中。

文件切分過(guò)程中會(huì)生成多個(gè)切片和一個(gè)清單文件(種子)。

在我們的實(shí)現(xiàn)中,文件添加和切分的過(guò)程是這樣的:

通過(guò)拖放將要共享的文件上傳到網(wǎng)絡(luò)中。

通過(guò)計(jì)算文件內(nèi)容的 SHA1 哈希值為文件創(chuàng)建 ID。

這個(gè) ID 被重新用作種子的文件名,擴(kuò)展名為“.xro”。這個(gè)過(guò)程對(duì)用戶(hù)來(lái)說(shuō)是透明的,用戶(hù)只需知道 ID 即可。

原始文件切分成 1 MB 塊,如果小于 1 MB,則切分為原始大小的 50%。

每個(gè)切片都被寫(xiě)入磁盤(pán),切片的名稱(chēng)就是其內(nèi)容的 SHA1 哈希值。

切片名稱(chēng)是按照順序?qū)懭敕N子文件的,以及原始文件名和文件大小(以字節(jié)為單位)。

種子和切片位置信息通過(guò) STORE 遠(yuǎn)程過(guò)程調(diào)用廣播給對(duì)等節(jié)點(diǎn)。對(duì)于每個(gè) shard/manifest,宿主節(jié)點(diǎn)在自己的路由表中查找與文件 ID 最接近的節(jié)點(diǎn)。這些對(duì)等節(jié)點(diǎn)都接收包含文件的 ID 和位置的 STORE 遠(yuǎn)程過(guò)程調(diào)用。

下面是 JSON 格式的種子內(nèi)容:

復(fù)制代碼

{

"file_name":"banana.mp4",

"length":9137395,

"pieces":[

"272610812651008498817059664145444816819140431736",

"255845820650928817902394043384061703021184974492",

"709124865584808529999187320247131501825035282844",

"463972141944555281071361859762050722622562309482",

"665233928362169136349271011451642022996948352498",

"460767108478119568061824765684889409150273585314",

"242856439500459087965632547950882773486858003109",

"1113118586291233368092664992853829437069513635744",

"55094692080869844054492088107211106202780121432"

]

}

文件檢索的處理方式也是類(lèi)似的:

用戶(hù)輸入他們想要從網(wǎng)絡(luò)中檢索的文件的 ID。這個(gè) ID 是文件內(nèi)容的哈希值,也恰好是他們首先檢索的清單文件的名稱(chēng)。

通過(guò)向最接近清單文件 ID 的對(duì)等節(jié)點(diǎn)發(fā)出 FIND VALUE 遠(yuǎn)程過(guò)程調(diào)用,從網(wǎng)絡(luò)中檢索清單文件。

下載清單文件后,節(jié)點(diǎn)為清單文件中記錄的每個(gè)切片重復(fù)查找和下載過(guò)程(FIND VALUR 遠(yuǎn)程過(guò)程調(diào)用)。

下載完所有切片后,將它們重新合并到原始文件中。

然后,節(jié)點(diǎn)向最接近文件各自 ID 的對(duì)等節(jié)點(diǎn)廣播其獲取的切片和清單的位置信息。

從 Xorro P2P 網(wǎng)絡(luò)中檢索文件的例子。

開(kāi)發(fā)策略:從本地環(huán)境模擬并擴(kuò)展網(wǎng)絡(luò)應(yīng)用到真實(shí)網(wǎng)絡(luò)。

第一階段:測(cè)試模式

我們是如何著手構(gòu)建和測(cè)試的?

在項(xiàng)目的早期階段,我們需要測(cè)試節(jié)點(diǎn)間的通信,但我們只有類(lèi)和測(cè)試套件,沒(méi)有網(wǎng)絡(luò),沒(méi)有遠(yuǎn)程過(guò)程調(diào)用傳輸,甚至也沒(méi)有幾臺(tái)計(jì)算機(jī)。

我們經(jīng)常啟動(dòng) Ruby 的交互式 Shell(IRB),將幾個(gè)節(jié)點(diǎn)進(jìn)行實(shí)例化,并讓它們手動(dòng)通信。當(dāng)然,這可以通過(guò)腳本來(lái)實(shí)現(xiàn)。但一旦引入真正的網(wǎng)絡(luò)環(huán)境,并且節(jié)點(diǎn)對(duì)象不能在相同的 Ruby 進(jìn)程中直接使用,否則它就會(huì)很快崩潰。

我們需要某種代理對(duì)象,它在測(cè)試和本地開(kāi)發(fā)期間以一種方式運(yùn)行,在實(shí)際網(wǎng)絡(luò)環(huán)境中部署時(shí)又以另一種方式運(yùn)行。

我們的解決方案是讓每個(gè)節(jié)點(diǎn)將所有網(wǎng)絡(luò)通信都委托給先前存在的網(wǎng)卡(Network Adapter)對(duì)象。

在測(cè)試時(shí),在這個(gè)網(wǎng)卡對(duì)象實(shí)際上是一個(gè)“Fake Network Adapter”(偽網(wǎng)卡),本質(zhì)上是一個(gè)由其他節(jié)點(diǎn)組成的數(shù)組,帶有一些用于查找和遠(yuǎn)程過(guò)程調(diào)用代理的方法。這允許我們?cè)跊](méi)有遠(yuǎn)程過(guò)程調(diào)用傳輸協(xié)議的情況下在本地沙箱中測(cè)試節(jié)點(diǎn)的交互過(guò)程。

典型的工作流程如下圖所示:

節(jié)點(diǎn) A 要求網(wǎng)絡(luò)向節(jié)點(diǎn) B 發(fā)送遠(yuǎn)程過(guò)程調(diào)用,節(jié)點(diǎn) A 提供聯(lián)系節(jié)點(diǎn)的 ID、IP 和端口。

網(wǎng)絡(luò)查找節(jié)點(diǎn) B 是否存在于 Fake Network (偽網(wǎng)絡(luò))環(huán)境中,這是通過(guò)聯(lián)系節(jié)點(diǎn)的 ID 來(lái)完成的。

網(wǎng)絡(luò)直接調(diào)用節(jié)點(diǎn) B 上的方法,改變狀態(tài)和 / 或返回一些數(shù)據(jù)作為響應(yīng)。

網(wǎng)絡(luò)將該響應(yīng)傳遞回節(jié)點(diǎn) A,節(jié)點(diǎn) A 反過(guò)來(lái)改變狀態(tài)或?qū)@些信息做出響應(yīng)。

第二階段:在本地沙箱中通過(guò) HTTP 進(jìn)行遠(yuǎn)程過(guò)程調(diào)用

我們的下一步是引入 HTTP 協(xié)議作為構(gòu)建遠(yuǎn)程過(guò)程調(diào)用方法的基礎(chǔ)協(xié)議。

為此,我們實(shí)現(xiàn)了一個(gè) Real Network Adapter (真網(wǎng)卡)對(duì)象。它與我們的 Fake Network Adapter 具有相同的接口,但不是通過(guò) ID 查找接收節(jié)點(diǎn)并直接調(diào)用該方法的,Real Network Adapter 從所提供的聯(lián)系節(jié)點(diǎn)信息和對(duì)應(yīng)于遠(yuǎn)程過(guò)程調(diào)用的路由中列出的 IP / 端口處理一個(gè) HTTP Post 請(qǐng)求,可能包括請(qǐng)求主體中的相關(guān)數(shù)據(jù)——請(qǐng)求節(jié)點(diǎn)的聯(lián)系信息、查詢(xún)信息等。

典型工作流程與上圖類(lèi)似:

節(jié)點(diǎn) A 要求網(wǎng)絡(luò)向節(jié)點(diǎn) B 提供遠(yuǎn)程過(guò)程調(diào)用,節(jié)點(diǎn) A 提供聯(lián)系節(jié)點(diǎn)的 ID、IP 和端口。

網(wǎng)絡(luò)為 IP、端口和遠(yuǎn)程過(guò)程調(diào)用路徑生成 HTTP POST 請(qǐng)求,并將其與任何有效負(fù)載數(shù)據(jù)一起發(fā)送。

接收節(jié)點(diǎn)的 HTTP 端點(diǎn)接收 POST 請(qǐng)求,并調(diào)用 Node 對(duì)象上的接收遠(yuǎn)程過(guò)程調(diào)用的方法。

此接收遠(yuǎn)程過(guò)程調(diào)用方法的返回值通過(guò) HTTP 端點(diǎn)轉(zhuǎn)換為 HTTP 響應(yīng),并發(fā)送回調(diào)用節(jié)點(diǎn)的網(wǎng)卡。

網(wǎng)絡(luò)接收響應(yīng),并將其傳遞給節(jié)點(diǎn) A,節(jié)點(diǎn) A 反過(guò)來(lái)更改狀態(tài)或?qū)@些新信息做出響應(yīng)。

正如你所見(jiàn)到的,從節(jié)點(diǎn)的角度來(lái)看,并沒(méi)有什么變化:每個(gè)節(jié)點(diǎn)都發(fā)送和接收相同的信息,但是網(wǎng)絡(luò)對(duì)象和 HTTP 端點(diǎn)抽象出節(jié)點(diǎn)之間的通信。

第三階段:RPC/HTTP 在互聯(lián)網(wǎng)環(huán)境下傳遞

一旦我們知道節(jié)點(diǎn)間的通信使用 HTTP 協(xié)議,我們的下一步就是將節(jié)點(diǎn)部署到互聯(lián)網(wǎng)上的多個(gè)系統(tǒng)上。如果系統(tǒng)直接在公共互聯(lián)網(wǎng)上運(yùn)行,或者它們位于已配置打開(kāi)端口的防火墻之后,這種方法就可以很好地工作。

NAT 防火墻后的節(jié)點(diǎn)則是另一回事。它們可以很好地加入網(wǎng)絡(luò)并檢索文件,但如果沒(méi)有端口轉(zhuǎn)發(fā)的話(huà),它們就不能接收傳入的 HTTP 連接,因此不能對(duì)網(wǎng)絡(luò)做出貢獻(xiàn)。

從長(zhǎng)遠(yuǎn)來(lái)看,目標(biāo)是基于 TCP / UDP 協(xié)議的遠(yuǎn)程過(guò)程調(diào)用和文件傳輸協(xié)議,同時(shí)支持 STUN 和 TURN 服務(wù)器來(lái)處理公共 IP / 端口發(fā)現(xiàn)和傳入連接。但是,在這個(gè)項(xiàng)目中,我們需要一種快速繞過(guò) NAT 和防火墻的方法。

為此,我們構(gòu)建了對(duì) Ngrok 的支持,這是一個(gè)第三方隧道服務(wù),這樣,防火墻后面的節(jié)點(diǎn)就可以成為我們網(wǎng)絡(luò)中完全正常運(yùn)行、功能齊全的成員。

靈活的節(jié)點(diǎn)實(shí)例化和啟動(dòng)腳本

我們意識(shí)到現(xiàn)在有許多不同的節(jié)點(diǎn)配置 / 環(huán)境需要支持和測(cè)試。此外,我們還需要一種能夠在這些配置之間快速、無(wú)縫切換的方法。

在每個(gè)環(huán)境中,一個(gè)節(jié)點(diǎn)廣播它的 IP / 端口,以及它所托管的每個(gè)切片或種子的完整 URL / 路徑。

如果我們只在本地環(huán)境中工作的話(huà),那么所有節(jié)點(diǎn)都在不同的 TCP 端口從“本地”進(jìn)行廣播。

如果節(jié)點(diǎn)直接在互聯(lián)網(wǎng)上,它應(yīng)該廣播自己的公共 IP 和端口。

如果節(jié)點(diǎn)具有完全限定的域名,那么該節(jié)點(diǎn)應(yīng)該廣播該域名,而不是數(shù)字 IP 地址。

如果節(jié)點(diǎn)位于防火墻之后,且防火墻已正確配置用于 NAT 轉(zhuǎn)換 / 端口轉(zhuǎn)發(fā),則該節(jié)點(diǎn)仍然可以依賴(lài)它的公共 IP 和端口。

如果節(jié)點(diǎn)位于沒(méi)有轉(zhuǎn)發(fā)端口的防火墻后面,則需要:

建立到 Ngrok 服務(wù)器的隧道,并注意到它唯一的 Ngrok 地址,這樣它就可以將地址廣播給其他節(jié)點(diǎn)。

要知道它是一個(gè) “Leech” 節(jié)點(diǎn),而不是廣播它所托管的任何文件的位置信息。

我們確定了節(jié)點(diǎn)可能擁有的許多配置,并創(chuàng)建了環(huán)境變量來(lái)表示這些選項(xiàng)。我們的節(jié)點(diǎn)實(shí)例化代碼對(duì)這些變量做出反應(yīng),我們?cè)O(shè)計(jì)了一系列 Bash 腳本,來(lái)為我們工作的每個(gè)環(huán)境標(biāo)準(zhǔn)化這些配置:測(cè)試、本地、局域網(wǎng)、廣域網(wǎng)等。

系統(tǒng)架構(gòu)

我們最終的系統(tǒng)架構(gòu)如下所示:

頂級(jí)對(duì)象是 XorroNode,它是一個(gè)模塊化的 Sinatra 應(yīng)用程序。

每個(gè) XorroNode 包含:

一個(gè)單獨(dú)的 Kademlia 節(jié)點(diǎn),負(fù)責(zé)維護(hù)自己的路由表和分布式哈希表。

用于向其他節(jié)點(diǎn)發(fā)起遠(yuǎn)程過(guò)程調(diào)用的網(wǎng)卡。

用于從其他節(jié)點(diǎn)、Web UI 和文件傳輸接收遠(yuǎn)程過(guò)程調(diào)用的 Sinatra 端點(diǎn)。

用于文件接收、切分和清單文件的創(chuàng)建。謝謝