Как ставить в очередь фоновые задачи в ASP.NET Web API

У меня есть webapi, который предназначен для обработки отчетов в очереди. Шаги, которые принимает приложение, следующие:

  • Получить контент
  • Сопоставьте контент с объектом и поместите его в очередь
  • Опрос для ожидающих элементов в очереди
  • Элементы процесса в очереди поочередно

Я думал использовать Entity Framework для создания базы данных с поставленными элементами, например:

public class EFBatchItem
{
    [Key]
    public string BatchId { get; set; }
    public DateTime DateCreated { get; set; }
    public DateTime DateCompleted { get; set; }
    public string BatchItem { get; set; }
    public BatchStatus Status { get; set; }
}

Мой вопрос. Есть ли более эффективный способ, используя NServiceBus, BlockingCollection или ConcurrentQeueue, чем постоянный опрос базы данных и вытаскивание отложенных элементов один за другим? Я раньше не использовал очереди.

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

EDIT: Большой вопрос, который у меня есть, - лучший способ отобразить прогресс для пользователя. Как только пользователь отправляет контент, он переходит на новую страницу и может просматривать статус с помощью идентификатора партии. Требуется ли MSMQ или NServiceBus, чтобы уведомить пользователя? Это похоже на вариацию парадигмы REQUEST/Acknowledge/Push?

Ответы

Ответ 1

IMHO, приложение ASP.NET Web API не должно запускать эти фоновые задачи самостоятельно. Он должен отвечать только за получение запроса, вставить его в очередь (как вы указали) и вернуть ответ, указывающий на успех или неудачу полученного сообщения. Для этого подхода вы можете использовать различные системы обмена сообщениями, такие как RabbitMQ.

Что касается уведомления, у вас есть несколько вариантов. У вас может быть конечная точка, которую клиент может проверить, завершена ли обработка или нет. Кроме того, вы можете предоставить конечную точку потокового API, к которой может подписаться ваш клиент. Таким образом, клиент не должен опросить сервер; сервер может уведомлять клиентов, которые подключены. У ASP.NET Web API есть отличный способ сделать это. В следующем блоге объясняется, как:

Вы также можете рассмотреть SignalR для уведомлений этого типа сервера для клиентов.

Причина, по которой фоновые задачи сложны для приложения ASP.NET Web API, заключается в том, что вы несете ответственность за сохранение AppDomain. Это проблема, особенно когда вы размещаете в IIS. В следующих сообщениях в блоге объясняется, что это действительно хорошо:

Ответ 2

Это пакет NuGet, и он называется HangFire - https://github.com/HangfireIO/Hangfire. Задачи сохраняются даже за пределами утилизации пула.

Ответ 3

Мне нравится решение @Todd. Только ради полноты, но есть еще один вариант, который еще не упоминался:

HostingEnvironment.QueueBackgroundWorkItem(cancellationToken =>
{
    // Some long-running job
});

Примечание:

"Когда ASP.NET должен перерабатывать, он будет уведомлять фоновое произведение (установив CancellationToken), а затем будет ждать до 30 секунд для завершения работы. Если фоновая работа не завершена в этот временной интервал, работа загадочно исчезнет".

И избегайте использования методов службы с введенным DbContext здесь, так как это не сработает.

Источники: MariusSchulz и StephenCleary