我目前正在开发移动应用程序使用的Web API。如果进行了需要发送电子邮件的API调用,则会将该电子邮件添加到Azure存储中的队列中。为了处理队列(阅读队列中的邮件并实际发送),我认为最好的解决方案是创建一个托管服务,该服务将在后台执行。
要实现此目的,我遵循了以下文档中的说明:https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-2.1
我为此创建了一个类,该类实现了.NET Core 2.1中的抽象BackgroundService-class。看起来像这样:
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的所有其他调用几乎要花费十倍的时间。只有在我对BackgroundService的实现中注释掉Task.Delay()部分后,性能才能恢复到可接受的水平。
但是,这似乎比我的问题的实际解决方案更像是一种解决方法。我是否在做其他错误而使性能这样的坦克?