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

WCF 實戰 (13):基於 MSMQ 打造回應式服務 — 解決單向通訊無法獲知執行結果難題

     編輯:關於.NET

一、痛點:One-way MEP 的盲區

MSMQ 天生支援單向 (One-way) 訊息交換模式。客戶端送出訂單後立即返回,無法得知服務端是否成功處理、或發生何種錯誤。這在訂單處理、金融扣款等關鍵業務中完全無法接受。

One-way MEP 交互圖

二、解決架構:雙向佇列 + SOAP Header 傳遞回呼地址

核心思想:客戶端同時啟動一個本地 MSMQ 服務 (Response Service),專門接收處理端的回執訊息。客戶端提交訂單時,透過 SOAP Header 將本地回呼佇列地址 (OrderResponseContext) 夾帶傳遞。服務端處理完成後,主動連線至該地址發送 Acknowledge 訊息。

回應式服務架構圖

回執內容 (Acknowledge Message)

  • Order No.:唯一識別碼
  • Exception:失敗時的錯誤資訊,成功為 null

三、關鍵技術實作

1. 透過 SOAP Header 傳遞上下文 (避免污染 Service Contract)

不修改 IOrderProcessor.Submit(Order) 簽名,改用 OperationContext 操作 Header:

// 客戶端:寫入 Header
OrderResponseContext context = new OrderResponseContext { ResponseAddress = localQueueAddress };
MessageHeader<OrderResponseContext> header = new MessageHeader<OrderResponseContext>(context);
OperationContext.Current.OutgoingMessageHeaders.Add(header.GetUntypedHeader("OrderResponseContext", "ns"));

// 服務端:讀取 Header
OrderResponseContext ctx = OperationContext.Current.IncomingMessageHeaders.GetHeader<OrderResponseContext>("OrderResponseContext", "ns");

2. OrderResponseContext 封裝

[DataContract]
public class OrderResponseContext
{
    [DataMember] public Uri ResponseAddress { get; set; }

    public static OrderResponseContext Current
    {
        get => OperationContext.Current?.IncomingMessageHeaders.GetHeader<OrderResponseContext>("OrderResponseContext", "ns");
        set
        {
            var header = new MessageHeader<OrderResponseContext>(value);
            OperationContext.Current.OutgoingMessageHeaders.Add(header.GetUntypedHeader("OrderResponseContext", "ns"));
        }
    }
}

3. 服務端發送回執

public void Submit(Order order)
{
    // ... 業務處理邏輯 ...
    FaultException fault = null;
    if (order.IsExpired) fault = new FaultException(...);

    var responseCtx = OrderResponseContext.Current;
    var factory = new ChannelFactory<IOrderResponse>(new NetMsmqBinding(), new EndpointAddress(responseCtx.ResponseAddress));
    var channel = factory.CreateChannel();
    using (new OperationContextScope((IContextChannel)channel))
    {
        channel.SubmitOrderResponse(order.OrderNo, fault);
    }
}

四、完整專案結構 (6 子專案)

  • Contract:定義 IOrderProcessor、IOrderResponse、Order、OrderResponseContext
  • Service:訂單處理邏輯 OrderProcessorService
  • Hosting:自宿主啟動訂單佇列 .\private$\orderprocessor
  • LocalService:客戶端本地回呼服務 OrderResponseService
  • LocalHosting:啟動回呼佇列 .\private$\orderresponse
  • Client:建立 OrderResponseContext、送出訂單、等待回執

五、執行結果驗證

客戶端送出兩筆訂單 (一筆正常、一筆過期):

Client 執行輸出

服務端處理記錄:

Order Processing 輸出

回呼端接收結果:

Order Response 輸出

六、總結

此模式完美解決 MSMQ One-way 無法感知結果的問題,且不侵入業務 Contract,符合 SOA 解耦原則。適用於需異步可靠回執的分散式系統 (如訂單、付款、報表生成)。

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