介绍
众所周知ASP.NET第一次访问时需要JIT编译,这就导致了ASP.NET程序第一次访问速度特别慢,尤其是ASP.NET MVC Razor模板引擎是解释型的,第一次还会将它编译一次,从前我们经常会说第一个人访问的都是人品有问题的,但是应用程序池会每过20分钟(默认,可修改)自动回收一次,也就是说每20分钟就要做一次人品有问题的人。
在IIS7.5之前我们想让我们只能设置的ASP.NET应用程序应用程序池的回收时间,比如设一个超大的时间,但是这样做只是防止了应用程序池定时回收,却不能解决重启后,或是其它原因进程回收后每一个人访问的慢的“人品问题”,所以微软在IIS7.5 WINDOWS 2008带的IIS上增加一个叫做热启动的功能。
热启动的原理很简单,就是在IIS的配置文件中做一些设定并指定一个继承自System.Web.Hosting.IProcessHostPreloadClient的类,然后告诉IIS说,如果哪个应用程序池回收了再次激活启动的时候就执行一下这家伙,而这家伙的功能基本上就是初始化系统的数据。
配置方法
- 在站点项目中添加一个心跳检查的接口,接口不需要经过鉴权,以下是我添加方法:
- 在Global.asax下的HttpApplication中添加
protected void Application_BeginRequest()
{
var context = HttpContext.Current;
if (context.Request.Path == "/health/ping")
{
context.Response.StatusCode = 200;
context.Response.Write("OK");
HttpContext.Current.ApplicationInstance.CompleteRequest();
}
}
- 添加预热方法
- 站点项目下添加如下类
public class ApplicationPreload : System.Web.Hosting.IProcessHostPreloadClient {
public void Preload (string[] parameters) {
try {
Console.WriteLine($"{GetLocalIp()}预热中,开始时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
//自动请求的url,其中http://localhost:8001 最好配置在config中,这边只是演示。
string url = "http://localhost:8001/health/ping"; //请求地址
HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
req.Method = "GET";
req.BeginGetResponse (o => {//一定要异步请求
Console.WriteLine($"{GetLocalIp()}预热成功!结束时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
}, null);
} catch (Exception ex) {
Console.WriteLine($"{GetLocalIp()}预热失败,失败原因:{ex.Message}");
}
}
private string GetLocalIp () {
///获取本地的IP地址
string addressIP = string.Empty;
foreach (IPAddress address in Dns.GetHostEntry (Dns.GetHostName ()).AddressList) {
if (address.AddressFamily.ToString () == "InterNetwork") {
addressIP = address.ToString ();
}
}
return addressIP;
}
}
- 打开IIS站点下应用池的高级设置,如下图:
-
把启动模式改成AlwayRunning
image.png
-
选中根节点,在右边的功能中找到【配置编辑器】,如图所示:
image.png -
我们需要修改以下两个配置,如图所示
image.png -
打开serviceAutoStartProviders,添加预热类信息
image.png
image.png -
打开sites配置,把预热与站点绑定
image.png
image.png - 到此站点的热启动已经配置完毕,重新站点可以查看效果。
注意事项
- 在代码中最好将所有的都用try{}catch{}包住,因为如果这里抛出的异常会导致应用程序停止.
- 运行的状态我们可以从事件管理器中进行查看,或是自己在代码中写日志记录运行的状态.
- 这个类中所做的并不会引用站点的启动,不会执行应用程序的生命周期,也就是说不会调用Application_Start以及其它生命周期过程.所以在本例中我们会一个请求这个站点.
- 如果在这里请求站点时一定要用异步的方式Request.同步的Request会报超时.
网友评论