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

以 WCF 訂閱發佈模式取代輪詢:優化郵件審批服務架構

     編輯:關於.NET

原有架構痛點

早期為配合特定崗位人員透過郵件回覆「同意」完成審批,開發了一個獨立的郵件審批服務,採用 固定間隔輪詢 郵件伺服器:

  1. 每 10 分鐘連線郵件伺服器抓取新郵件。
  2. 解析郵件格式,提取審批單據資訊。
  3. 呼叫審批流程引擎完成審批。

缺點明顯:

  • 即時性差:最長 10 分鐘延遲。
  • 資源浪費:無新郵件仍發起連線與處理流程。
  • 單執行緒瓶頸:處理耗時時若縮短間隔會導致並發衝突,且郵件伺服器需回執,耦合度高。

解決方案:WCF 雙工通訊實現訂閱發佈

架構轉型

將「客戶端輪詢」改為「伺服器推送」:

  1. 審批服務啟動時,向郵件伺服器(WCF 服務端)註冊訂閱。
  2. 郵件伺服器收到新郵件時,主動回呼 審批服務的 Callback 合約。
  3. 審批服務接收郵件內容,異步處理解析與審批流程。

關鍵 WCF 合約設計

[ServiceContract(CallbackContract = typeof(IMailNotificationCallback))]
public interface IMailSubscriptionService
{
    [OperationContract(IsOneWay = true)]
    void Subscribe(string clientId);

    [OperationContract(IsOneWay = true)]
    void Unsubscribe(string clientId);
}

public interface IMailNotificationCallback
{
    [OperationContract(IsOneWay = true)]
    void OnNewMailReceived(MailMessageDto mail);
}

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, 
                   ConcurrencyMode = ConcurrencyMode.Multiple)]
public class MailSubscriptionService : IMailSubscriptionService
{
    private static readonly Dictionary<string, IMailNotificationCallback> _subscribers 
        = new Dictionary<string, IMailNotificationCallback>();
    private static readonly object _lock = new object();

    public void Subscribe(string clientId)
    {
        var callback = OperationContext.Current.GetCallbackChannel<IMailNotificationCallback>();
        lock (_lock) _subscribers[clientId] = callback;
    }

    public void Unsubscribe(string clientId)
    {
        lock (_lock) _subscribers.Remove(clientId);
    }

    // 郵件伺服器內部呼叫,對外不公開
    internal static void NotifyNewMail(MailMessageDto mail)
    {
        List<IMailNotificationCallback> callbacks;
        lock (_lock) callbacks = _subscribers.Values.ToList();
        
        foreach (var cb in callbacks)
        {
            Task.Run(() => 
            {
                try { cb.OnNewMailReceived(mail); }
                catch { /* 記錄錯誤,移除失效訂閱 */ }
            });
        }
    }
}

客戶端(審批服務)實作

public class ApprovalService : IMailNotificationCallback
{
    private IMailSubscriptionService _proxy;
    private readonly string _clientId = "ApprovalService_01";

    public void Start()
    {
        var context = new InstanceContext(this);
        var factory = new DuplexChannelFactory<IMailSubscriptionService>(
            context, "MailSubscriptionEndpoint");
        _proxy = factory.CreateChannel();
        _proxy.Subscribe(_clientId);
    }

    public void OnNewMailReceived(MailMessageDto mail)
    {
        // 異步處理解析與審批,避免阻塞 Callback 執行緒
        Task.Run(() => ProcessMailAsync(mail));
    }

    private async Task ProcessMailAsync(MailMessageDto mail)
    {
        // 解析郵件、提取單據、呼叫審批引擎...
    }
}

優勢與後續擴展

  • 即時觸發:郵件到達瞬間推送,零延遲。
  • 資源節省:無閒時輪詢,連線長駐但極輕量。
  • 水平擴展:多實例審批服務各自訂閱,郵件伺服器廣播通知,天然支援分散式部署。
  • 容錯機制:Callback 異常自動移除訂閱,服務重啟自動重訂閱。

遷移建議

  1. 郵件伺服器端新增 WCF 訂閱服務,並行運行一段時間驗證穩定性。
  2. 審批服務改造為雙工客戶端,部署後觀察流量與延遲指標。
  3. 確認無誤後下線舊輪詢邏輯。

總結

WCF 雙工通訊完美契合「事件驅動」場景,將輪詢改為訂閱發佈,不僅解決即時性與資源浪費,更為未來分散式擴展奠定基礎。雖郵件解析複雜度仍存,但架構層面已邁出關鍵一步。

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