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

交易處理:建構可處理故障且不丟失資料的可擴充系統

     編輯:關於.NET

HTTP 與訊息遺失

團隊初期使用 HTTP 傳輸 WCF 服務,服務處理過程中寫入資料庫。壓力測試一週發現訊息遺失,主要為包含訂單資訊的訊息,且集中在 10 分鐘內。日誌分析發現:關鍵 Windows 修補程式自動安裝導致伺服器重啟。HTTP 處理訊息時開啟資料庫交易,寫入資料提交。伺服器重啟導致交易中斷,資料庫回滾保持一致,但原始訊息資料既不在記憶體也不在網路堆疊中——訊息遺失。對訂單系統意味著經濟損失;空管系統則可能釀成災難。

穩定訊息傳遞

決定從 HTTP 轉用穩定傳輸,在 MSMQ 與 SQL Service Broker 間選擇。Service Broker 優勢:訊息傳遞在資料庫內,避免分散式交易;MSMQ 優勢:Windows 內建零開銷、與 WCF 緊密整合、伺服器間點對點通訊不加重資料庫負載。最終決定每台伺服器使用專用 MSMQ 隊列。

  • MSMQ 不自動將每條訊息寫入磁碟(利效能)。確保穩定性:設定 Message.Recoverable = true 或用 NetMsmqBinding (預設 Durable = true)。
  • 全方案用 NetMsmqBinding 時,非穩定傳遞訊息需獨立端點,設定非交易隊列與 Durable = false。
  • 隊列故障回滾訊息:必須在交易內執行「接收」操作。OperationBehaviorAttribute.TransactionScopeRequired 搭配佇列傳輸輕鬆實現,出隊交易用於處理訊息。

系統一致性

處理訊息後,服務回覆/發送其他訊息。若用 HTTP/TCP 等不識別交易的技術極危險。資料庫死鎖導致交易回滾,已發送的其他系統資訊可能不實。圖 1 展示死鎖導致系統 A 收到錯誤通知,引發全域衝突。

訂單處理實例:採購訂單到達 → 更新狀態 → 通知倉儲 → 更新 CRM 客戶值 → CRM 死鎖 → 交易回滾 → 重試時客戶資料顯示無交易 → 倉儲系統未收到回滾通知 → 產品在裝卸台等待超過一小時 → 單一事故導致週利潤降低 30%。轉用 MSMQ 可迎刃而解。

交易性訊息傳遞

MSMQ 發送訊息:方法返回不代表訊息已發送。訊息先本地存於外發隊列。在交易內發送時,僅提交交易後 MSMQ 才真正發送。死鎖或交易中止時,外發隊列訊息被刪除。注意:交易性訊息傳遞不意味著發送者與處理服務共享交易。訊息到達處理服務僅表示發送者成功提交交易,不代表接收服務處理行為。

瞬態條件處理

  • 格式正確訊息可能因資料庫死鎖、連線池極限導致異常(瞬態環境條件)。預設行為:交易異常全回滾,訊息回隊列,稍後重試(環境可能已改善)。
  • 資料庫不可用屬非瞬態(不知恢復時間)。單純回滾重試可能重複異常。訊息可能含高價值資料(百萬美元訂單),不宜留在處理-回滾迴圈。
  • 多資料庫/多表情況:部分資源離線導致部分訊息類別持續回滾,佔用線程導致其他訊息類別也無法處理,服務資源利用率極低。
  • 智能做法:連續失敗 n 次後將訊息移至錯誤隊列(本質上與其他隊列無異)。資源離線時,受影響訊息移至錯誤隊列,其他訊息繼續處理,服務維持可用。

反序列化錯誤

位元組到達端點時反序列化可能失敗:XML 宣告的資料型別未部署/版本錯誤、舊客戶端對新服務端點發送不相容訊息。訊息可能含重要資料,不宜丟棄或阻塞輸入隊列。解決方案:直接移至錯誤隊列(無需等待 n 次回滾,因處理結果必定失敗)。

錯誤隊列管理

  • 中毒訊息可能為垃圾,需操作人員檢查決定。
  • 反序列化異常:路由至舊版本端點或重新格式化後回輸入隊列。
  • 資料庫離線:錯誤隊列訊息與日誌標記隱藏問題,利於快速識別解決。

時間與訊息遺失

穩定訊息傳遞非萬靈丹,有相關開銷。企業對企業案例:訂單系統與外部物流公司通訊。平均訊息 1MB,每秒 10 筆訂單。物流伺服器不可用時,訊息堆積外發隊列:I/O 10MB/s (600MB/min)。3 小時後發現,系統嘗試向 36GB RAID 5 寫入 100GB 資料,伺服器失去穩定性且難以備份。備份過程中遺失數百萬美元訂單。

TimeToBeReceived

  • 訂單系統接收請求、發布/接收事件,產生輸入/外發隊列訊息。部分資料僅幾分鐘有效,保留更久無意義。
  • 服務級別協議 (SLA) 定義響應時間要求。若服務無法在給定時間 (含隊列等待) 完成處理,即視為失敗。
  • 可為各訊息類型定義有效期 (含發送者外發隊列時間、傳輸時間、接收者隊列時間)。MSMQ 用 Message.TimeToBeReceived 設定。
  • 現實:訊息遺失不可避免。客戶端視角:遺失訊息、遺失響應、伺服器緩慢無差別。服務作為客戶端呼叫其他服務時,需自我保護:用超時機制,未在規定時間收到響應則通告已接收請求、稍後發送響應 (如郵件)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved