[英]Implemented IHostedService in an asp.net core app, How to run it without the first request on IIS?
我在 asp.net 核心網站中實現了 IHostedService。 它工作得很好,但問題是我希望它在托管服務器啟動或 IIS 服務重新啟動時啟動,但除非對網站的第一個請求進入,否則它不會啟動。
更新 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 文件中的 class 程序:
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>();
}
啟動 class:
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 核心應用程序的進程,如果應用程序關閉或崩潰,則重新啟動應用程序。
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 核心應用。
托管它“OutOfProcess”可以解決問題,但請記住這不是首選方式。 我已經使用給定的代碼在 GitHub 上創建了一個 repo,您可以檢查最后一次提交的更改。
來源: https://github.com/tvdias/SO58831661
有關 InProcess 和 OutOfProcess 之間差異的深入解釋,我建議閱讀此頁面: https://weblog.west-wind.com/posts/2019/Mar/16/ASPNET-Core-Hosting-on-IIS-with-ASPNET -核心-22 。
這是我創建webservices
的方式。 在Startup.cs
我注入我的IHostedServices
。 Container
是來自StructureMap
的 class 。 我從現有項目中復制了它,因此它不能 100% 適合您的示例。
public class Program
{
public static void Main(string[] args)
{
Config.Directories.EnsureDirectoryTree();
var isService = !(Debugger.IsAttached || args.Contains("--console"));
var webHostService = MyWebHostService.BuildWebHostService(args.Where(arg => arg != "--console").ToArray());
if (isService)
{
ServiceBase.Run(webHostService);
}
else
{
webHostService.InitializeBackend();
webHostService.Host.Run();
}
}
}
public class MyWebHostService : WebHostService
{
public static readonly Logger Logger = LogManager.GetCurrentClassLogger();
public IWebHost Host { get; }
public static ZlsWebHostService BuildWebHostService(string[] args)
{
ConfigureNLog();
Logger.Info("{0} (v{1}) starting...", Config.ServiceName, GetApplicationVersion());
// restore config files
Config.Files.EnsureRestored();
var host = CreateWebHostBuilder(args).Build();
return new ZlsWebHostService(host);
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args)
{
var pathToExe = Assembly.GetExecutingAssembly().Location;
var pathToContentRoot = Path.GetDirectoryName(pathToExe);
return WebHost.CreateDefaultBuilder()
.UseKestrel()
.UseContentRoot(pathToContentRoot)
.ConfigureAppConfiguration((context, config) =>
{
config.SetBasePath(Config.Directories.ActiveConfig);
config.AddJsonFile(Config.Files.KestrelConfig.RelativePath, true, true);})
.ConfigureLogging((hostingContext, logging) =>
{
logging.ClearProviders();
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
logging.AddConsole();
if(hostingContext.HostingEnvironment.IsDevelopment())
logging.AddDebug();
})
.UseNLog()
.UseStartup<Startup>();
}
public MyWebHostService(IWebHost host) : base(host)
{
this.Host = host;
}
protected override void OnStarting(string[] args)
{
InitializeBackend();
base.OnStarting(args);
}
protected override void OnStarted()
{
Logger.Info("{0} started...", Config.ServiceName);
base.OnStarted();
}
protected override void OnStopped()
{
Logger.Info("{0} stopped...", Config.ServiceName);
base.OnStopped();
}
...
}
public class Startup
{
...
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public IServiceProvider ConfigureServices(IServiceCollection services)
{
...
services.AddSingleton<PaymentQueueService>();
...
var container = new Container(c =>
{
c.IncludeRegistry<MyFooRegistry>();
c.Populate(services);
});
return container.GetInstance<IServiceProvider>();
}
...
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.