• 沒有找到結果。

第四章、 研究成果: 系統實作與測試

2、 系統實作

2.6 同步訊息交換

在客戶端應用程式同步模組的程式實作上是非同步模式,其檔案同步訊息交 換機制會新建一個執行緒,其不斷從同步佇列中,取得等候同步的物件,並把物 件內容轉換成 JSON 字串資料格式,對同步伺服器送出同步請求,而客戶端應用 程式會在接收到伺服器端的訊息回應,並決定後續同步動作。本系統在同步訊息 交換的實作上,是使用 Messaging Server 元件的 RabbitMQ 伺服器來做為訊息交 換的中介,其會和 Sync Server 元件部署同一台伺服器上,其安裝及設定如下:

 透過 apt-get install rabbitmq-server 指令來安裝 RabbitMQ 3.2.4 版。

 使 用 rabbitmq-plugins enable rabbitmq_management 指 令 來 啟 用 RabbitMQ 的管理介面網頁。

 使用預設的 guest 帳號登入管理介面,並新增使用者帳號和密碼,設定 成 Administrator 以及給予權限。

完成 RabbitMQ 的安裝設定後,Sync Server 元件上的同步程式會用 Python 的 Pika 套件實作 RabbitMQ 的 Producer,用來發送訊息和 Consumer,用來接收 訊息;Client 元件的 Windows 客戶端應用程式是使用 RabbitMQ .NET Client 套件,

並以.NET C#實作 Producer 和 Consumer,而 Linux 客戶端應用程式亦是使用 Python 的 Pika 來實作,詳細的程式實作參數如表十三。

表 十三:RabbitMQ 客戶端實作參數

名稱 種類 Exchange Type Routing Key

同步程式 Producer response direct 客戶端的唯一識別(clientkey) 同步程式 Consumer request topic user.reg.*.*

req.sync.*.*

sync.cloud.*.*

客戶端程式 Producer request topic user.reg.{userid}.{clientkey}

req.sync.{userid}.{clientkey}

sync.cloud.{userid}.{clientkey}

客戶端程式 Consumer response direct 客戶端的唯一識別(clientkey)

2.7 檔案與資料夾同步

Input userid Input token

http get server file list get local file list

FOR server file in server file list

IF server file is not exist in local file list THEN http download server file to local

ELSE

update local file ENDIF

remove file in local file list ENDFOR

http get server folder last modified time FOR local file in local file list

IF server folder last modified time is greater than local file modified time THEN delete local file

ELSE

add sync object with create operation to sync queue ENDIF

ENDFOR

Web Server 元件入口網站除了提供帳號驗證介面外,在上面也提供了檔案與 資料夾同步的功能,其建立一個名為 home 的 Django App 作為登入後的預設功能 頁面,使用者在網站上操作的檔案與資料夾同步,其檔案清單會直接對應到本系 統伺服器端。當本地端和伺服器端檔案清單維持一致後,使用者異動檔案、資料 夾,在本系統上其同步可以依據同步的方向性來區分為,從本地端同步到雲端、

從雲端同步到本地端兩種以及直接在入口網站同步,此三種情境分別如下所述,

圖四十五為系統同步示意圖。

圖 四十五:系統同步示意圖

( 1 ). 本地端同步到雲端

使用者在 Client 元件,Windows、Linux 本地端的系統監控資料夾內,異動 檔案與資料夾的操作主要可以分為新增、修改、刪除、更名,四種異動事件,此 部分同步流程延續同步訊息交換,客戶端應用程式會新建一個執行緒來不斷接收 同步伺服器所發送的同步訊息,收到其內容包含 Type:readyToSync 後,客戶端 應用程式會根據此四種異動事件有不同的同步動作,把檔案與資料夾同步到本系 統的伺服器上,再由同步伺服器把檔案與資料夾同步到雲端上,詳細四種異動事 件的實作如下所述。

 新增和修改同步動作

本系統的兩階段同步機制,客戶端應用程式會先把本地端檔案同步到 OpenStack Swift 上,而新增和修改 Swift 上的檔案,其 API 都是以 HTTP PUT 的 方法來操作,物件如果不存在則是新增反之則是取代,語法範例如下:

curl -i $publicURL/$uid/Google Drive/helloworld.txt -X PUT -H "Content-Type:

text/html; charset=UTF-8" -H "X-Auth-Token: $token"

語法中的三個參數,Token、使用者 ID(uid)和物件網址,其中的$token 值程式會 從 SQLite 的 Identity 資料表取出使用,$uid 則是使用者 ID 的 MD5 Hash 值而物 件網址則是由$uid 加上檔案路徑所組成,在 Swift 上是沒有資料夾的概念的,檔 案的路徑對於 Swift 來說只是檔案的名稱,例如:使用者在監控資料夾內的 Google Drive 資料夾內的 demo 資料夾中新建一個 test.txt 檔案,客戶端應用程式不需要 先 對 Swift 新 建 demo 資 料 , 而 是 直 接 對 $publicURL/$uid/Google Drive/demo/test.txt 進行 HTTP PUT 方法來新建該 test.txt 檔案。

 刪除同步動作

對 Swift 的刪除動作可以分為,刪除檔案和刪除資料夾。刪除檔案的 Swift API 語法範例如下:

curl -i $publicURL/$uid/Google Drive/helloworld.txt -X DELETE -H "X-Auth-Token:

