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

WCF 分散式交易:TransactionFlow 與兩階段提交 (2PC) 實戰

     編輯:關於.NET

WCF 支援跨服務的分散式交易,基於兩階段提交協定 (Two-Phase Commit, 2PC),確保多個服務操作的原子性:要麼全成功,要麼全回滾。

核心設定三要素

  1. 契約層:[TransactionFlow(TransactionFlowOption.Mandatory)] 強制要求呼叫端傳入交易
  2. 實作層:[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)] 在交易範圍內執行
  3. 綁定層:wsHttpBinding 設定 transactionFlow="true" 支援交易流動

服務端實作

Hello 服務:正常寫入

[ServiceContract]
public interface IHello {
    [OperationContract]
    [TransactionFlow(TransactionFlowOption.Mandatory)]
    void WriteHello(string name);
}

public class Hello : IHello {
    [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
    public void WriteHello(string name) {
        var ctx = new DBDataContext();
        ctx.Items.InsertOnSubmit(new Item {
            Title = $"Hello: {name}, TransactionId: {Transaction.Current.TransactionInformation.LocalIdentifier}",
            CreatedTime = DateTime.Now
        });
        ctx.SubmitChanges();
    }
}

Hi 服務:模擬失敗

[ServiceContract]
public interface IHi {
    [OperationContract]
    [TransactionFlow(TransactionFlowOption.Mandatory)]
    void WriteHi(string name);
}

public class Hi : IHi {
    [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
    public void WriteHi(string name) {
        if (DateTime.Now.Second % 2 == 0) 
            throw new Exception("為測試交易而拋出的異常");
        
        var ctx = new DBDataContext();
        ctx.Items.InsertOnSubmit(new Item {
            Title = $"Hi: {name}, TransactionId: {Transaction.Current.TransactionInformation.LocalIdentifier}",
            CreatedTime = DateTime.Now
        });
        ctx.SubmitChanges();
    }
}

Result 服務:查詢結果

[ServiceContract]
public interface IResult {
    [OperationContract] List<Item> GetResult();
}

public class Result : IResult {
    public List<Item> GetResult() {
        var ctx = new DBDataContext();
        return ctx.Items.OrderByDescending(x => x.CreatedTime).ToList();
    }
}

裝載設定

<bindings>
  <wsHttpBinding>
    <binding name="TransactionConfiguration" transactionFlow="true" />
  </wsHttpBinding>
</bindings>

<services>
  <service name="WCF.ServiceLib.Transaction.Hello" behaviorConfiguration="TransactionBehavior">
    <endpoint address="" binding="wsHttpBinding" contract="WCF.ServiceLib.Transaction.IHello" bindingConfiguration="TransactionConfiguration" />
  </service>
  <service name="WCF.ServiceLib.Transaction.Hi" behaviorConfiguration="TransactionBehavior">
    <endpoint address="" binding="wsHttpBinding" contract="WCF.ServiceLib.Transaction.IHi" bindingConfiguration="TransactionConfiguration" />
  </service>
  <service name="WCF.ServiceLib.Transaction.Result" behaviorConfiguration="TransactionBehavior">
    <endpoint address="" binding="basicHttpBinding" contract="WCF.ServiceLib.Transaction.IResult" />
  </service>
</services>

客戶端協調交易

var proxyHello = new TransactionSvc.Hello.HelloClient();
var proxyHi = new TransactionSvc.Hi.HiClient();
var proxyResult = new TransactionSvc.Result.ResultClient();

var options = new TransactionOptions {
    IsolationLevel = IsolationLevel.Serializable,
    Timeout = TimeSpan.FromSeconds(30)
};

using (var ts = new TransactionScope(TransactionScopeOption.Required, options)) {
    try {
        proxyHello.WriteHello("webabcd");
        proxyHello.Close();

        proxyHi.WriteHi("webabcd"); // 可能拋出異常
        proxyHi.Close();

        ts.Complete(); // 兩階段提交:準備階段 -> 提交階段
        lblErr.Text = "OK";
    } catch (Exception ex) {
        lblErr.Text = ex.ToString(); // 未呼叫 Complete,交易自動回滾
    }
}

GridView1.DataSource = proxyResult.GetResult();
GridView1.DataBind();

兩階段提交 (2PC) 流程

  1. 準備階段:交易協調器通知所有資源管理器(資料庫、佇列等)準備提交
  2. 各資源管理器將變更寫入持久化記錄檔,回應「準備就緒」或「失敗」
  3. 提交階段:
  4. 若全部回應「準備就緒」→ 協調器發送「提交」命令
  5. 若任一回應「失敗」→ 協調器發送「回滾」命令
  6. 資源管理器執行提交/回滾,釋放鎖定資源

TransactionFlowOption 選項

選項說明
Mandatory強制要求呼叫端提供交易,否則拋出例外
Allowed允許但不強制,有交易則加入,無則建立新交易
NotAllowed禁止交易流動(預設值)

注意事項

  • 需啟用 MSDTC (Distributed Transaction Coordinator) 服務
  • 防火牆需開放 MSDTC 通訊埠 (動態 RPC 埠 + 135)
  • 所有參與資源必須支援 2PC(SQL Server、MSMQ、Oracle 等)
  • 交易範圍內避免長時間運算或外部呼叫,減少鎖定持有時間

WCF 分散式交易讓微服務架構也能擁有 ACID 保證,是金融、電商等強一致性場景的關鍵技術。

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