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

WCF 實例模式深度解析:PerCall、PerSession、Single 生命週期與適用場景

     編輯:關於.NET

WCF InstanceContextMode 決定服務實例的建立時機、生命週期與共享範圍,是服務設計的核心決策之一。三種模式各有優劣,需根據業務特性選擇。

三種實例模式比較

模式建立時機銷毀時機狀態共享範圍典型用途
PerCall每次呼叫前呼叫結束後無 (每呼叫獨立)無狀態、高併發、可擴展服務
PerSession (預設)Session 建立時Session 結束時Session 內共享有狀態商務流程、購物車、精靈嚮導
Single服務啟動時 (首次呼叫)服務關閉時全域共享 (所有呼叫者)快取、計數器、單例資源管理

完整程式碼範例

PerCall 模式

[ServiceContract]
public interface IPerCallMode {
    [OperationContract] int Counter();
}

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class PerCallMode : IPerCallMode {
    private int _counter;
    public int Counter() => ++_counter; // 每次呼叫永遠回傳 1
}

PerSession 模式

[ServiceContract]
public interface IPerSessionMode {
    [OperationContract] int Counter();
}

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class PerSessionMode : IPerSessionMode {
    private int _counter;
    public int Counter() => ++_counter; // 同一 Session 遞增
}

Single 模式

[ServiceContract]
public interface ISingleMode {
    [OperationContract] int Counter();
}

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class SingleMode : ISingleMode {
    private int _counter;
    public int Counter() => ++_counter; // 全域遞增,所有客戶端共享
}

裝載設定差異

PerCall / Single:basicHttpBinding (無會話)

<service name="WCF.ServiceLib.InstanceMode.PerCallMode">
  <endpoint address="" binding="basicHttpBinding" contract="WCF.ServiceLib.InstanceMode.IPerCallMode" />
</service>

<service name="WCF.ServiceLib.InstanceMode.SingleMode">
  <endpoint address="" binding="basicHttpBinding" contract="WCF.ServiceLib.InstanceMode.ISingleMode" />
</service>

PerSession:wsHttpBinding + 可靠會話

<service name="WCF.ServiceLib.InstanceMode.PerSessionMode">
  <endpoint address="" binding="wsHttpBinding" 
      contract="WCF.ServiceLib.InstanceMode.IPerSessionMode"
      bindingConfiguration="PerSessionModeBindingConfiguration" />
</service>

<wsHttpBinding>
  <binding name="PerSessionModeBindingConfiguration">
    <reliableSession enabled="true" />
    <security>
      <message establishSecurityContext="true" />
    </security>
  </binding>
</wsHttpBinding>

basicHttpBinding 不支援會話,wsHttpBinding 需啟用 reliableSession 與安全內容才能建立 Session。

客戶端驗證結果

PerCall:每次點擊回傳 1

var proxy = new PerCallModeClient();
proxy.Counter(); // 1
proxy.Counter(); // 1
proxy.Close();

PerSession:同一 Session 遞增

if (Session["proxy"] == null) 
    Session["proxy"] = new PerSessionModeClient();

var proxy = Session["proxy"] as PerSessionModeClient;
proxy.Counter(); // 1
proxy.Counter(); // 2
proxy.Counter(); // 3

Single:全域遞增

var proxy = new SingleModeClient();
proxy.Counter(); // 1 (第一個用戶)
proxy.Counter(); // 2 (同用戶)

var proxy2 = new SingleModeClient();
proxy2.Counter(); // 3 (不同用戶,共享同一實例)

進階考量

併發模式搭配

InstanceContextMode建議 ConcurrencyMode說明
PerCallMultiple每呼叫新實例,天然無併發問題
PerSessionSingle/ReentrantSession 內單執行緒,避免同步複雜度
SingleMultiple需自行實作同步 (Mutex, lock 等)

擴展性與資源消耗

  • PerCall:最易擴展 (無狀態,適合負載平衡),但頻繁建構/解構有開銷
  • PerSession:平衡狀態與擴展性,但需黏性 Session 或共享狀態存儲
  • Single:單一實例成為瓶頸,難以水平擴展,適合單機部署

單例模式的狀態隔離技巧

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class SingleMode : ISingleMode {
    // 使用 ThreadLocal 或 ConcurrentDictionary 隔離各呼叫者狀態
    private ConcurrentDictionary _counters = new ConcurrentDictionary();
    
    public int Counter(string clientId) {
        return _counters.AddOrUpdate(clientId, 1, (k, v) => v + 1);
    }
}

選型決策樹

  1. 服務需要保持跨呼叫狀態嗎?
    • 否 → PerCall (首選)
    • 是 → 繼續
  2. 狀態是否屬於特定用戶/Session?
    • 是 → PerSession (需支援會話綁定)
    • 否 → 繼續
  3. 狀態是否為全域共享 (快取、計數器、單例資源)?
    • 是 → Single (注意併發與擴展限制)

理解實例模式的生命週期與狀態共享語意,是設計高效能、可維護 WCF 服務的基礎功力。

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