不知为何,似乎没有什么项目会做ASP.NET自动升级,更多的是手工、程序配合,极少有项目完全自动升级。

这里并不讨论有关于在线升级所涉及的流程及方式,理论上所有流程跟C/S完全两样。

B/S和C/S在升级模块上的区别

C/S都明白可以运行2套独立程序,即更新和宿主分开,这便没有什么问题。而对于B/S结构,也可以如此做,但有个问题,对于产品来说如果需要配置2个网站,先不排除必须在同一机器、目录访问权限等限制以外,对于虚拟机用户无疑成本上升。

因此第一前提是单一网站下产品自动升级。

bin文件夹成为升级的弊端

为何这么说?

升级避免不了bin文件夹的修改,这会引起一个问题,倘若bin文件夹较大,通过File.Copy复制一半有可能会倒置AppDomain重启,中断升级。从而引起网站无法访问。
因此需要有种方法来强制bin文件夹修改时不重启AppDomain,抑或延缓。

对于默认配置来讲,我们可以通过machine.config来强制设置restartOnExternalChanges设为false,程序就不会重启了。

<section name="appSettings" type="System.Configuration.AppSettingsSection, System.Configuration, Version=2.0.0.0,Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
restartOnExternalChanges="false" requirePermission="false" />

看似可行性,但有个致命就是该节点无法被继承,所以我们无法在网站web.config里面强制更改默认配置。当然同样要求每个客户强制去修改这个也是不可能。所以:

第一种办法:修改machine.config来强制修改bin文件夹时不引起application重启,不可行。

而后我尝试使用发布产品时使用第二种办法预编译。预编译根本不可能起到作用,原因是预编译对于application来说,还是需要修改bin文件夹,同样也会遇到如上问题。

对于第三种办法使用Ninject依赖注入,这毋庸置疑是可行了,但由于产品已经开发尾声,倘若做这种修改,也不太现实。

因此我继续尝试其他方法,bin文件夹是受于AppDomain的监测通知重启;因此假使可以通过配置来强制这种监测通知时间不是立即,那问题也变得简单。

终于在web.config的httpRuntime节点找到 maxWaitChangeNotificationwaitChangeNotification。注意这两个属性必须要结合使用。

通过web.config配置来延缓AppDomain重启

我将用更加白话来说明这两个属性。

maxWaitChangeNotification:从第一次文件更改开始,N秒内等待后才重启AppDomain。

waitChangeNotification:两次文件更改间隔时间超出N秒内重启AppDomain。

假如以下配置:

<httpRuntime targetFramework=”4.5″ maxWaitChangeNotification=”60″ waitChangeNotification=”15″ />

表示:如果2次文件更改时间不超过15秒,则从第一次文件更改开始60内才会重启AppDomain。

这里的时间点并不会按设置的准确来重启AppDomain,但测试下来该时间点始终会大于所设置的时间。

很明显这就是我想要的。

至此ASP.NET产品化的自动升级已经解决,望此文对各位有所帮助。