$token"

由於本地端檔案路徑和 Swift 上的檔案路徑是相同的,所以檔案監控模組取得的 刪除事件的檔案路徑可以直接組成 Swift 上的物件網址,再加上$token 就可以直 接對 Swift 進行 HTTP DELETE 操作。對資料夾進行刪除操作,Swift 有提供 Bulk Delete 功能,即是一次操作刪除多個檔案,其語法範例如下:

curl -i $publicURL/?bulk-delete -X DELETE -H "X-Auth-Token: $token"

此外送出的請求中 HTTP Message Body 還需要條列出刪除檔案的路徑,範例如 下:

$uid/Google Drive/ helloworld.txt

$uid/Google Drive/demo/test.txt

 更名同步動作

對 Swift 的更名動作可以分為,更名檔案和重新命名資料夾。由於 Swift API 沒有提供更名的 API,所以更名的操作是以複製舊檔案到新檔案的路徑,並且把 舊檔案進行刪除操作,其複製的語法範例如下:

curl -i $publicURL/$uid/Google Drive/helloworld.txt -X COPY -H "X-Auth-Token:

$token" -H "Destination: $uid/Google Drive/hello.txt"

其中 Destination 的值是檔案新的路徑,語法中舊檔名 helloworld.txt 變成 hello.txt 表示使用者重新命名了檔案,當複製完成後,接著會在進行刪除 Swift 上舊檔案 API,來進行檔案與資料夾的同步。Sync Server 元件,同步伺服器上的同步程式 是用 Python 來實作,並配合使用了各雲端服務所提供的套件來加速開發,使用 套件與說明如表十四。

表 十四:雲端服務套件與說明

雲端服務 套件 說明

Google Drive oauth2client 和

google-api-python-client 的 MediaInMemoryUpload

使用 oauth2client 驗證 Access Token 取得 Credential 後,透過 MediaInMemoryUpload 同 步檔案與資料夾

Microsoft OneDrive 無 自己實作介接 OneDrive 的 REST API,來完成檔案與

( 2 ). 雲端同步到本地端

從雲端同步到本地端有兩種情境,第一種是使用者異動本地端檔案同步到雲 端時,同步程式同時也會透過 RabbitMQ 發送訊息給該使用者的其他本地端上已 啟動的客戶端應用程式,透過主動通知(Push)的方式,當收到同步訊息內容包含 Type:needToSync 的值,則會自動透過 Swift API 使用 HTTP GET 把檔案同步下 來到本地端相對應的路徑。

第二種雲端同步到本地端的情境則是,使用者直接在雲端上修改經由本系統 同步上去的檔案,而客戶端應用程式會定期檢查本地端監控資料夾內的檔案清單,

再透過雲端服務提供的 HTTP API 定期一分鐘(Polling)去和登入使用者已連結的 雲端服務上的檔案清單做比對,如果雲端上的檔案最後修改時間大於本地端,則 把雲端檔案更新本地端檔案。

在實作上,Linux 客戶端應用程式,由於是使用 Python 進行開發,所以會使 用和伺服器端同步程式相同的套件,參考如表九;Windows 客戶端應用程式存取 Google Drive 會使用 Google.Apis.Drive.v2 套件、對 Dropbox 使用 DropboxRestAPI 套件、對 Microsoft OneDrive 使用 OneDriveRestAPI 套件,存取 Hadoop HDFS 則 自己實作對其 WebHDFS 的 REST API。

( 3 ). 直接在入口網站同步

使用者可以在 Web Server 元件入口網站,透過網頁介面去同步檔案與資料 夾,其功能包含新增、修改、刪除和更名,網站本身不直接提供檔案內容修改功 能,而是需要使用者重新上傳同樣檔案名稱修改後的檔案,網站會判斷為修改同 步事件而不是新增的同步事件。在入口網站上的操作會透本身提供的檔案與資料 夾同步 API 來進行,其會直接對 Swift 上的檔案進行異動,當對 Swift 的檔案異 動成功後,同步 API 也會透過 RabbitMQ 發送同步訊息通知同步程式,其則會進 行後續同步到雲端和通知該使用者的其他本地端應用程式來進行同步。

2.8 檔案權限管理

使用者在 Web Server 元件入口網站可以設定檔案存取權限,透過對網頁上 單一檔案點選 Share 按鈕,對系統 API 的 Share 功能送出 HTTP POST 操作,API 程式會先判斷該檔案是否已經設成公開,如果是則取得該檔案的分享代碼;如果 不是則會使用 Django 的 django.utils.crypto.get_random_string 方法隨機產生一個 15 個字元的分享代碼。最後,從傳入的參數取得檔案名稱,並把兩個變數(分享 代碼、檔案名稱)組合成可以取得檔案的存取網址,回傳給使用者網頁端顯示,

虛擬程式碼如下。

Input filepath

Initialize sharecode to none Initialize sharelink to none

IF file exist in server file list THEN IF file has share code THEN

set sharecode to file share code ELSE

generate 15 char random string set sharecode to the string

update share code in server file list ENDIF

set sharelink to share url + / + sharecode + / + filename ENDIF

RETURN HttpResponse sharelink

入口網站上會建立一個名為 share 的 Django App,作為彙整公開檔案列表網 Content-Disposition,值為 attachment; filename={filename},回傳給使用者網頁 端。