В новом ASP.NET Web API как проектировать «пакетные» запросы? - PullRequest
2 голосов
/ 01 марта 2012

Я создаю веб-API на основе нового ASP.NET Web API. Я пытаюсь понять, как лучше всего обрабатывать людей, отправляющих несколько наборов данных одновременно. Если у них есть 100 000 запросов, было бы хорошо разрешить им подавать 1000 одновременно.

Допустим, у меня есть новый метод создания контактов в контроллере контактов:

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);
    }
}

Это хорошая практика? Будет ли это анализировать запрос GET с массивом контактов JSON (при условии, что они правильно отформатированы)?

И, наконец, какие-нибудь советы о том, как лучше всего отвечать на пакетные запросы? Что делать, если 4 из 300 терпят неудачу?

Спасибо миллион!

Ответы [ 2 ]

2 голосов
/ 01 марта 2012

Когда вы помещаете коллекцию, вы либо вставляете всю коллекцию, либо заменяете существующую коллекцию, как если бы это был один ресурс.Это очень похоже на GET, DELETE или POST коллекцию.Это атомная операция.Использование в качестве замены для отдельных вызовов PUT, контакт может быть не очень RESTfull (но это действительно открыто для обсуждения).

Возможно, вы захотите взглянуть на HTTP pipelining и отправить несколькоPutContact запрашивает один и тот же сокет.С каждым запросом вы можете вернуть стандартный HTTP-статус для этого отдельного запроса.

В прошлом я реализовывал пакетные обновления с помощью SOAP, и мы столкнулись с рядом непредвиденных проблем, когда система находилась под нагрузкой.Я подозреваю, что вы столкнетесь с теми же проблемами, если не будете обращать на это внимания.

  1. Например, база данных может прерваться в середине обновления пакета, и весь ад выпадет из-за сбоевнадежность, транзакции и т. д. И бедному клиенту пришлось выяснить, что на самом деле было обновлено, и повторить попытку.
  2. Когда было слишком много записей для обновления, запрос HTTP истекал из-за истечения времени.Это открыло еще одну банку с червями.
  3. Другая проблема заключалась в том, сколько данных мы будем принимать во время обновления?Достаточно ли было 10 МБ контактов?Возможно, 1 МБ?Большие буферы имеют многочисленные последствия с точки зрения использования памяти и безопасности.

Отсюда мое предложение взглянуть на HTTP-конвейеризацию .

Обновление

Мое предложение будет относиться к пакетному созданию контактов как к асинхронному процессу.Просто предположим, что «задание» совпадает с процессом «пакетного создания».Таким образом, служба может выглядеть следующим образом:

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 для службы, чтобы обновить состояние задания на выполнение и выполнение.

Вам понадобится другой сервис для навигации по только что обработанным данным, устранения ошибок и так далее.

Ваш фоновый процесс может нуждаться в терпимости к ошибкам проверки.Если нет, или если ваша служба выполняет проверку (при условии, что вы не выполняете вызовы базы данных и т. Д., Для которых время ответа не может быть гарантировано), вы можете вернуть такую ​​структуру, как CreateJobResponse, которая содержит достаточно информации для вашего клиента, чтобы исправить проблему и повторно отправить запрос.Если вам необходимо выполнить некоторую проверку, которая занимает много времени, сделайте это в фоновом режиме, пометьте задание как невыполненное и обновите задание информацией, которая позволит клиенту исправить ошибки и повторно отправить запрос.Это предполагает, что клиент может что-то сделать с тем, что задание не выполнено.

Если метод Create разбивает запрос задания на множество меньших «заданий», вам придется иметь дело с тем фактом, что он может быть не атомарным, и ставить многочисленные задачи, чтобы отслеживать, успешно ли выполнены задания.

0 голосов
/ 01 марта 2012

Операция PUT должна заменить ресурс.Обычно вы делаете это для одного ресурса, но когда делаете это для коллекции, это означает, что вы заменяете исходную коллекцию на набор переданных данных.Не уверен, что вы собираетесь это сделать, но я предполагаю, что вы просто обновляете подмножество коллекции, и в этом случае более подходящим будет метод PATCH.как лучше всего отвечать на пакетные запросы?Что делать, если 4 из 300 терпят неудачу?

Это действительно ваше дело.Существует только один ответ, поэтому вы можете отправить 200 OK или 400 Bad Request и указать детали в теле.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...