• 沒有找到結果。

第四章、 系統實作

4.2 實作內容

4.2.2 Super Seeder

而當 Super Seeder 回復到可服務的狀態後,會從自己的 MDS Server List 去連線登入系統,並且等待提供服務。

3.4.2.2 Super Seeder 只有跟 MDS Client 連線

另一種狀況是 Super Seeder 只有跟 MDS Client 連線,如下圖 3-14 所示:

圖 3-14

此狀況由於 MDS Server

能夠繼續提供檔案傳輸服務,對於此狀況伺服端元件並無做相關的處 理。

30

Super Seeder 只有跟 MDS Server 連線

MDS Server 與 Super Seeder 保持連線,所以仍然 能夠繼續提供檔案傳輸服務,對於此狀況伺服端元件並無做相關的處 保持連線,所以仍然 能夠繼續提供檔案傳輸服務,對於此狀況伺服端元件並無做相關的處

31

第四章、系統實作

本章節將會說明系統上實作的所有細節,包含程式架構以及實作 的內容。

4.1 程式架構

在程式架構上,由於 MDS Server、Super Seeder 皆由過去巨 量檔案發佈系統承接而來,主要的程式架構仍是以滿足大量的下載需 求為主,而 MDS Server 與 Super Seeder 均會承載大量的連線與封 包處理,因此繼續延用較高的 I/O 架構。以過去的網路程式而言,處 理同時連線 (Concurrent connections) 的網路程式皆會使用

select() 系統呼叫[8],達到快速處理多個 socket 的能力。然而在大部 分的系統中,為了不讓 select() 超過其能負載的範圍,皆定義了 FD_SETSIZE 這個巨集常數來限制其能力,以 FreeBSD 與 Linux 來說,

其值為 1024。也就是說,select() 最多只能夠同時處理 1024 個 socket,這對於大量連線的巨量檔案發佈系統並不足夠。

而還有另一種 poll() 系統呼叫[9],雖然沒有限制最大能處理的 socket 數目,但實際上當連線的數量達到兩千個左右的連線數時,

速度便相當慢了,原因在於掃瞄每個 socket 需要花費大量時間。

因此,FT-MDS 延續過去 MDS 必須使用快速處理超大量 socket,

32

且反應速度夠快的系統呼叫。在著名的 The C10K Problem[10] 網頁 中,提出了種種的 I/O 處理策略,我們這次依然選擇 Event-Driven 的方式,並使用 Non-blocking I/O (非阻塞式 I/O) 以及 Readiness Change Notification (就緒狀態改變通知) 的高效能系統呼叫:

FreeBSD 的 kqueue()[11] 以及 Linux 的 epoll()[12]

在 MDS 的處理連線核心中而為了讓程式能夠跨平台,我們使用 了 libevent 這套 Open Source 開放原始碼函式庫[13]。libevent 在編 譯函式庫時,能針對編譯的系統環境,選擇效能最佳的系統呼叫,像 在 FreeBSD 的 kqueue()、Linux 的 epoll()、Solaris 的 /dev/poll[14]

與 event ports[15],以及傳統的 select() 與 poll()。因此,我們的程 式可以在不修改程式碼的情況下,輕鬆地在多個平台上編譯、執行。

此外,libevent 作者採用 BSD License (3-clause BSD License) 授權協議[16],若將 MDS 運用於企業內,便不易產生侵犯授權爭議。

這也是使用 libevent 的優點之一。

4.2 實作內容

MDS Server 與 Super Seeder 以 C++ 實作而成,是一個 single-threaded 的單一執行緒程式,並且以 single-process 單一程

33

序服務所有連線。由於 MDS Server 與 Super Seeder 皆為需處理大 量同時連線的程式,因此兩者共用相同、使用 libevent[13] 撰寫的程 式核心。目前 MDS Server 與 Super Seeder 已在下列系統中測試:

 FreeBSD 7.0-Release (amd64 64bit)

 Debian Linux 2.6.18 Release 4.0 (i386 32bit)

因程式在 UNIX 環境執行運作,所以兩者皆設計以 daemon process 在系統背景執行,透過指令稿與額外的控制程式,發送 POSIX Signal 來控制 MDS Server 與 Super Seeder 進行啟動、停止、

重新啟動、回報狀態等動作。並使用 syslog 服務記錄程式輸出的訊 息,使其和 UNIX 系統整合,提高使用便利性。

以下說明針對 MDS Server 及 Super Seeder 個別的實作問題與 解決方法。

4.2.1 MDS Server

MDS Server 在系統中扮演中樞控制的角色,提供 Super Seeder、

