2015/8/12 技术探讨

    正如各位读者所知道的一样,我这个博客(jhonge.net)是一个运行在64位CentOS 6.5上基于ASP.NET MVC 4.0的博客程序,截至目前为止,已经连续运行了差不多三百天。虽然每天的访问量不多,但总体上还是运行比较稳定的。

 

    但就在最近(累计第二次)我却发现了一个问题,那就是网站运行到一定时候,就会出现问题,而且问题还是比较严重,具体现象就是:网站无法访问,页面出现的是Mono原生的Error页面(不是ASP.NET的CustomError页面),并且连访问Jexus的info页面都出现访问不能。

    由于站点本身做了Exception自动收集的功能,因此我翻看了相关的运行时异常记录,其记录如下:

System.Web.HttpException: Single file build failed. ---> System.Web.Compilation.CompilationException: CS0006: Metadata file `/tmp/root-temp-aspnet-0/1b820d29/App_global.asax_3cf66e67.dll' could not be found
  at System.Web.Compilation.AssemblyBuilder.BuildAssembly (System.Web.VirtualPath virtualPath, System.CodeDom.Compiler.CompilerParameters options) [0x00000] in <filename unknown>:0 
  at System.Web.Compilation.AssemblyBuilder.BuildAssembly (System.Web.VirtualPath virtualPath) [0x00000] in <filename unknown>:0 
  at System.Web.Compilation.BuildManager.GenerateAssembly (System.Web.Compilation.AssemblyBuilder abuilder, System.Web.Compilation.BuildProviderGroup group, System.Web.VirtualPath vp, Boolean debug) [0x00000] in <filename unknown>:0 
  at System.Web.Compilation.BuildManager.BuildInner (System.Web.VirtualPath vp, Boolean debug) [0x00000] in <filename unknown>:0 
  --- End of inner exception stack trace ---
  at System.Web.Compilation.BuildManager.BuildInner (System.Web.VirtualPath vp, Boolean debug) [0x00000] in <filename unknown>:0 
  at System.Web.Compilation.BuildManager.Build (System.Web.VirtualPath vp) [0x00000] in <filename unknown>:0 
  at System.Web.Compilation.BuildManager.BuildInner (System.Web.VirtualPath vp, Boolean debug) [0x00000] in <filename unknown>:0 
  at System.Web.Compilation.BuildManager.Build (System.Web.VirtualPath vp) [0x00000] in <filename unknown>:0 
  at System.Web.Compilation.BuildManager.GetCompiledType (System.Web.VirtualPath virtualPath) [0x00000] in <filename unknown>:0 
  at System.Web.Compilation.BuildManager.GetCompiledType (System.String virtualPath) [0x00000] in <filename unknown>:0 
  at System.Web.Mvc.BuildManagerWrapper.System.Web.Mvc.IBuildManager.GetCompiledType (System.String virtualPath) [0x00000] in <filename unknown>:0 
  at System.Web.Mvc.BuildManagerCompiledView.Render (System.Web.Mvc.ViewContext viewContext, System.IO.TextWriter writer) [0x00000] in <filename unknown>:0 
  at System.Web.Mvc.ViewResultBase.ExecuteResult (System.Web.Mvc.ControllerContext context) [0x00000] in <filename unknown>:0 
  at System.Web.Mvc.ControllerActionInvoker.InvokeActionResult (System.Web.Mvc.ControllerContext controllerContext, System.Web.Mvc.ActionResult actionResult) [0x00000] in <filename unknown>:0 
  at System.Web.Mvc.ControllerActionInvoker+<>c__DisplayClass1a.<InvokeActionResultWithFilters>b__17 () [0x00000] in <filename unknown>:0 
  at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter (IResultFilter filter, System.Web.Mvc.ResultExecutingContext preContext, System.Func`1 continuation) [0x00000] in <filename unknown>:0 

     其描述原因也是比较清晰的,熟悉.NET的读者大概都会知道,ASP.NET运行的时候会把一些编译了的资源放到临时目录中(Linux中为/tmp目录,Windows为。。。‘额忘了’),如果出现文件的缺失(最常见的就是WIndows中因为.NET临时目录权限的原因造成网站无法启动),将导致站点“宕机”。要解决这种情况,方法也比较简单,那就是让Mono重新编译站点即可。

    我这里给出两个手法:

      (1)、在CronTab中添加定时重启Jexus的任务计划。

      (2)、利用ASP.NET的机制,定时的往WebConfig中追加一个空格或者在/bin目录中touch一个文件然后删除。

      (3)、【不熟悉慎用】定时的Kill -9 Jexus的工作进程(注意不是主进程)

    以上手法,无论采用哪种,原理都是让Mono重新编译站点,覆盖老的资源,刷新资源创建/修改时间(Linux会根据这个时间来决定是否保留)。

    通过上述手法,基本上可以保证各位读者的网站长期的安全稳定运行。等等,这里还有一个“釜底抽薪”的办法,那就是直接把Linux定期清理/tmp目录的行为直接干掉(感谢网友雷神(化名)协助)。

    【以下危险,出现任何磁盘被爆的后果于本文无关】

    读者们可以执行“ls /etc/cron*”看看:

    可以看到有一些定时的任务,我们把目光聚焦到“tmpwatch”中,这个脚本的执行频率为每天一次。通过翻阅相关资料,这个脚本的作用就是检查/tmp目录,并把“足够”旧的文件删除(有兴趣的读者可以看里面的源码)。它就是把我们的运行时资源删除的“罪魁祸首”。我们只要把这个脚本从磁盘中删除,Linux就不会每天定时的检查我们的临时资源,也不会删除我们的运行时资源了。(还是要小心磁盘被临时资源占满的情况)。

    好的,就先记录这么多,望对读者们有用,感谢。

  [ Linux.NET ]   [ Mono ]   [ Linux ]   [ .NET ]
知识共享许可协议 本作品由小蝶惊鸿创作,采用知识共享署名 4.0 国际许可协议进行许可,转载时请保留本文署名及链接。