无需重新加载即可更新.NET网站


13

我曾经在中开发网站PHPASP classic以及是否需要进行某些更改。您可以更改单个/几个文件,而没人会真正注意到。也许有人在上传过程中请求更改的文件,但这大约是半秒钟的时间。对于大多数较小的网站,这没有问题。

但是,最新的网站是使用此网站构建的C# MVC,当您更改代码时,您需要重建网站并上传更改后的DLL文件。但是,当您更改DLL文件时,它将重新启动您的网站并重置所有活动状态sessions。它还必须重新加载所有内容,在大型站点上,可能需要花费几分钟才能加载所有内容。浏览该站点的每个人都会注意到并需要再次登录。

网站的主要更新并不常见,因此这不是问题。但是我们确实有定期的促销“小”更新。就像“填写此表格并获得三个月的免费会员资格”或“上传...的图片的前10个将获得价格”一样。我想你会得到漂移的。有些促销活动与此类似,可以使用一个模块根据显示的设置显示正确的信息,但是通常需要自定义代码。

我在想一个系统,其中每个推广是它自己的DLL基于接口的文件,然后加载DLL使用动态Type.GetTypeActivator.CreateInstanceInvokeMember。尽管这可行,但我想知道这是否是正确的方法。

所以我的问题是:如何.NET在不重新加载整个网站和删除会话的情况下(而不是重新启动应用程序池)动态更新网站。


为了回应您的悬赏评论:我工作的大型网站通过处理负载均衡器和进程外会话来处理较小的代码更改,就像处理大型代码一样,因为部署到活动中的所有代码都必须经过审查/签核过程,我们不能只是在服务器上放置代码。我猜我们对“大”的定义可能不匹配;)
扎夫-本·迪吉德(Ben Duguid

Answers:


11

查看“应用程序初始化” IIS 7.5,Windows 2008 R2(较难设置)IIS 8,Windows 2012

应用程序初始化允许任何应用程序(不是应用程序池的站点)重启重叠,并使用旧的,仍在运行前一个应用程序的设备同时预热新的应用程序。一旦启动了新应用程序(由您可以设置的URL决定),它将开始使用新应用程序并关闭前一个应用程序。将应用程序初始化与方法结合使用以确保会话在整个应用程序池重新启动之间保持不变,可以使您的站点无缝地重新启动。(Zhaph对机器密钥有很好的说明。)

除了以上用于应用程序初始化配置的链接之外,您还需要查看触发网站重新启动的因素-由于网站重新启动不使用应用程序初始化,因此网站重新启动将是无缝的。

您可以配置IIS,以便DLL更新不会立即触发站点重启,也不会更改web.config(httpRuntime和外部配置文件上的ChangeNotification值较高,与您的站点有关)。

最终结果是,您可以在不重新启动站点的情况下更新DLL /代码,然后强制应用程序重新启动,这将使用AppInitialization后台预热来无缝更改代码。

协调一致地执行这些操作对于无缝重启非常有效。


那里有一套很好的步骤-当然要考虑一下:)
Zhaph-Ben Duguid 2015年

这听起来像我要找的东西。尝试一下并进行设置。谢谢
雨果·德辛

@HugoDelsing希望它对您有用。
jeffreypriebe 2015年

谢谢,这是我最终使用的,效果很好。
雨果·德辛

@HugoDelsing很高兴听到它也对您有用。
jeffreypriebe 2015年

5

有多种方法可以处理您的要求,以及问题的几个不同方面:

处理促销的小更新

您真正想要的是一个内容管理系统或类似的系统,它使您可以即时编辑内容(想想Wordpress / Drupal或从.NET的角度来看N2 CMS,Umbraco,Orchard等),但是如果您没有沿那条路走,可以尝试一些方法。

因为ASP.NET仅在您触摸某些类型的文件时才真正重新加载(web.config(s),而/bin/and /app_code/文件夹的内容大部分)-并且对“其他文件更改”具有可配置的限制(基本上,一旦您进行了修改,您网站中的许多文件会重新启动应用程序池- NumRecompilesBeforeAppRestart)您可以考虑做一些事情,在其他文件夹中检查一些静态(即.html)文件,以根据需要提取并显示这些文件,或者利用LoadControl采用字符串路径的方法一个.ascx用户控制和动态加载它-你如何决定要展现的是一个不同的问题StackOverflow上更适合-但是我建议一个基于命名约定的解决方案。

您还可以考虑使用类似Managed Extensibility Framework(MEF-从版本4开始就已是.NET框架的完整部分)之类的东西,它允许您编写基于插件的体系结构并在目录外部指定文件夹/bin/以进行监视新的.DLL-尽管我没有尝试过查看它是否可以避免应用重新启动的问题,但是我已经在网络环境中使用了此功能,以便为网站添加通用功能。

如果那没有吸引力,我能想到的唯一其他选择是像在经典ASP中一样,将控件添加为“在前面的代码”-即使用<script runat="server">块而不是编译的“代码在后”类包含运行控制逻辑-这将删除一个DLL变革的需要,在一些第一次性能损失为代价的控制被编译的飞行-再次,你需要用平衡这个NumRecompilesBeforeAppRestart,如果你正在做很多小的更改。

如何在应用重新启动期间保持会话?

这可能是一个较容易解决的问题,涉及三个关键步骤:

  1. 将MachineKey(IIS7,但仍然保持8)配置为恒定值,而不是AutoGenerate-这意味着当AppPool回收时,它将使用相同的密钥,因此能够从之前解密会话cookie,viewstate等。回收。
  2. 无论是设置一个状态服务器配置一个数据库来保存会话状态
  3. 在web.config中从使用或切换InProc到SessionState元素。StateServerSQLServer

这样,您将拥有持久的会话,这些会话可以在应用程序重启后继续存在。但是,这些并不是“免费的”-您存储在会话中的所有内容现在都必须可序列化,并且由于每个页面加载现在都需要更多的网络行程才能获得,并可能释放会话数据,因此您的性能会受到轻微影响。

但是,如果您处于部署后需要花费“几分钟”才能重新启动应用程序的位置,则可能需要考虑迁移到负载平衡的环境,或者至少考虑使用热插拔的暂存/实时设置。 (例如Azure / AWS / etc.net提供的服务)-这样,您可以在更新服务器时使服务器脱机或使用新代码使其准备就绪,然后将其换入-如果您已采取解决共享地址的步骤会话(请参见上文),这将正常工作,并且不会影响您的用户。


谢谢您的回答。不幸的是,这CMS不是我想要的。我不想更改内容,我想更改代码。有关会话的部分仅是示例。更改它并不能解决重新加载DLL文件时网站停顿一两分钟的问题。该MEF部分很有趣,但是是我正在考虑的系统的第三方解决方案。所以+1是努力的结果,但不幸的是,这并不是我的问题的答案。
雨果·德辛

1
我已经更新了答案,以解决其中的几个问题:MEF由MS发布,自v4起已成为.NET框架的完整部分。你可以尝试使用代码在前方为你的新控件,或者采取负载平衡/舞台,现场安装,这将使得到一台服务器运行起来,然后换入。
Zhaph本-杜吉德

1
我已经概述了使用应用程序初始化的替代解决方案。好处是所有代码和服务器设置都是“正常的”,而无需特殊的负载平衡或动态加载控件,从而使您的运行环境更简单。当然,出于其他原因,负载平衡/分段实时设置可能很有用。
jeffreypriebe,2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.