В настоящее время я разрабатываю веб-API, используемый нашим мобильным приложением.Если выполняется вызов API, который должен отправить электронное письмо, оно добавляется в очередь в хранилище Azure.Для обработки очереди (чтения почты очереди и ее фактической отправки) я подумал, что лучшим решением будет создание размещенной службы, которая будет делать это в фоновом режиме.
Для реализации этого я следовал инструкциям из следующей документации: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-2.1
Я создал класс, который реализует абстрактный BackgroundService-класс из .NET Core 2.1 для этого.Это выглядит так:
namespace Api.BackgroundServices
{
/// <summary>
/// Mail queue service.
/// This handles the queued mails one by one.
/// </summary>
/// <seealso cref="Microsoft.Extensions.Hosting.BackgroundService" />
public class MailQueueService : BackgroundService
{
private readonly IServiceScopeFactory serviceScopeFactory;
/// <summary>
/// Initializes a new instance of the <see cref="MailQueueService"/> class.
/// </summary>
/// <param name="serviceScopeFactory">The service scope factory.</param>
public MailQueueService(IServiceScopeFactory serviceScopeFactory)
{
this.serviceScopeFactory = serviceScopeFactory;
}
/// <summary>
/// This method is called when the <see cref="T:Microsoft.Extensions.Hosting.IHostedService" /> starts. The implementation should return a task that represents
/// the lifetime of the long running operation(s) being performed.
/// </summary>
/// <param name="stoppingToken">Triggered when <see cref="M:Microsoft.Extensions.Hosting.IHostedService.StopAsync(System.Threading.CancellationToken)" /> is called.</param>
/// <returns>A <see cref="T:System.Threading.Tasks.Task" /> that represents the long running operations.</returns>
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
await HandleMailQueueAsync();
//await Task.Delay(3000, stoppingToken);
}
}
private async Task HandleMailQueueAsync()
{
using (IServiceScope serviceScope = serviceScopeFactory.CreateScope())
{
TelemetryClient telemetryClient = serviceScope.ServiceProvider.GetService<TelemetryClient>();
try
{
IMailHandler mailHandler = serviceScope.ServiceProvider.GetService<IMailHandler>();
await mailHandler.HandleMailQueueAsync();
}
catch (Exception exception)
{
telemetryClient.TrackException(exception);
}
}
}
}
}
После регистрации, вызвав
services.AddHostedService<MailQueueService>();
в Startup.cs, он успешно обработает почтовую очередь, но все другие вызовы WebAPI принимаютпочти в десять раз длиннееТолько если я закомментирую часть Task.Delay () в моей реализации BackgroundService, производительность вернется к приемлемому уровню.
Однако это больше похоже на обходной путь, чем на реальное решение моей проблемы.Я что-то не так делаю, что делает танк производительности вот таким?