refs:
How to auto start and keep an ASP.NET core web application running on IIS – taithienbo
1、在 ASP.NET Core 中使用托管服务实现后台任务
在 ASP.NET Core 中使用托管服务实现后台任务,非常的简单。这样就可以在一起维护和管理。
1、实现IHostedService,IDisposable这两个接口,或者直接继承BackgroundService抽象类(因为它实现IHostedService,IDisposable),看代码:
//实现接口:IHostedService,IDisposable
public class EmailBackgroundService : IHostedService,IDisposable
{
//定义一个定时器
private Timer _timer;
/// <summary>
/// 启动任务绑定
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public Task StartAsync(CancellationToken cancellationToken)
{
Common.WriteEmailLog("定时任务被启动", "...start...");
//绑定定时任务
//设置延迟时间
_timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromSeconds(60 * Interval));
return Task.CompletedTask;
}
/// <summary>
/// 定时执行的操作,绑定到定时器上
/// </summary>
/// <param name="state"></param>
/// <returns></returns>
private void DoWork(object state)
{
Common.WriteEmailLog("定时任务被触发", "开始一波邮件发送");
try
{
//一波操作
}
catch (Exception ex)
{
Common.WriteEmailLog("定时发送邮件时报错", ex.Message);
}
}
/// <summary>
/// 任务关闭时执行
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public Task StopAsync(CancellationToken cancellationToken)
{
Common.WriteEmailLog("定时任务被关闭", "...end...");
_timer?.Change(Timeout.Infinite, 0);
return Task.CompletedTask;
}
/// <summary>
/// 释放托管资源,释放时触发
/// </summary>
public void Dispose()
{
Common.WriteEmailLog("定时任务被释放闭", "...Dispose...");
_timer?.Dispose();
//iis会回收这个定时任务,这边在回收的时候触发一个请求,来再次唤醒该服务
Thread.Sleep(5000);
HttpHelper.HttpGet(_configuration.GetSection("AwakenUrl").Value);
}
}
2、在Startup类中注册后台任务:
//配置后台任务
//services.AddTransient(typeof(Microsoft.Extensions.Hosting.IHostedService), typeof(EmailBackgroundService));
services.AddHostedService<EmailBackgroundService>();
2、解决iis自动回收导致任务被终止的问题
IIS会定时回收,类似于自动重新启动网站,我们都有知道网站启动后第一次访问往往会比较慢,网站启动后没有访问,过段时间iis会回收,请求再来的时候会和网站刚刚启动的时候一样,需要等待一段时间,很不舒服,这个就是因为iis回收导致的。
定时回收除了会出现上面的情况外,还会将我们托管的后台任务回收掉,导致我们的后台任务终止执行,直到进来一个请求(网站内任意地址)任务启动,那么如果请求很久没来,这个任务将无法被启动,错过任务应该执行的档口。虽然我们可以通过调整自动回收的时间,甚至设置他不自动回收,但这样始终不是最好的解决方案。
通过配置iis来实现预加载,即在资源被回收的情况下,通过一个链接来唤醒自身,这样首次访问的时候不会觉得卡顿,并且我们被回收掉的定时任务又会重新的启动起来,一举两得,具体的配置方法如下:
1、设置网站的启用预加载:
2、编辑配置
3、设置应用程序池 启动模式为:AlwaysRunning
经过上面的一顿操作,就配置好了。
If you have an ASP.NET or an ASP.NET core which hosts a background job that needs to always run, want to preload the application for performance instead of waiting for the initial request to hit the app, or just get some tips on IIS, then read on.
Application does not auto start and goes into idle
The ASP.NET core module handles requests for an ASP.NET core application and manages the process under which the application runs. Per the documentation, the module does not start the process for the ASP.NET core app until it receives an initial HTTP request.
The module starts the process for the ASP.NET Core app when the first request arrives and restarts the app if it crashes. This is essentially the same behavior as seen with ASP.NET 4.x apps that run in-process in IIS that are managed by the Windows Process Activation Service (WAS)
As the behavior of an ASP.NET core module is similar to the WAS, the module also terminates the application it has not received a HTTP request for the application after a predefined period of time (Idle time-out). This lazy loading feature is by design to efficiently manage resources.
Keeping the app to run continuously on IIS
Do the following to keep an ASP.NET core application auto start and always run on IIS:
I. Install the Application Initialization Module
The application initialization module allows IIS to preemptively perform initialization tasks such as making the initial HTTP request to your application, or call your custom logic to perform whatever you desire to warm up your app.
I find it necessary to install the module even though the settings for making an application auto start and always running are there on IIS 10 which is the server I am using.
You can install the Application Initialization module via the Server Manager. You can find the module under Server Roles -> Web Server -> Application Developer -> Application Initialization.
II. Configure the app pool
In IIS Manager, right click on the application pool under which the application runs and select “Advanced Settings”. Update the following values:
- Set the .NET CLR version to v4.0.
- Set start mode to “Always Running”.
- Set Idle Time-Out (minutes) to 0.
The Idle time-out value of 0 means your application never time out. IIS does not kill your application even if it has not received any HTTP request for an indefinite time.
Setting the start mode to “Always Running” tells IIS to start a worker process for your application right away, without waiting for the initial request.
The .NET CLR version is a little tricky. Normally, for an ASP.NET core application, we would set the .NET CLR version to “No Managed Code”, as suggested in the hosting ASP.NET core application on IIS documentation.
ASP.NET Core runs in a separate process and manages the runtime. ASP.NET Core doesn’t rely on loading the desktop CLR.
However, I’ve found it is necessary to set the .NET CLR version for the other settings to work ( application auto start and always run ).
III. Configure the IIS site
In IIS Manager, right click on the site for the application, select “Manage Website” -> “Advanced Settings” and set the “Preload Enabled” value to true.
That’s it.
That’s all I have to do to keep the ASP.NET core app running on IIS. Let me know if you have questions. Your feedback is also welcome.