2012-03-01 72 views
2

我正在創建一個基於新的ASP.NET Web API的Web API。我試圖理解處理同時提交多個數據集的人的最佳方法。如果他們有100,000個請求,那麼讓他們一次提交1000個請求會很好。在新的ASP.NET Web API中,如何設計「批量」請求?

比方說,我有我的聯繫方式控制器創建新的聯繫方式:

public string Put(Contact _contact) 
{ 
    //add new _contact to repository 
    repository.Add(_contact); 

    //return success 
} 

什麼是正確的方法,讓用戶「批量」提交新的聯繫人?我在想:

public string BatchPut(IEnumerable<Contact> _contacts) 
{ 
    foreach (var contact in _contacts) 
    { 
     respository.Add(contact); 
    } 
} 

這是一個很好的做法嗎?這是否會解析帶有JSON數組的聯繫人的GET請求(假設它們格式正確)?

最後,關於如何最好地響應批處理請求的任何提示?如果300箇中的4個失敗會怎樣?

非常感謝!

+0

什麼保證你有沒有在服務器上請求尺寸方面,你的數據庫的用戶數量,用戶類型,數據的質量,時間限制和可靠性?這些會影響您可以使用的設計選擇? – bloudraak 2012-03-01 21:00:56

+0

我有一個API爲每個API請求創建1個作業。到目前爲止,API一次只能完成1項工作。這種限制已經引起了大客戶的頭痛,他們需要提出多達200,000個請求。每個單一的API調用都會作爲一條消息進入Amazon SQS,因此併發性一直不是問題,僅僅是讓大量客戶感到頭疼。謝謝! – 2012-03-01 22:02:41

+0

您的業務流程是否允許異步處理?例如,當我在一家我們曾經在排隊計算報價的保險公司工作時,客戶提交了數據,並且必須在報價創建時進行輪詢。這取決於可用資源,從第二或第二到第三十分鐘採取任何措施。 – bloudraak 2012-03-01 22:14:35

回答

2

當您放置一個集合時,您要麼插入整個集合,要麼將現有集合替換爲一個資源。它與GET,DELETE或POST集合非常相似。這是一個原子操作。使用是作爲替代個別呼籲PUT聯繫人可能不是很RESTfull(但這是真正開放的辯論)。

您可能想看看HTTP pipelining併發送同一套接字的多個PutContact請求。通過每個請求,您可以返回該單個請求的標準HTTP狀態。

我在過去使用SOAP實現了批量更新,並且在系統加載時我們遇到了一些無法預料的問題。如果你不注意,我懷疑你會遇到同樣的問題。

  1. 例如,數據庫可以在批量更新的中間超時和所有的地獄中失敗兩方面打破了鬆動,可靠性,交易等,以及可憐的客戶必須弄明白髮生了什麼實際進行了更新,並嘗試再次。
  2. 當有太多記錄要更新時,HTTP請求會超時,因爲我們花費的時間太長。這打開了另一罐蠕蟲。
  3. 另一個問題是我們在更新過程中會接受多少數據?足夠的10MB的接觸?也許1MB?內存使用和安全性方面,較大的緩衝區有很多含義。

因此,我建議查看HTTP pipelining

更新

我的建議是處理批創建聯繫人作爲一個異步的過程。假設「工作」與「批量創建」過程相同。因此,該服務可能如下所示:

public class JobService 
{ 
    // Post 
    public void Create(CreateJobRequest job) 
    { 
     // 1. Create job in the database with status "pending" 
     // 2. Save job details to disk (or S3) 
     // 3. Submit the job to MSMQ (or SQS) 
     // 4. For 20 seconds, poll the database to see if the job completed 
     // 5. If the job completed, return 201 with a URI to "Get" method below 
     // 6. If not, return 202 (aka the request was accepted for processing, but has not completed) 
    } 

    // Get 
    public Job Get(string id) 
    { 
     // 1. Fetch the job from the database 
     // 2. Return the job if it exists or 404 
    } 
} 

後臺進程是從隊列中可以更新數據庫或交替進行投入到服務,以更新作業的狀態運行,並完成消費的東西。

你需要另一種服務,通過剛加工,地址錯誤等數據進行導航。

您後臺進程可能需要寬容驗證錯誤。如果沒有,或者如果你的服務做驗證(假設你是不是做數據庫調用等,爲它的響應時間不能得到保證),你可以返回一個結構類似,其中包含您的客戶端來解決這個問題,並重新提交請求足夠的信息CreateJobResponse。如果您必須進行一些費時的驗證,請在後臺進程中執行此操作,請將作業標記爲失敗並使用允許客戶修復錯誤並重新提交請求的信息更新作業。這假定客戶可以通過工作失敗的事實做些事情。

如果創建方法打破了作業請求成許多較小的「工作」你必須要處理的事實,它可能不是原子,並造成諸多挑戰監視作業是否已成功完成。

+0

嗨沃納 - 感謝您的建議。我不應該使用PUT動詞 - 我的錯誤。如果你有一段時間再看一遍,我就會重申上述問題。乾杯! – 2012-03-01 20:24:48

+0

這是驚人的沃納,非常感謝!你正在回答我甚至沒有想過要回答的問題。如果MVC web api中的模型綁定足夠聰明,可以處理上面顯示的自定義對象列表,我仍然很好奇。聽起來像我有更大的問題需要處理。乾杯! – 2012-03-02 04:39:13

0

PUT操作應該取代資源。通常情況下,您會針對單個資源執行此操作,但是在針對集合執行此操作時,這意味着您將使用傳遞的數據集替換原始集合。不知道你是否有意這樣做,但我認爲你只是更新集合的一個子集,在這種情況下PATCH方法更合適。

最後,關於如何最好地響應批處理請求的任何提示?如果300箇中的4個失敗會怎樣?

這真的取決於你。只有一個響應,因此您可以發送200 OK或400 Bad Request,並將詳細信息放在主體中。

+0

謝謝Maurice-我不應該說PUT。我打算讓人們批量創建新的聯繫人(一次可以創建1000個聯繫人)。 – 2012-03-01 20:13:10