在新的ASP.NET Web API中,如何设计“批处理”请求?

时间:2012-03-01 18:02:01

标签: asp.net-mvc-4 asp.net-web-api

我正在基于新的ASP.NET Web API创建Web API。我正在努力了解处理人们同时提交多个数据集的最佳方法。如果他们有100,000个请求,那么让他们一次提交1,000个就好了。

假设我的联系人控制器中有一个新的Contact方法:

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个失败怎么办?

万分感谢!

2 个答案:

答案 0 :(得分:2)

当您输入集合时,您要么插入整个集合,要么替换现有集合,就像它是单个资源一样。它与GET,DELETE或POST非常相似。这是一个原子操作。使用是作为对PUT的单个调用的替代,联系人可能不是非常RESTfull(但这确实是开放的辩论)。

您可能需要查看HTTP pipelining并发送同一套接字的多个PutContact请求。对于每个请求,您可以返回该单个请求的标准HTTP状态。

我过去使用SOAP实现了批量更新,当系统负载时,我们遇到了许多无法预料的问题。如果你不注意,我怀疑你会遇到同样的问题。

  1. 例如,数据库可能会在批量更新过程中超时,并且在故障,可靠性,交易等方面完全崩溃。穷人客户必须弄清楚实际更新的内容并再试一次。 / LI>
  2. 当要更新的记录太多时,HTTP请求会超时,因为我们花了太长时间。这打开了另一种蠕虫。
  3. 另一个问题是我们在更新期间会接受多少数据? 10MB的联系人够了吗?也许1MB?较大的缓冲区在内存使用和安全性方面有很多含义。
  4. 因此,我的建议是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
        }
    }
    

    从队列中消耗内容的后台进程可以更新数据库,或者对服务执行PUT以将Job的状态更新为正在运行和已完成。

    您需要其他服务来浏览刚刚处理的数据,解决错误等问题。

    您的后台进程可能需要容忍验证错误。如果没有,或者如果您的服务进行了验证(假设您没有进行数据库调用等,无法保证响应时间),您可以返回一个类似CreateJobResponse的结构,其中包含足够的信息供客户端解决问题并重新提交请求。如果必须进行一些耗时的验证,请在后台进程中执行此操作,将作业标记为失败,并使用允许客户端修复错误并重新提交请求的信息更新作业。这假设客户端可以对作业失败的事实做一些事情。

    如果Create方法将作业请求分解为许多较小的“作业”,则必须处理这样一个事实,即它可能不是原子的,并且会对监视作业是否成功完成提出许多挑战。

答案 1 :(得分:0)

PUT操作应该替换资源。通常,您针对单个资源执行此操作,但在针对集合执行此操作时,这意味着您将原始集合替换为传递的数据集。不确定你是否有意这样做,但我假设你只是更新集合的一个子集,在这种情况下,PATCH方法会更合适。

  
    

最后,有关如何最好地响应批量请求的任何提示?如果300中的4个失败怎么办?

  

这真的取决于你。只有一个响应,因此您可以发送200 OK或400 Bad Request并将详细信息放入正文中。