c# - 在 asp.net 核心应用程序中实现了 IHostedService,如何在没有 IIS 的第一个请求的情况下运行它?
问题描述
我已经在一个 asp.net 核心网站中实现了 IHostedService。它工作得很好,但问题是我希望它在托管服务器启动或 IIS 服务重新启动时启动,但除非对网站的第一个请求进入,否则它不会启动。
- 该网站托管在 IIS 版本 10.0.18 上
- AppPool 处于“AlwaysRunning”模式
- 网站上的“PreloadEnabled”为“True”。
- 将“.NET CLR 版本”设置为“无托管代码”或“v4.0.xxxxxx”没有帮助。
- dotnet core 版本为 2.2 并安装了 dotnet core hosting bundle。
更新 1: @Arthur 建议的“应用程序初始化模块”没有帮助。既不是现场也不是服务器级别。
我使用的配置:
<applicationInitialization
doAppInitAfterRestart="true"
skipManagedModules="false"
remapManagedRequestsTo="init.htm">
<add initializationPage="/init.htm" hostName="localhost"/>
</applicationInitialization>
更新2:这是我实现界面的方式
internal class PaymentQueueService : IHostedService, IDisposable
{
private readonly ILogger _logService;
private Timer _timerEnqueue;
public PaymentQueueService(ILogger logService)
{
_logService = logService;
}
public Task StartAsync(CancellationToken cancellationToken)
{
_logService.LogInformation("Starting processing payments.");
_timerEnqueue = new Timer(EnqueuePayments, null, TimeSpan.Zero,
TimeSpan.FromSeconds(10));
return Task.CompletedTask;
}
private void EnqueuePayments(object state)
{
_logService.LogInformation("Enqueueing Payments.");
}
public Task StopAsync(CancellationToken cancellationToken)
{
_logService.LogInformation("Stopping processing payments.");
_timerEnqueue?.Change(Timeout.Infinite, 0);
return Task.CompletedTask;
}
public void Dispose()
{
_timerEnqueue?.Dispose();
}
}
main.cs 文件中的 Program 类:
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args).ConfigureServices(services =>
{
services.AddHostedService<PaymentQueueService>();
}).Configure((IApplicationBuilder app) =>
{
app.UseMvc();
})
.UseStartup<Startup>();
}
启动类:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostEnvironment env)
{
}
}
解决方案
由于建议的“应用程序初始化模块”不起作用,您可以考虑自己与客户进行调用,因为
该模块在第一个请求到达时启动 ASP.NET Core 应用程序的进程,并在应用程序关闭或崩溃时重新启动该应用程序。
public class Program {
static Lazy<HttpClient> client = new Lazy<HttpClient>();
public static async Task Main(string[] args) {
var host = CreateWebHostBuilder(args).Start();//non blocking start
using (host) {
bool started = false;
do {
var response = await client.Value.GetAsync("site root");
started = response.IsSuccessStatusCode;
await Task.Delay(someDelayHere);
} while (!started);
host.WaitForShutdown();
}
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureServices(services => {
services.AddHostedService<PaymentQueueService>();
})
.Configure((IApplicationBuilder app) => {
app.UseMvc();
})
.UseStartup<Startup>();
}
笔记:
要防止进程外托管的应用程序超时,请使用以下方法之一:
- 从外部服务 ping 应用程序以使其保持运行。
- 如果应用仅托管后台服务,请避免 IIS 托管并使用 Windows 服务来托管 ASP.NET Core 应用。