Как ставить в очередь фоновые задачи в 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