最近几天遇到一个问题,郁闷了很久:
只要网站有一段时间没有人访问,那么接下来第一次访问网站的人访问速度变得很慢。
在这里记录下解决的方式,希望可以帮助遇到同样问题的朋友(asp.net 版本的网站)。
先说说我的运行环境:
之所以会出现上面的问题,很明显的一个原因就是应用程序池被自动回收了,再次访问网站速度就变慢了(不知道是不是需要重新编译?求高手指教)
那么从本质原因入手,从两方面解决该问题:1减少编译时间。2,尽量不回收应用程序池
第一:减少编译时间
我检查了我的代码,确实有个dll的编译时间居然要一分钟。(实在不明真相。。。只好去掉了这个dll,这种情况应该很少见吧。。。)
第二,尽量不回收应用程序池
这里说的尽量不回收应用程序池,不是说禁用该功能。意思是:尽量让网站保持激活状态,不要因为网站空闲而被自动回收了应用程序池。
所以,我解决的方式是:在凌晨4点自动回收一次应用程序池,其余时间,通过模拟访网站,让网站时刻处于激活状态。
下面提供两种方式模拟访问网站。经过验证,第一种方式的效果不好,第二种比较实用。
第一种方式:在Global.asax页面中添加以下代码,定时访问页面。
void Application_Start(object sender, EventArgs e) { //定时器测试 System.Timers.Timer objTimer = new Timer(); objTimer.Interval = 60000;//一分钟检查一次 objTimer.Enabled = true; objTimer.Elapsed += new ElapsedEventHandler(objTimer_Elapsed); objTimer.Start(); } void objTimer_Elapsed(object sender, ElapsedEventArgs e) { int intHour = e.SignalTime.Hour; int intMinute = e.SignalTime.Minute; int intSecond = e.SignalTime.Second;
//五分钟自动访问一次页面 if ((intMinute % 5 == 0)) { string url = System.Configuration.ConfigurationManager.AppSettings["AutoPage"];//网站下的某个页面 System.Net.HttpWebRequest myHttpWebRequest = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url); myHttpWebRequest.Timeout = 200000; try { System.Net.HttpWebResponse myHttpWebResponse = (System.Net.HttpWebResponse)myHttpWebRequest.GetResponse(); System.IO.Stream receiveStream = myHttpWebResponse.GetResponseStream(); } catch (Exception ex) { string dir = HttpRuntime.AppDomainAppPath + \\Log; using (System.IO.StreamWriter sw = new System.IO.StreamWriter(dir + "\\auto" + System.DateTime.Now.ToString("yyyyMMdd") + ".txt", true)) { sw.WriteLine("=============================== 定时访问页面发生异常 auto Error:" + System.DateTime.Now.ToString()); sw.WriteLine(ex.ToString()); sw.WriteLine(); } } } }
void Application_End(object sender, EventArgs e) { // 在应用程序关闭时运行的代码 System.Threading.Thread.Sleep(5000); string dir = HttpRuntime.AppDomainAppPath + "\\Log"; //iis地址池自动回收之后,自动重连
string url = System.Configuration.ConfigurationManager.AppSettings["AutoPage"];//网站下的某个页面 System.Net.HttpWebRequest myHttpWebRequest = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url); myHttpWebRequest.Timeout = 200000;
try { System.Net.HttpWebResponse myHttpWebResponse = (System.Net.HttpWebResponse)myHttpWebRequest.GetResponse(); System.IO.Stream receiveStream = myHttpWebResponse.GetResponseStream(); } catch (Exception ex) { using (System.IO.StreamWriter sw = new System.IO.StreamWriter(dir + "\\auto" + System.DateTime.Now.ToString("yyyyMMdd") + ".txt", true)) { sw.WriteLine("=============================== 程序池回收 发起自动连接异常 Application_End auto Errer:" + System.DateTime.Now.ToString()); sw.WriteLine(ex.ToString()); sw.WriteLine(); } } } |
第二种方式:在Global.asax页面中添加以下代码,模拟点击页面
void Application_Start(object sender, EventArgs e) { RegisterCacheEntry(); }
protected void Application_BeginRequest(Object sender, EventArgs e)
//检查缓存是否过期(如果过期注册自动访问事件) private void RegisterCacheEntry() { if (null != HttpContext.Current.Cache[DummyCacheItemKey]) { return; } HttpContext.Current.Cache.Add(DummyCacheItemKey, "Test", null, DateTime.MaxValue, TimeSpan.FromMinutes(5), CacheItemPriority.NotRemovable, new CacheItemRemovedCallback(CacheItemRemovedCallback)); } // 缓存项过期时程序模拟点击页面,阻止应用程序结束 public void CacheItemRemovedCallback(string key, object value, CacheItemRemovedReason reason) { HitPage(); }
// 模拟点击网站网页 private void HitPage() { System.Net.WebClient client = new System.Net.WebClient(); client.DownloadData(DummyPageUrl);
string dir = HttpRuntime.AppDomainAppPath + "\\Log";
using (System.IO.StreamWriter sw = new System.IO.StreamWriter(dir + "\\autopage" + System.DateTime.Now.ToString("yyyyMMdd") + ".txt", true)) { sw.WriteLine("=============================== 每5分钟自动访问页面:" + System.DateTime.Now.ToString()); sw.WriteLine(); } } |
以上就是我解决该问题的方式,时隔一年半之后才重新写了一点东西,希望可以帮到需要的朋友吧。:-)