Как настроить веб-API ядра .NET,
Кроме того, подпрограмма, которая постоянно проверяет очередь и обрабатывает сообщения одно за другим.
Согласно требованию, api будет действовать как получатель сообщений, которые могут получать до сотен раз в минуту, в то время как сообщения, которые он получает, должны обрабатываться одно за другим. Я немного новичок в веб-API, поэтому задаюсь вопросом, стоит ли иметь такую настройку, и если да, то как собрать различные компоненты.
Заранее спасибо..
Честно говоря, я не думаю, что имеет смысл получать и обрабатывать сообщения в одном процессе, поэтому я бы рекомендовал использовать внешнюю систему обмена сообщениями, такую как RabbitMQ или Кафка, или любую другую существующую систему по вашему выбору, где вы можете размещать свои сообщения и другую процесс поглотит его. Это довольно большая тема, можно начать с этот учебник
Если вы все еще хотите, чтобы это было в одном процессе, это также возможно, вы можете создать очередь фоновых задач, поместить туда свои сообщения и создать фоновая задача, который будет потреблять их из этой очереди.
public interface IBackgroundTaskQueue
{
void QueueBackgroundWorkItem(Func<CancellationToken, Task> workItem);
Task<Func<CancellationToken, Task>> DequeueAsync(
CancellationToken cancellationToken);
}
public class BackgroundTaskQueue : IBackgroundTaskQueue
{
private ConcurrentQueue<Func<CancellationToken, Task>> _workItems =
new ConcurrentQueue<Func<CancellationToken, Task>>();
private SemaphoreSlim _signal = new SemaphoreSlim(0);
public void QueueBackgroundWorkItem(
Func<CancellationToken, Task> workItem)
{
if (workItem == null)
{
throw new ArgumentNullException(nameof(workItem));
}
_workItems.Enqueue(workItem);
_signal.Release();
}
public async Task<Func<CancellationToken, Task>> DequeueAsync(
CancellationToken cancellationToken)
{
await _signal.WaitAsync(cancellationToken);
_workItems.TryDequeue(out var workItem);
return workItem;
}
}
Фоновая задача:
public class QueuedHostedService : BackgroundService
{
private readonly ILogger _logger;
public QueuedHostedService(IBackgroundTaskQueue taskQueue,
ILoggerFactory loggerFactory)
{
TaskQueue = taskQueue;
_logger = loggerFactory.CreateLogger<QueuedHostedService>();
}
public IBackgroundTaskQueue TaskQueue { get; }
protected async override Task ExecuteAsync(
CancellationToken cancellationToken)
{
_logger.LogInformation("Queued Hosted Service is starting.");
while (!cancellationToken.IsCancellationRequested)
{
var workItem = await TaskQueue.DequeueAsync(cancellationToken);
try
{
await workItem(cancellationToken);
}
catch (Exception ex)
{
_logger.LogError(ex,
$"Error occurred executing {nameof(workItem)}.");
}
}
_logger.LogInformation("Queued Hosted Service is stopping.");
}
}
Регистрация:
public void ConfigureServices(IServiceCollection services)
{
services.AddHostedService<QueuedHostedService>();
services.AddSingleton<IBackgroundTaskQueue, BackgroundTaskQueue>();
}
Ввести в контроллер:
public class ApiController
{
private IBackgroundTaskQueue queue;
public ApiController(IBackgroundTaskQueue queue)
{
this.queue = queue;
}
public IActionResult StartProcessing()
{
queue.QueueBackgroundWorkItem(async token =>
{
// put processing code here
}
return Ok();
}
}
Вы можете изменить BackgroundTaskQueue в соответствии со своими требованиями, но я надеюсь, что вы понимаете идею, лежащую в основе этого.
Алекс, могу я попросить вас взглянуть на мою проблему, которую я вчера разместил по этой ссылке; stackoverflow.com/questions/53292738/… Спасибо!
Спасибо, Алекс, за краткую реализацию. Но не могли бы вы объяснить, как использовать именно этот подход для обработки фоновой задачи с помощью RabbitMQ?
@AsifIqbal, я не думаю, что этот подход можно использовать с RabbitMQ, его цель прямо противоположная - иметь фоновую обработку без каких-либо внешних систем обмена сообщениями
Спасибо, Алекс за направление. Я изучаю варианты, которые вы дали.