ASP.NET Core 托管服务在 API 闲置后休眠

7
我有一个托管的服务,每分钟检查一次电子邮件帐户。 我还使用Web API 2.1的MVC。 为了启动我的托管服务,我必须通过调用API方法来“唤醒”它。 在Web API停止活动一段时间后,托管服务会进入睡眠状态并停止检查电子邮件。 就好像它被垃圾回收了一样。 如何使其持续运行?
非常感谢您的帮助。
Startup.cs:
public void ConfigureServices(IServiceCollection services)
    {
        services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new Info {Title = "CAS API", Version = "v1"});

                // Set the comments path for the Swagger JSON and UI.
                var xmlFile = $"{Assembly.GetEntryAssembly().GetName().Name}.xml";
                var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
                c.IncludeXmlComments(xmlPath);
            })

            .AddCors(options =>
            {
                options.AddPolicy("CorsPolicy",
                    builder => builder.WithOrigins(Configuration["uiOrigin"])
                        .AllowAnyMethod()
                        .AllowAnyHeader()
                        .AllowCredentials());
            })
            .AddHostedService<EmailReceiverHostedService>()
            .Configure<EmailSettings>(Configuration.GetSection("IncomingMailSettings"))
            .AddSingleton<IEmailProcessor, MailKitProcessor>()
            .AddSingleton<IEmailRepository, EmailRepository>()


          ...

EmailReceiverHostedService.cs:

using CasEmailProcessor.Options;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Threading;
using System.Threading.Tasks;

public class EmailReceiverHostedService : IHostedService, IDisposable
{
    private readonly ILogger _logger;
    private readonly Timer _timer;
    private readonly IEmailProcessor _processor;
    private readonly EmailSettings _emailConfig;


    public EmailReceiverHostedService(ILoggerFactory loggerFactory,
        IOptions<EmailSettings> settings,
        IEmailProcessor emailProcessor)
    {
        _logger = loggerFactory.CreateLogger("EmailReceiverHostedService");
        _processor = emailProcessor;
        _emailConfig = settings.Value;
        _timer = new Timer(DoWork, null, Timeout.Infinite, Timeout.Infinite);
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Timed Background Service is starting.");
        StartTimer();
        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Timed Background Service is stopping.");
        StopTimer();

        return Task.CompletedTask;
    }

    public void Dispose()
    {
        _timer?.Dispose();
    }

    private void StopTimer()
    {
        _timer?.Change(Timeout.Infinite, 0);
    }
    private void StartTimer() { _timer.Change(TimeSpan.FromSeconds(_emailConfig.TimerIntervalInSeconds), TimeSpan.FromSeconds(_emailConfig.TimerIntervalInSeconds)); }

    private void DoWork(object state)
    {
        StopTimer();
        _processor.Process();
        StartTimer();
    }
}

你使用什么来托管你的API?可能已经配置了一个空闲超时,它会说“如果我在x分钟内没有收到任何请求,则关闭以节省内存”。 - Woohoojin
我正在使用IIS来托管。 - Cindy Hoskins
2
在应用程序池中有一个20分钟的“空闲”超时时间。我将观察日志,看看它是否在20分钟后超时,然后将超时时间增加到40分钟。最终,我可能需要在Windows服务中托管电子邮件部分。 - Cindy Hoskins
您可以配置您的应用程序始终运行,阅读此文章:http://docs.hangfire.io/en/latest/deployment-to-production/making-aspnet-app-always-running.html - agua from mars
2个回答

11
正如您所想的那样,当在IIS中托管时,应用程序池回收可能会导致您的主机关闭。以下已经指出了这一点:
重要的是要注意,您部署ASP.NET Core WebHost或.NET Core Host的方式可能会影响最终解决方案。例如,如果您将WebHost部署在IIS或常规Azure应用服务上,则由于应用程序池回收,您的主机可能会关闭。 部署注意事项和经验教训 对于可能的解决方法,您可以尝试将空闲超时设置为零以禁用默认回收。
由于IIS的默认回收,您可以考虑不同的托管方法:
- 使用Windows服务 - 使用Docker容器(Windows容器),但需要Windows Server 2016或更高版本。 - 使用Azure函数

针对您的情况,您可以尝试 在Windows服务中托管ASP.NET Core


1
我在Windows事件计划程序中创建任务,以访问一个URL来唤醒服务。 powershell.exe -command {Invoke-WebRequest http://localhost:8080}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接