MDS Client 登入,傳送所需資訊,並維護其清單以及控管簡易的負 載平衡數值等功能。

34

以下介紹與系統穩定度相關的 Super Seeder 與 MDS Client 狀 態維護,清除已發生問題之 Super Seeder 與 MDS Client 所設計的 KeepAlive[17] 機制。

4.2.1.1 Super Seeder 與 MDS Client 狀態維護

Super Seeder 除了在登入時會傳送其服務資訊給 MDS Server 外,在運行的過程中,也會定時傳送 Report 資訊給 MDS Server,

內容為負載 (loading)、每秒處理幾個片段要求 (requests/sec) 以 及頻寬使用率 (bandwidth usage)。MDS Server 會依照目前所有 Super Seeder 的負載狀況,來決定要指派哪一個 Super Seeder 給 MDS Client。

而 MDS Client 在登入時會傳送 NAT[18][19][20] 與頻寬測試資訊以 及目前狀態。其狀態分為兩種:

 已完成所有 File 片段 (Seeder)

 未完成所有 File 片段 (Leecher)

當 MDS Client 開始或繼續下載一個新發佈的 File 時,狀態為

35

Leecher;而當 MDS Client 完成所有 File 片段時,會傳送已完成資 訊給 MDS Server,讓 MDS Server 更新此 MDS Client 的狀態。

MDS Client 狀態不同,在挑選、組合 MDS Client List 時的策略 也有所不同。例如:當某個 MDS Client 已經成為 Seeder 後,MDS Server 就不需要再給它內含 Seeder 的 MDS Client List,因為它已 經不需要其他 MDS Client 傳送 File 片段給它。MDS Server 這時會 給他全部都是 Leecher 的 MDS Client List,讓它盡全力去傳送 File 片段;而在 MDS Client 仍是 Leecher 時,MDS Server 會給它一部 份 Seeder、一部份 Leecher 的 MDS Client List。除了讓它能和 Seeder 們要求 File 片段外,也能和其他 Leecher 交換彼此沒有的 File 片段。

4.2.1.2 KeepAlive 機制

在經過一段時間的運作後,總是會發生一些例外狀況,如 Super Seeder 所在的伺服器當機,或者某 MDS Client 所在的使用者電腦 無預警斷電,甚至是某一家 ISP 業者發生網路故障等。這些會造成不 正常斷線、甚至不知道有沒有斷線的狀況,導致 MDS Server 沒有偵 測到 Super Seeder、MDS Client 的離開,而繼續維護其狀態。

36

這些不正確的狀態資訊,會讓其他 MDS Client 取得不可用的 Super Seeder 與 MDS Client List,因此要設法讓 MDS Server 知道 每個 Super Seeder、MDS Client 是否真正存活。

在這邊,我們讓 MDS Server 記錄 Super Seeder 與 MDS Client 最後傳送資訊的時間戳記 (timestamp),並定時檢查目前時間與該 時間戳記的差值。超過預定的時間 (如 600 秒) 時,發送 KeepAlive 封包,並期待回傳 KeepAlive Acknowledge 封包。若一段時間過後 仍未收到 KeepAlive Acknowledge,則判定對方已發生問題,MDS Server 將主動切斷連線,並釋放其所使用資源。不使用 TCP Socket Option 中的 SO_KEEPALIVE[17] 選項,是因為此機制需要 2 小時內 皆沒有任何傳輸,才會發出探測封包。兩小時是相當久的時間,若同 時有許多 MDS Client 發生問題,對系統的效能會有相當大的影響。

雖然有方法能夠更改此時間,但各種平台上上的支援程度並不相同,

因此決定自行實作。

4.2.2 Super Seeder

Super Seeder 為系統中最為忙碌的元件,需要不停地處理來自 MDS Client 的 File 片段請求,並回傳該片段給 MDS Client。Super

37

Seeder 與 MDS Client 之間的行為參考自 BitTorrent 協定[13],含有 一系列的狀態與資料封包格式。而為了保持 Super Seeder 的穩定,

以及定時回報狀態給 MDS Server 外,也需要控制其輸出的頻寬。以 下將說明 Super Seeder 如何與 MDS Client 通訊、並靈活地回報狀 態給 MDS Server,以及如何控制輸出頻寬。

4.2.2.1 與 MDS Client 通訊

BitTorrent 協定主要用於交握、確認已有 File 片段、以及要求 File 片段、傳遞 File 片段。各封包有其順序,依序如下:

1. Handshake:

Super Seeder 與 MDS Client 之間傳送的第一個封包,內含軟 體版本資訊及目前所使用 File Signature 的一組雜湊值 (hash)。

