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

C# 遠端執行與分散式計算:從 Remoting 到任務伺服器實作

     編輯:關於C#

前言:跨應用程式域的物件呼叫藝術

.NET Remoting 是早期 .NET Framework 提供的分散式物件通訊基礎設施,雖然已被 WCF/gRPC 取代,但其核心概念——應用程式域隔離、通道與格式化器、激活模式、序列化邊界——對理解現代微服務架構、Actor 模型、甚至 Blazor WebAssembly 的 JS 互操作仍具啟發意義。本文深度解析 Remoting 兩種傳遞模式(ByRef/ByValue),並實作一個功能完整的分散式任務伺服器。

核心架構圖解

┌─────────────┐     TCP Channel (8085)      ┌─────────────┐
│  Client     │ ◄─────────────────────────► │  Server     │
│  AppDomain  │  1. Register Channel        │  AppDomain  │
│             │  2. Activator.GetObject     │             │
│  - ITask    │  3. Proxy → Remote Call     │  - TaskRunner (MarshalByRefObject) │
│  - ClientTask (Serializable)              │  - Singleton │
└─────────────┘                             └─────────────┘
       ▲                                            │
       │         ByValue: Serialize entire object  │
       │         ByRef:  Proxy → remote invocation │
       └────────────────────────────────────────────┘

兩種遠端物件傳遞模式深度對比

維度ByRef (MarshalByRefObject)ByValue ([Serializable])
物件實際位置永遠駐留在伺服器 AppDomain序列化後傳輸至客戶端 AppDomain
方法執行端伺服器端客戶端本地
網路往返每次呼叫皆跨網路僅傳輸時跨網路
狀態共享天然共享 (Singleton)各客戶端擁有獨立副本
適用場景資源密集型服務 (DB連線、硬體控制)計算密集型任務、資料傳輸物件 (DTO)
序列化需求僅 Proxy 需序列化整個物件圖必須可序列化

任務伺服器完整實作

1. 契約介面 (ITask.dll)

namespace TaskServer
{
    public interface ITask
    {
        object Run();           // 執行核心邏輯,回傳結果物件
        string Identify();      // 任務描述,供日誌/監控使用
    }
}

2. 伺服器端執行器 (TaskRunner.dll) - ByRef 物件

namespace TaskServer
{
    public class TaskRunner : MarshalByRefObject
    {
        private ITask _remoteTask;

        public string LoadTask(ITask task)
        {
            if (task == null) return "[e] Task reference is NULL.";
            _remoteTask = task;
            Console.WriteLine($"[i] Task loaded: {_remoteTask.Identify()}");
            return "[i] Task loaded. Welcome to the All Powerful TaskServer.";
        }

        public object RunTask()
        {
            Console.WriteLine("[i] Running task on server...");
            object result = _remoteTask.Run();
            Console.WriteLine("[i] Task finished.");
            return result;  // 結果物件需 [Serializable] 才能回傳給客戶端
        }
    }
}

3. 伺服器啟動引擎 (TaskServerEngine.exe)

public class TaskServerEngine
{
    public static void Main()
    {
        Console.WriteLine("The All Powerful Task Server!");
        TcpChannel chan = new TcpChannel(8085);
        ChannelServices.RegisterChannel(chan, false);  // false = 不加密

        Type runnerType = typeof(TaskRunner);
        RemotingConfiguration.RegisterWellKnownServiceType(
            runnerType, "TaskServer", WellKnownObjectMode.Singleton);

        Console.WriteLine("[i] Task Server started on tcp://localhost:8085/TaskServer");
        Console.ReadLine();  // 保持執行
    }
}

4. 客戶端任務實作與呼叫 (TaskClient.exe)

[Serializable]
public class ClientTask : ITask
{
    private int _a, _b;
    public ClientTask(int a, int b) { _a = a; _b = b; }

    public object Run() => _a * _b;  // 複雜計算邏輯放這裡

    public string Identify() => $"MultiplyTask: {_a} × {_b}";
}

public class Client
{
    public static void Main()
    {
        TcpChannel chan = new TcpChannel();
        ChannelServices.RegisterChannel(chan, false);

        TaskRunner runner = (TaskRunner)Activator.GetObject(
            typeof(TaskRunner), "tcp://localhost:8085/TaskServer");

        ClientTask task = new ClientTask(100, 100);
        string loadMsg = runner.LoadTask(task);      // ByValue 傳遞任務物件
        Console.WriteLine($"Server: {loadMsg}");

        object result = runner.RunTask();            // 遠端執行,結果 ByValue 回傳
        Console.WriteLine($"Result: {result}");      // 10000
    }
}

5. 編譯與執行順序 (關鍵依賴關係)

csc /target:library /out:ITask.dll ITask.cs
csc /target:library /out:TaskRunner.dll TaskRunner.cs /r:ITask.dll
csc /out:TaskServer.exe TaskServerEngine.cs /r:ITask.dll /r:TaskRunner.dll
csc /out:TaskClient.exe Client.cs /r:ITask.dll /r:TaskRunner.dll

進階主題:分散式計算擴展方向

非同步執行與回調

// ITask 擴展
public interface IAsyncTask : ITask
{
    IAsyncResult BeginRun(AsyncCallback callback, object state);
    object EndRun(IAsyncResult ar);
}

// 客戶端不阻塞等待
IAsyncResult ar = runner.BeginRunTask(callback, null);

任務優先佇列與負載平衡

  • 伺服器端維護 PriorityQueue<ITask>
  • 多個 TaskRunner (SingleCall 模式) 形成 Worker Pool
  • 引入 Heartbeat 機制監控 Worker 健康度

安全性強化

  • 通道加密:new TcpChannel(8085, null, new BinaryServerFormatterSinkProvider { TypeFilterLevel = TypeFilterLevel.Full })
  • 自訂 IServerChannelSinkProvider 實作 Token 驗證
  • 限制序列化型別:BinaryFormatter.Binder = new SafeSerializationBinder()

從 Remoting 到現代架構的演進

Remoting 概念現代對應技術關鍵差異
AppDomain 隔離Process/Container 隔離更強隔離,跨機器部署
MarshalByRefObjectgRPC Service / Web API Controller契約優先,語言中立
[Serializable] ByValueProtobuf/JSON DTO版本容忍,跨平台
Singleton/SingleCallSingleton/Scoped/Transient (DI)生命週期由容器管理
BinaryFormatterSystem.Text.Json / Protobuf安全、高效、標準化

總結

.NET Remoting 雖已退役,但其「透明遠端呼叫」與「物件遷移語意」的設計哲學,深刻影響了後續的 WCF、.NET Remoting (Core 3.0+ 移除)、gRPC、Orleans Actor 框架。掌握 ByRef/ByValue 邊界、序列化陷阱、激活模式選擇,能幫助開發者在微服務拆分、分散式任務佇列、邊緣計算等現代場景中做出正確的架構決策。本文實作的任務伺服器雖簡單,卻完整展示了「計算遷移至資源端」的分散式計算核心價值。

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