最近调试一个东西,写了个监控页面,发现自己Cache的数据在设定的过期时间远远还没有到的时候就过期了,于是我着手排查了下出现问题的原因
1.程序会删除缓存 -- 查找了整个项目,发现程序里根本没有删除缓存的操作,所以这个原因可以排除
2.写缓存的方法有问题 -- 这个也可以排除,因为很多地方用这个dll,其它项目不存在这个bug,所以这个原因也可以排除
3.服务器上有清除所有内存的程序 -- 于是一个个服务终止了下,最后发现终止了一个动转静服务后,程序就没有异常了,所以这个问题是因为动转静服务引起的了。
反编译了这个动转静服务的源码,发现并没有清理内存的操作,于是想到了是不是因为动转静服务的什么操作,引起了应用程序池Appliacation_End,然后cache都被回收了。于是在Global.asax里面的Application_End方法里写了下面的代码,用于记录是否引起了这个事件,以及引起事件触发的原因。
protected void Application_End(object sender, EventArgs e) { HttpRuntime runtime = (HttpRuntime)typeof(System.Web.HttpRuntime).InvokeMember("_theRuntime", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.GetField, null, null, null); if (runtime == null) return; string shutDownMessage = (string)runtime.GetType().InvokeMember("_shutDownMessage", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField, null, runtime, null); string shutDownStack = (string)runtime.GetType().InvokeMember( "_shutDownStack", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField, null, runtime, null); if (!EventLog.SourceExists(".NETRuntime")) { EventLog.CreateEventSource(".NETRuntime", "Application"); } EventLog log = new EventLog(); log.Source = ".NET Runtime"; log.WriteEntry(String.Format("\r\n\r\n_shutDownMessage={0}\r\n\r\n_shutDownStack={1}", shutDownMessage, shutDownStack), EventLogEntryType.Error); }
结果,日志文件里头果然有记录,记录都为:
=====================================================
The description for Event ID ( 0 ) in Source ( .NET Runtime ) cannot be found. The local computer may not have the necessary registry information or message DLL files to display messages from a remote computer. You may be able to use the /AUXSOURCE= flag to retrieve this description; see Help and Support for details. The following information is part of the event:
_shutDownMessage=Recompilation limit of 15 reached
HostingEnvironment initiated shutdown
HostingEnvironment caused shutdown
_shutDownStack= at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)
at System.Environment.get_StackTrace()
at System.Web.Hosting.HostingEnvironment.InitiateShutdownInternal()
at System.Web.Hosting.HostingEnvironment.InitiateShutdown()
at System.Web.HttpRuntime.ShutdownAppDomain(String stackTrace)
at System.Web.Compilation.DiskBuildResultCache.ShutdownCallBack(Object state)
at System.Threading._ThreadPoolWaitCallback.WaitCallback_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallbackInternal(_ThreadPoolWaitCallback tpWaitCallBack)
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback(Object state).
=====================================================
网上搜索了一下导致Asp.Net站点重启的原因,具体可以参考:http://blog.csdn.net/kaosini/article/details/8510087,其中第五条就这样说
修改aspx,master文件不一定会导致重启;但是每修改一次都会导致一次重新编译,重新编译次数达到15次之后会导致站点重启,重启原因是:
Recompilation limit of 15 reached HostingEnvironment initiated shutdown
于是我自己测试了下,停了动转静服务,在运行的项目里面,进行了如下操作
1.对1个Asp.net文件修改了20次以上,发现并没有导致Asp.net站点重启
2.对15个Asp.net文件进行修改,结果就出现了Asp.net站点重启
3.对20个html文件进行修改,发现并没有导致Asp.net站点重启
于是我就纳闷了,动转静导致的都是生成的html文件,并没有修改动态文件,为什么会导致站点重启呢,于是又谷歌了一番,终于又找到个有用的帖子
引起IIS下Asp.net应用程序重启的原因 http://blog.csdn.net/kaosini/article/details/8513536,这个是翻译过来的文章,原文是http://www.dotnetindia.com/2003/10/why_aspnet_rest.html
里面的一条这样说道,一个文件夹里同时有很多文件发生改变,.NET系统对这些变化通知来不及反应,这时候可能会重启。比如在高PV时每次访问都生成一次;
仔细想了下,导致我的站点重启的原因最有可能是两个
1.一个文件夹里同时有很多文件发生改变,.NET系统对这些变化通知来不及反应,这时候可能会重启
2.我Asp.net文件里面会include动转静生成的html文件,可能也被认为是Asp.net文件发生了变化,这个原因感觉是微乎其微,因为include动转静生成文件的asp.net文件不止15个,而且我把动转静的文件个数控制到15个以内的话,居然还是会出现重启的情况,虽然频率降低了。
补充(2013.01.18):今天我特地试了一下方法1,对项目下的任意一个文件进行多文件的覆盖,连续执行n多次,结果发现站点果然重启了。但是好像没有明显的规律,有时候执行两三次就会重启,有时候20多次照样不重启,所以不敢断言就是文件更新造成的。
下面是微软的帮助和支持里面的类似问题的原因和解决方案