我們將原本 BitTorrent 的 Handshake 擴充,額外加入發送端的 NAT 類型與頻寬,未來可利用此資訊進行更細微的最佳化。此 封包由 MDS Client 主動送出,Super Seeder 收到後回傳自己 的 Handshake 封包,完成交握。

2. BitField:

BitField 內記載發送端所擁有的 File 片段資訊,一個 bit 表示一

38

個片段。Super Seeder 在完成交握後,將傳送每個 bit 都是 1 的 BitField 封包給 MDS Client,告知對方自己擁有全部 File 片 段。

3. Interested:

此封包由 MDS Client 發出,表示想要從 Super Seeder 下載 File 片段。

4. UnChoke / Choke:

Super Seeder 收到來自 MDS Client 發出的 Interested 後,可 選擇回覆 UnChoke 或 Choke。UnChoke 表示同意 MDS Client 開始請求 File 片段;而 Choke 表示禁止 MDS Client 請求 File 片段。此機制是 BitTorrent 協定中用來控制傳輸的,有一套 Choking Policy 來控制。然而 Super Seeder 在目前的設計中,

是公平傳送 File 片段給每個發出要求的 MDS Client 的,因此當 Super Seeder 收到 Interested 封包時,一律回覆 UnChoke,

讓 MDS Client 能夠來請求 File 片段。

5. Request:

MDS Client 發出的 File 片段請求,內含片段編號 (piece number)、開始位置 (offset) 以及長度 (length)。雖然將 File 分成若干片段來傳送,但實際上每次請求的長度,才是真正在網

39

路上傳送的大小。在我們的系統中,長度均為 16384 Byte (16 KB)。

6. Piece:

Super Seeder 傳送給 MDS Client 的 File 片段,內含片段編號 (piece number)、開始位置 (offset) 以及長度 (length),最後 接上 File 片段資料。MDS Client 可從封包內容得知自己已經收 到了哪一個片段的部分內容。

每一個 MDS Client 與 Super Seeder 皆需經過上述封包流程,

在開始發送 Request 片段請求後,便不停地重複此步驟,直到完成 所有 File 片段。在完成所有 File 片段、成為 Seeder 之後,便會主動 與 Super Seeder 斷線。

4.2.2.2 狀態回報

為了精確監控 Super Seeder 的運作狀況,每一秒鐘便會執行一 個用來統計資訊的函式,而每執行五次此函式,便會將這五次所統計 資料的平均值,傳送給 MDS Server。內容含有負載 (loading)、每 秒處理幾個片段要求 (requests/sec) 以及頻寬使用率 (bandwidth usage)。

40

若 Super Seeder 目前並不忙碌,每五秒傳送一次 Report,便 顯得有點浪費了。因此我們設計了一個閒置計數器,此計數器數值越 大,表示 Super Seeder 越不忙碌。藉由此計數器,可以讓 Super Seeder 在忙碌的時候,每五秒便傳送一次 Report 給 MDS Server,

以即時監控狀態;而在漸漸不忙碌的時候,拉長傳送 Report 的時間 間隔;直到完全不忙碌的時候,傳送幾次 Report,讓 MDS Server 維護的 Super Seeder 狀態符合現況後,便停止傳送 Report。

4.2.2.3 控制輸出頻寬

MDS 系統的目的之一,便是讓使用此系統的公司、企業,能夠 降低頻寬上的花費。倘若 Super Seeder 不限制輸出,讓系統持續佔 用頻寬直到滿載,便失去使用 MDS 的意義。因此,讓 Super Seeder 能夠有效地控制輸出頻寬,是相當重要的。

由於傳送給 MDS Client 的 File 片段為主要輸出項目,且長度也 比通訊用封包長了許多倍,為了不影響其他通訊,輸出控制只針對傳 送 File 片段所用的 Piece 封包。

41

Super Seeder 控制輸出頻寬的步驟流程如下:

1. 設置一輸出計數器,初始值為零。

2. 每當送出一個 Piece 封包時,便累加其長度於輸出計數器。

3. 當寫入事件發生時,檢查輸出計數器,若小於預先設定的頻 寬限制大小,便寫入 Socket;若大於,則不寫入 Socket,

並將此連線暫停,使其不會再發生,並將其儲存至一清單。

4. 每一秒將輸出計數器列印到記錄檔,並將輸出計數器歸零,

然後將步驟三中,儲存在已暫停連線物件清單內,每一個連 線啟動。由於輸出計數器已歸零,下次發生寫入事件時,若

然後將步驟三中,儲存在已暫停連線物件清單內,每一個連 線啟動。由於輸出計數器已歸零,下次發生寫入事件時,若

相關文件