.NET 6部署后,IHostedService无法启动

6

我有一个API,其中包含一个HostedService,使用VS2022和.Net 6构建。

当我在本地运行服务时,一切都按预期调用并正常工作,但是当部署后,服务似乎无法启动。

我尝试了许多不同的配置,甚至尝试使用后台服务,但结果都相同。以下是我的代码:

我有一个现有的应用程序,在VS2019中构建为.Net Core 3.1,其中包含一个HostedService,并且正常工作。 我注意到,当我将我的.Net Core应用程序转换为.Net 6时,在部署时服务未启动,因此我决定构建一个小应用程序以查找问题的原因。

Program.cs

using HostedServices.Services;

var builder = WebApplication.CreateBuilder(args);

builder.Host.UseSerilog((context, loggerConfiguration) => loggerConfiguration
        .ReadFrom.Configuration(context.Configuration)
        .Enrich.FromLogContext()
        .Enrich.WithMachineName());

// Add services to the container.

builder.Services.AddControllers();

builder.Services.AddHostedService<MainService>();
var app = builder.Build();

// Configure the HTTP request pipeline.

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

这是托管服务。

namespace HostedServices.Services
{
    public class MainService : IHostedService, IDisposable
    {
        private int executionCount = 0;
        private readonly ILogger<MainService> _logger;
        private Timer _timer;
        private Task _executingTask;
        private readonly CancellationTokenSource _stoppingCts = new CancellationTokenSource();

        public MainService(ILogger<MainService> logger)
        {
            _logger = logger;
        }
        public Task StartAsync(CancellationToken cancellationToken)
        {
   
            _logger.LogInformation($"Test Hosted Service Started {DateTime.Now}.");
            _timer = new Timer(DoWork, null, TimeSpan.Zero,
                    TimeSpan.FromMinutes(1));

            return Task.CompletedTask;

        }

        private void DoWork(object state)
        {
            _executingTask = DoWorkAsync(_stoppingCts.Token);
        }

        private async Task DoWorkAsync(CancellationToken token)
        {
            _logger.LogInformation(
                    "Doing work: {0}", DateTime.Now);

        }

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

            _timer?.Change(Timeout.Infinite, 0);

            return Task.CompletedTask;
        }

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


    }
}

本地运行一切正常,但部署后服务似乎无法启动,未生成任何日志文件,也找不到任何报告的错误。

有任何想法吗?


你们在部署时使用什么方式进行托管?例如虚拟机上的IIS、Azure应用服务、Windows服务等。另外,你们的应用程序内部是否确实具有API端点? - sellotape
1
在IIS下,除非有第一个请求到达,否则应用程序中的任何内容都不会运行。这包括您的IHostedService,因此如果没有可以访问的端点,它就永远不会启动。一旦它启动了,您就会受到IIS应用程序池的空闲超时(以及任何其他适用的IIS配置)的限制。 - sellotape
1
IHostedService相当通用;您也可以通过其他方式进行托管;例如Windows服务(非常容易)。 - sellotape
1
我只是想发布一个更新。我决定拆分我的功能并创建一个Windows服务,该服务将调用我的API。这种结构为我提供了我需要的托管服务控制权。真正的问题是,API在收到请求之前不会启动,而我需要一些东西在部署后立即启动。感谢大家的帮助。 - tdean
我在Linux和Docker上使用.Net6.0,并且我怀疑我遇到了相同的问题 - 部署时托管服务无法启动。我确实有一个端点,每5秒钟从Kubernetes(api/health)发送请求。 - kuskmen
显示剩余2条评论
2个回答

3
问题在于,虽然 IHostedService 会在站点启动时启动,但是 IIS 什么时候启动站点呢?默认情况下,在收到请求之前不会启动。如果您的站点一段时间没有活动,IIS 也会终止线程。
IIS 有一个可以启用的功能叫做“应用程序初始化”。 然后,您需要配置应用程序池始终启动(startMode="AlwaysRunning")。
最后,您需要配置站点的应用程序预加载,以便在启动时向站点发送虚拟 HTTP 请求(preloadEnabled="true")。
有关此内容的文档,请参见:https://learn.microsoft.com/zh-cn/iis/get-started/whats-new-in-iis-8/iis-80-application-initialization

0

我们曾经遇到过同样的问题,并通过以下 IIS 设置解决了它:

  • 在“页面”高级设置下:“启用预加载”必须设置为“true”(这将强制应用程序在每次应用程序池回收和启动后运行)
  • 在“应用程序池”高级设置下:“启动模式”必须设置为“AlwaysRunning”
  • IIS 中的“页面”必须允许 http(因为启用预加载仅适用于 http,而不是通过 https)

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