hadoop的資料流分散式處理模型,是分散式運算模型的一種實現,hadoop對海量檔案資料比較適合,但對於很多公司的應用系統而言,基本都是基於資料庫的,並沒有多少檔案資料需要即時分析,就是記錄檔,也可以放在資料庫中,特別是使用者動作記錄(不是系統級日誌),當然,就是存成檔案,格式和內容也基本是確定的,分析的時候並不需要分拆和Map.其實只要一個簡單的分布式分析(reduce)即可。因此模型上沒必要搞得像hadoop那麼複雜(雖然說hadoop原理和實現也不是很複雜).何況大部分應用系統需要分析的資料還達不到這個層級.
考慮到一般的公司應用的即時資料存放都是確定的,也就是分析資料的來源基本是確定的,絕大部分的分析任務都會關顧所有的資料節點,因此也沒必要把調度服務搞得很複雜。模型可以進一步簡化。分散式運算的關鍵點其實就在於分析代碼的部署和管理、分布計算調度和執行、結果合并等。
首先,對於分散式運算代碼的自動部署其實很簡單,可以利用dotnet的wcf,(用 socket也可以,但用代碼wcf簡單,效率吧也不會差多少,如果用socket就看寫的人功底了).用wcf來傳送命令,同時傳送要執行任務的代碼(代碼量一般都不大,直接用byte數組就完全夠了),代碼部署服務接到代碼後可按照自己設定的規則來存為計算節點上的代碼。
其次對於分散式運算的執行,可以利用dotnet的應用程式定義域和程式集動態載入技術來完成,其實我覺得dotnet的這個架構還是非常好的,將使用者任務代碼放在自己的應用程式定義域中來執行比在宿主程式主應用程式定義域中採用線程來執行要安全很多(當然也可以體外執行,但可控性會小很多),不會影響宿主應用本身,使用者代碼之間也會有更好的隔離性,對資源的消耗也小很多,而且是同一進程,也有利於主應用程式監控執行過程和擷取執行結果。同時還可以彌補程式集載入後不能卸載的DotNet架構的缺點(其實也不能完全說是缺點,畢竟程式集載入後,可能很多其它地方都在應用該程式集,你卸載它勢必會造成一些問題,而整個應用程式定義域卸載,由於其在程式集上的獨立性,就不會有什麼問題產生,比較安全,而且易於實現)。
對於分散式運算的調度,由於這種基於資料庫的應用資料來源節點都比較確定,用全部都執行和使用者任務指定節點執行兩種方式就可以了,這就免除了基於負載情況的複雜調度模式。結果合并了邏輯可由客戶代碼自己完成,只是由宿主程式來執行(宿主是對等的,就是計算節點,但合并只在接受計算工作要求的節點執行)。中間的分散式運算結果我覺得介面上都採用字串來進行,這個字串怎麼解釋交給使用者代碼自己決定(實體類結果可以序列化成字串,回來後可以還原序列化回去,字串可以達到4G,如果不行採用檔案流也可以,但一般情況下字串就足夠了)。
雖然上面說計算節點是對等的,但有個問題就是如何解決一個節點知道其它節點的問題,如果每個節點都探測其它節點,這當然不是有效率的。我採用的方法是選一台比較好的伺服器做master,規定服務地址,由該節點維持一個其它節點的狀態。但這種狀態資訊也沒必要持久化(其它節點反而可以持久化,好處是master掛掉還是可以繼續工作)。其它節點啟動後每隔一段時間就會向Master發送自己的狀態,並向這個節點擷取其它節點資訊。再擷取這些節點資訊後,節點還是會相互之間更新狀態(不是必須的),如果Master掛掉後,這些節點由於儲存有其它一些節點的資訊,還是可以工作,當然新起來的節點還是會受到影響,而Master重新起來後,其它節點就會把自己的狀態註冊進來,因此Master只是起到一個簡化探測的橋樑作用。這些heartbeat訊息我也是採用wcf實現,只不過使用的是一次性服務(不是接聽模式和雙工模式).
整體過程如下: 使用者基於提供的計算合并介面(兩個介面)開發一個或多個自己的計算類,並編譯成程式集代碼,然後將該程式集代碼作為參數(位元組流)調用部署服務將代碼,調用成功後,就可以調用執行服務代碼(也可以把代碼放在這裡做為參數傳入),代碼並不需要每次都部署,系統會按一定規則尋找原先部署的代碼來完成計算,分散式運算完成後,服務將結果反饋給使用者(可非同步和同步).當然執行的時候需要指定計算類.
安全在服務層做(邊線),內部節點間請求可採用網卡物理地址認證,所有的請求都進行AES加密,並用時間戳記和內部執行序列完成重複請求和偽造請求的安全認證,當然一般情況下沒必要,因為這個系統是運行在內部的.使用者代碼安全可在應用程式定義域建立的時候通過控製程序域的安全參數來完成.
其實基於以上分散式運算模型,不僅可以做即時分析,也可以做電腦管理等,而且可以隨時動態增加功能,動態升級,一次部屬(節點Host程式),當然,如果搞點其它技術,就是一個超級病毒。
主要技術點:應用程式定義域,程式集動態載入,泛型,類的動態執行個體化,WCF(服務,自建宿主,動態調用代理),多線程(分發執行時),介面(分散式運算執行介面).
大家可以去實現一下,其實做進去就沒這麼難了,在這個基礎上再類比做MapReduce就很簡單了.
補充(2012-02-08):真正做的時候細節需要處理的地方還是很多,就是調試也需要技巧的,因為很多地方都需要用多線程實現非同步呼叫。當然,WCF的安全和序列化問題,也耗費了不少時間,WCF報錯很多時候都比較籠統,加上有時正常有時異常,使得追蹤分析錯誤很困難。如果大家做的過程中遇到這些問題,可以參考我後面寫的部落格,可以少走些彎路。