因為是類比和實驗,很多地方我都沒有做得很完善,能省則省了,因為我採用的是對等結構,這裡講一下計算節點的結構,一個計算接點包含三個基本的功能:
1)外部任務要求管理:負責接收外部請求的計算任務,並根據客戶提供的路由資訊,轉寄給目標計算節點的內部工作要求管理功能;
2)內部工作要求管理:負責接收計算節點發過來的任務或命令,並調用本地的任務執行功能;當然。
3)任務執行管理:這個負責具體的任務執行,包括代碼部署,代碼執行等.由於代碼的載入執行涉及到安全和卸載的問題,如果對客戶的代碼採用宿主外建立進程來執行,雖然可以解決代碼執行完後的清場問題,但控制和通訊都比較麻煩,而且不利於客戶代碼利用宿主提供的服務;但如果直接在宿主進程中執行,就會引發安全問題(使用者代碼可以訪問整個進程空間,而線程是沒有隔離功能的),而且執行完後,使用者的代碼也沒法卸載。因此,為了簡化問題,這裡利用了CLR的應用程式定義域(AppDomain)管理功能,可以相對比較完美的解決上述問題。
除了上述三個基本的功能外,計算節點還包括心跳服務,由於節點多了後,如果每個節點都向對方發布心跳資訊,效率當然是非常低下的,因此這裡我簡單的設定了一個中心節點(相當於Master節點),大家都向中心節點發,然後從中心節點擷取其它節點的狀態。這種方式下,如果中心節點掛了,影響肯定非常大。但實際上要解決這個問題,可以設定2-3個這樣的中心節點,如果第1個掛了,第2個中心節點就承擔這種狀態轉寄的責任。
每個節點由IP,連接埠和服務名唯一確定,但為了簡化管理,用IP和連接埠唯一確定一個節點,每個節點的服務名保持一致會比較好。
節點間的通訊,我直接用的是WCF,當然,自己寫這一層也是可以的,不過我覺得沒必要。
下面來看一下外部任務要求管理:
1)對外服務介面:
/// <summary> /// 用於提供給客戶進行公用服務. /// </summary> [ServiceContract(ProtectionLevel= System.Net.Security.ProtectionLevel.None)] public interface IComputingService { /// <summary> /// 任務程式集部署服務 /// </summary> /// <param name="TaskCommd"></param> /// <returns></returns> [OperationContract] List<ExecResult> DeployTaskAssembely(TaskCommand TaskCommd); /// <summary> /// 任務或命令執行服務,並進行結果合并。 /// </summary> /// <param name="TaskCommd"></param> /// <returns></returns> [OperationContract] ExecResult ExecuteTaskCommand(TaskCommand TaskCommd); /// <summary> /// 任務或命令執行服務,但不合并結果. /// </summary> /// <param name="TaskCommd"></param> /// <returns></returns> [OperationContract] List<ExecResult> ExecuteTaskCommandEx(TaskCommand TaskCommd); /// <summary> /// 提供在執行的計算命令查詢服務 /// </summary> /// <returns></returns> [OperationContract] List<CalcCommand> GetCalcCmmds(); /// <summary> /// 提供當前家在的資訊清單服務 /// </summary> /// <returns></returns> [OperationContract] List<CalcCommand> GetCurrAssemblies(); /// <summary> /// 擷取計算節點資訊服務 /// </summary> /// <returns></returns> [OperationContract(ProtectionLevel = System.Net.Security.ProtectionLevel.None)] List<CalcNodeInfo> GetCalcNodeInfos(); // TODO: 在此添加您的服務作業 }
這是對外服務,相應的用戶端調用代理在DCSComputingSvcProxy類中實現。對於對外請求任務管理,核心的實現在DCSComputingDispather類中.
這個類負責根據使用者提供的路由資訊將任務轉寄到目標計算節點或者調用本地內部請求任務管理來執行自己該負責的任務。這些代碼太長,就不貼了,關鍵技術點就是多執行緒。
內部請求任務管理的對計算節點服務介面如下:
/// <summary> /// 內部分散式運算服務,不對外公開. /// </summary> [ServiceContract] public interface IDistributedComputingService { /// <summary> /// 任務代碼部屬服務 /// </summary> /// <param name="CalcCommd"></param> /// <returns></returns> [OperationContract] ExecResult DeployTaskAssembely(CalcCommand CalcCommd); /// <summary> /// 任務執行服務 /// </summary> /// <param name="CalcCommd"></param> /// <returns></returns> [OperationContract] ExecResult ExecuteTaskCommand(CalcCommand CalcCommd); /// <summary> /// 提供當前節點正在執行的命令的清單服務 /// </summary> /// <returns></returns> [OperationContract] List<CalcCommand> GetCalcCmmds(); /// <summary> /// 擷取當前資訊清單服務 /// </summary> /// <returns></returns> [OperationContract] List<CalcCommand> GetCurrAssemblies(); /// <summary> /// 計算節點資訊清單. /// </summary> /// <returns></returns> [OperationContract] List<CalcNodeInfo> GetCalcNodeInfos(); /// <summary> /// 服務節點註冊。 /// </summary> /// <param name="NodeInfo"></param> /// <returns></returns> [OperationContract] string RegisterCalcNodeInfo(CalcNodeInfo NodeInfo); }}
功能上跟對外服務類似,但簡單很多。
明天繼續...