開發Web項目后,部署到 IIS上 ,運行一直穩定,當Web程序中加入了定時任務,或者線程之類的機制后,第二天發現悲催了,定時任務並沒有執行,此時重新登錄一下網站,定時任務又重新執行。原來IIS默認有回收線程池機制,當網站一段時間沒有人訪問時,會自動回收,項目中的線程、進程自然而然就被終止掉了。而以前類似於定時任務,線程之類的都是用控制台程序寫,然后打包成服務運行在Windows上,只要服務不終止,里面的線程就會一直運行下去,不會存在所謂的運行一段時間就被回收的情況。晚上搜索了解決線程池回收問題,主流方案是修改IIS 程序池的默認設置,將 固定時間間隔設置0,閑置超時設為0 ,即對此IIS項目不進行回收,也就不存在定時任務,線程程序被終止的情況。對 IIS 詳細的參數一知半解,這次補習了一下功課,有時候 IIS參數的設置 也是對程序的一種有效優化.
要知道,IIS自動回收相當於服務器IIS重啟,應用程序池內存清空,所有數據被清除,相當於IIS重啟,如果手動進行干預,使IIS程序不再進行回收,久而久之,可能會使程序運行變慢, 甚至會內存溢出,總歸是心有不安。反過來想,擔心程序自動回收后,線程之類的會被終止,此時只有重新登錄網站,線程才會自動去運行。也就是說,如果在程序池回收后保證運行一次網站的運行就可。說白了就是回收后進行一次URL的請求,線程池回收后會進入 Application_End ,那么將訪問URL的方法寫入到Application_End 中即可。如下圖所示
protected void Application_End(object sender, EventArgs e) { //寫進日志隊列 LogHelper.InfoLogQueue.Enqueue("Application_End"); Thread.Sleep(3000); //這里設置你的web地址,可以隨便指向你的任意一個aspx頁面,激發Application_Start string url = "http://Home/Update"; HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create(url); HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse(); Stream receiveStream = myHttpWebResponse.GetResponseStream();//得到回寫的字節流 }
也就是說,程序池回收后去請求了一次URL,首先會進入到 Application_Start 方法中,則在此方法中加入 定時任務,線程之類的操作就很合適,試想,程序池回收后,定時任務線程終止,然后去請求一次URL,線程開啟,如此往復
protected void Application_Start() { AreaRegistration.RegisterAllAreas(); GlobalConfiguration.Configure(WebApiConfig.Register); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); //開啟日志 LogHelper Log = new LogHelper(); Log.Process(); //開始記錄 LogHelper.InfoLogQueue.Enqueue("Application_Start"); //開啟定時任務 AutoTask(); }
對於以前接手的 web 程序中,使用線程之類的很少用到, 像線程、定時任務多用控制台程序包裝成服務,但是也保不齊有Web中用到,這里記錄一下