【轉】[C#] WebAPI 防止併發調用二(冥等性)

來自:阿里的 通義靈碼

使用冪等性設計來防止C# WebAPI方法的併發調用是一種推薦的方法,因爲它不會阻塞其他請求,而是確保多次調用同一個操作會產生相同的結果。這裏有一個簡單的示例,說明如何在WebAPI控制器中實現冪等性的API:

using System;
using System.Web.Http;
using System.Linq;
using System.Collections.Generic;

public class MyApiController : ApiController
{
    private readonly Dictionary<string, DateTime> _recentRequests = new Dictionary<string, DateTime>();

    [HttpPost]
    public IHttpActionResult ProcessOrder([FromBody] OrderRequest request)
    {
        string requestId = request.Id; // 假設每個請求都有一個唯一的ID

        // 檢查在過去的一段時間內(例如1分鐘)是否有相同的請求
        if (_recentRequests.ContainsKey(requestId) && (DateTime.UtcNow - _recentRequests[requestId]) < TimeSpan.FromMinutes(1))
        {
            return Conflict(); // 返回409 Conflict狀態碼,表示請求已經在處理中
        }

        // 存儲請求ID,表示正在處理
        _recentRequests[requestId] = DateTime.UtcNow;

        try
        {
            // 這裏執行你的關鍵操作,比如處理訂單
            // ...

            // 假設訂單處理成功
            return Ok("Order processed successfully.");
        }
        finally
        {
            // 清除過期的請求記錄,保持字典大小
            var expiredRequests = _recentRequests.Where(r => (DateTime.UtcNow - r.Value) > TimeSpan.FromMinutes(1)).Select(r => r.Key).ToList();
            foreach (var expiredRequestId in expiredRequests)
            {
                _recentRequests.Remove(expiredRequestId);
            }
        }
    }

    public class OrderRequest
    {
        public string Id { get; set; } // 請求的唯一標識
        // 其他訂單相關屬性...
    }
}

在這個示例中,我們維護了一個字典 _recentRequests 來存儲最近的請求ID及其時間戳。當新的請求到來時,我們檢查這個ID是否在最近的一分鐘內出現過。如果出現過,我們返回一個衝突狀態,表明請求已經在處理中。如果沒有,我們就記錄這次請求並執行操作。最後,我們定期清理過期的請求記錄,以防止字典過大。

請注意,這個示例假設了你有一個可以關聯到每個請求的唯一ID。在實際應用中,你可能需要依賴數據庫或其他持久化存儲來實現冪等性,特別是當處理涉及數據庫操作的情況時,你可能需要在數據庫級別實現冪等性,例如通過使用唯一約束、事務和回滾邏輯等。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章