首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

TPL:打造任務並行執行的水平擴展架構

     編輯:關於.NET

前言:從垂直擴展到水平擴展

.NET Framework 4 引入的任務並行庫 (TPL) 讓開發者能輕鬆利用多核心處理器的並行運算能力。然而,單機垂直擴展(增加核心數)往往受限於成本、硬體插槽限制或主機託管環境的約束。當單一伺服器的運算資源觸及天花板時,將計算負載分散到伺服器叢集中,實現水平擴展,便成為必然選擇。雲端託管環境正是此類架構的典型應用場景。

本文將構想一套完整的概念性解決方案,結合 .NET Framework 4.5 的新特性(如 WebSockets 雙向通訊、MEF 無屬性註冊、TPL 資料流等),展示如何打造一個具備水平擴展能力的分散式任務執行平台。

核心架構:三大邏輯層

整個系統由三個核心邏輯層組成,各司其職,透過雙工通訊協同工作:

  • 遠端任務客戶端:客戶端介面層,封裝分散式環境的複雜性,提供類似本地 TPL 任務的 API 體驗。
  • 任務協調器:系統的唯一入口點,負責接收請求、實施節流與佇列機制、管理任務生命週期,並透過回呼通道將執行狀態即時推送回客戶端。
  • 任務執行節點:實際承載 TPL 任務執行的工作節點,部署在負載平衡器後方,可動態增減以實現水平擴展。

資訊流向:客戶端提交請求 → 協調器節流佇列 → 分派至執行節點 → 執行節點透過回呼更新協調器 → 協調器推送狀態至客戶端。

水平擴展任務架構圖

關鍵技術實現細節

1. 雙工通訊與 WebSockets

為了實現「伺服器主動推送進度」的需求,架構採用 WCF 雙工合約。.NET 4.5 引入的 NetHttpBinding 原生支援 WebSockets 傳輸(需 Windows 8 以上環境),大幅降低了雙向通訊的實作門檻,避免了傳統輪詢的資源浪費。

2. 客戶端:TaskCompletionSource 解耦請求與回應

RemoteTaskClient 類別是客戶端的核心。它利用 TaskCompletionSource<TResult> 建立「未完成的任務」,將每個提交請求對應到一個 ClientRequestInfo 物件,內含唯一 ID、任務類型、參數及 TaskCompletionSource。當協調器透過回呼通道回報狀態(完成、取消、錯誤)時,CallbackHandler 即可精準地喚醒對應的 Task,讓呼叫端能以同步或非同步方式(Task.WaitAll, await)處理結果。

// 核心邏輯片段
internal class ClientRequestInfo<TResult> {
    internal STask TaskExecutionRequest { get; set; }
    internal TaskCompletionSource<TResult> CompletionSource { get; set; }
    // ...
}

// 回呼處理器
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
class CallbackHandler<TResult> : ITaskUpdateCallback {
    public void UpdateStatus(string id, STaskStatus status, object result) {
        if (_requests.TryRemove(id, out var info)) {
            switch (status) {
                case STaskStatus.Completed: info.CompletionSource.SetResult((TResult)result); break;
                case STaskStatus.Canceled: info.CompletionSource.SetCanceled(); break;
                case STaskStatus.Faulted: info.CompletionSource.SetException((Exception)result); break;
            }
        }
    }
}

3. 協調器:節流與佇列的藝術

協調器是系統穩定性的守門人。單純的「收到即轉發」會導致兩大風險:單一大批次請求佔滿單一節點(負載不均),以及尖峰負載耗盡節點資源(記憶體、CPU)。

解決方案引入三層節流語意:

  • maxSTasksPerRequest:限制單次分派給節點的任務數,配合負載平衡器分散壓力。
  • maxNumberOfTasks:全域並行任務上限,防止資源耗盡。
  • maxNumberOfTasksByType:按任務類型限流(如 CPU 密集型 vs I/O 密集型),實現資源隔離與公平調度。

配合 ConcurrentQueue<STaskInfo> 作為線程安全的請求佇列,一個獨立的 Submitter 背景任務(基於 async/await 週期性運行)依據上述規則從佇列取出任務分派,若觸及類型限流則將任務重新入佇,確保各類任務皆有執行機會。

// 節流核心邏輯
internal static List<STaskInfo> GetTasksFromRequestQ() {
    var ret = new List<STaskInfo>();
    for (int i = 0; i < maxSTasksPerRequest; i++) {
        if (currentTotalCount + i == maxNumberOfTasks || !_requestQ.TryDequeue(out var info))
            return ret;
        if (currentTypeCount == GetMaxNumberOfTasksByType(info.ClientRequest.STaskTypeName)) {
            _requestQ.Enqueue(info); // 重新入佇,讓位給其他類型
        } else {
            ret.Add(info);
        }
    }
    return ret;
}

4. 執行節點:MEF 動態發現與取消權杖傳遞

任務執行節點不硬編碼任務邏輯,而是透過 MEF (Managed Extensibility Framework) 掃描 extensions 目錄,動態載入實作 IRunnableTask 介面的組件。.NET 4.5 的 RegistrationBuilder 支援無屬性註冊,部署新任務只需放入 DLL 即可,無需重啟服務。

任務啟動時建立 CancellationTokenSource 並註冊到字典,支援協調器轉發的取消指令。任務本體與續續任務結合:前者執行業務邏輯,後者負責捕獲結果/異常並透過回呼通道更新協調器,最後清理取消權杖資源。

5. 取消機制的全鏈路串聯

從客戶端 CancellationToken.Register → 協調器 CancelTask 服務操作 → 尋找對應節點通道 → 節點 Cancel 操作 → 觸發 CancellationTokenSource.Cancel() → 任務內部 ThrowIfCancellationRequested 拋出 OperationCanceledException → 續續任務捕獲並回報 Canceled 狀態。全鏈路無阻塞,符合 TPL 取消模式最佳實踐。

擴展性考量與總結

本文架構假設協調器為單點,若需協調器本身高可用,需引入負載平衡器,並將節流計數器外部化至分散式快取或資料庫(如 Redis、SQL Server),同時處理分散式一致性與競爭條件。此外,Microsoft HPC Pack 等成熟產品亦可作為替代方案評估。

TPL 提供了單機並行的堅實基礎,配合 WCF 雙工、MEF 組合、非同步佇列節流等企業級模式,我們得以跨越機器邊界,構建出既能榨乾多核 CPU、又能彈性擴展叢集的分散式計算平台,為批次處理、工作負載自動化等場景提供強大引擎。

程式碼範例下載: https://archive.msdn.microsoft.com/mag201210TPL

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved