为 IIS 修复缓慢的初始负载

IIS 对于低流量网站有一个恼人的功能,它回收未使用的工作进程,导致第一个用户在一段时间后到达网站得到一个非常长的延迟(30秒以上)。

我一直在寻找这个问题的解决方案,我已经找到了这些潜在的解决方案。

答: 使用应用程序初始化插件

B. 使用.NET 4自动启动

C. 禁用空闲超时(在 IIS 重置下)

D. 预编译网站

我想知道哪一个更好,更重要的是,为什么有这么多的解决方案来解决同一个问题?(我的猜测是,它们不是,我只是没有正确理解某些事情)。

剪辑

执行 C似乎足以让我的网站保持活跃,但我发现网站运行缓慢的真正根源与实体框架有关,我似乎无法理解为什么它会变冷。看看 这个的问题,哪个 不幸的是还没有得到回应已经回答了!

我最终只是不得不做一个 热身脚本偶尔访问我的网站,以确保它保持快速。

165900 次浏览

选项 A、 B 和 D 似乎是同一类,因为它们只影响最初的启动时间,它们对网站进行预热,就像在内存中编译和加载库一样。

使用 C 语言,设置空闲超时,应该足够让后续的服务器请求得到快速服务(重新启动应用程序池需要相当长的时间——以秒为单位)。

据我所知,超时的存在是为了节省内存,其他网站在该机器上并行运行可能需要。代价就是一次缓慢的加载时间。

除了在用户不活动的情况下应用程序池会被关闭这一事实之外,应用程序池默认每1740分钟(29小时)进行一次循环。

来自 technet:

Internet 信息服务(IIS)应用程序池可以是 定期循环,以避免不稳定的状态,可能导致 应用程序崩溃、挂起或内存泄漏。

只要应用程序池循环还在运行,就足够了。 但是,如果您真的希望大多数组件具有一流的性能,那么还应该使用您提到的应用程序初始化模块之类的东西。

我之所以使用 B,是因为它与工作进程回收相结合,意味着在回收时只会有一个延迟。这避免了在空闲后响应第一个请求时与初始化通常相关联的延迟。你还可以保留回收利用的好处。

有关如何帮助解决性能问题的提示,请参阅本文。这包括“冷启动”部分中与启动相关的性能问题。无论您正在使用哪种类型的服务器,本地还是生产环境中,其中大部分都很重要。

Https://blogs.msdn.microsoft.com/b/mcsuksoldev/2011/01/19/common-performance-issues-on-asp-net-web-sites/

如果应用程序反序列化 XML 中的任何内容(包括 Web 服务...) ,请确保 SGEN 针对反序列化中涉及的所有二进制文件运行,并将生成的 DLL 放入全局装配缓存(GAC)中。这将预编译运行 SGEN 的程序集所使用的所有序列化对象,并将它们缓存在结果 DLL 中。这可以节省大量的时间,从磁盘和 Web 服务的初始调用中首次反序列化(加载)配置文件。 Http://msdn.microsoft.com/en-us/library/bk3w6240(vs.80).aspx

如果任何一台 IIS 服务器没有对外访问互联网的权限,可以通过在 machine.config 中添加 generatePublisher證 = “ false”来关闭对 Authenticode 二进制文件的证书吊销列表(CRL)检查。否则,每个工作进程可以挂起超过20秒在启动期间,而它超时试图连接到互联网,以获得一个 CRL 列表。 Http://blogs.msdn.com/amolravande/archive/2008/07/20/startup-performance-disable-the-generatepublisherevidence-property.aspx

Http://msdn.microsoft.com/en-us/library/bb629393.aspx

考虑在所有程序集上使用 NGEN。然而,如果不仔细使用,这并不会带来很大的性能提高。这是因为必须在构建时仔细设置每个进程加载的所有二进制文件的基加载地址,以免重叠。如果因为地址冲突而不得不重新加载二进制文件,那么几乎所有使用 NGEN 带来的性能提升都将丧失。 Http://msdn.microsoft.com/en-us/magazine/cc163610.aspx

编写一个 ping 服务/脚本来访问您的空闲网站是一个相当好的方法,因为您将有一个完整的控制。如果您已经租用了一个专用的主机箱,那么您提到的其他选项也是可用的。

在共享主机空间中,热身脚本是最好的一级防御(自助是最好的帮助)。这是一篇共享 如何从你自己的网络应用程序做到这一点的想法的文章。

Web 主机挑战

您必须记住,如果您像我们许多人(小公司和个人)一样托管在共享服务器上,那么所有的机器配置选项都不可用。

NET MVC 开销

我的网站至少需要30秒的时间,而它已经超过20分钟没有被点击(网络应用程序已经被停止)。太可怕了。

测试性能的另一种方法

还有另一种方法来测试它是你的 ASP.NET MVC 启动还是别的什么。在你的网站上放一个普通的 HTML 页面,你可以直接点击它。
如果问题与 ASP.NET MVC 启动有关,那么 HTML 页面将几乎立即呈现,即使 Web 应用程序尚未启动。
这就是我第一次意识到问题出在 ASP.NET MVC 启动阶段的原因。 我在任何时候都可以加载一个 HTML 页面,而且加载速度非常快。然后,在打开那个 HTML 页面之后,我会打开我的一个 ASP.NET MVC URL,然后我会看到一条 Chrome 消息: “等待 raddev.us... ...”

使用有用脚本的另一个测试

之后,我写了一个 LINQPad (查看 http://linqpad.net了解更多信息)脚本,每8分钟(少于应用程序卸载的时间——应该是20分钟)我让它运行几个小时。

当脚本运行的时候,我点击了我的网站,每次我的网站出现的速度都非常快。这给了我一个很好的想法,我所经历的缓慢很可能是因为 ASP.NET MVC 的启动时间。

获取 LinqPad 并运行以下脚本——只需将 URL 更改为您自己的 URL 并让它运行,您就可以轻松地对其进行测试。 祝你好运。

注意 : 在 LinqPad 中,您需要按 F4并添加对 System 的引用。Net 添加将检索您的页面的库。

ALSO : 确保将 String URL 变量更改为指向一个 URL,该 URL 将从 ASP.NET MVC 站点加载路由,以便引擎能够运行。

System.Timers.Timer webKeepAlive = new System.Timers.Timer();
Int64 counter = 0;
void Main()
{
webKeepAlive.Interval = 5000;
webKeepAlive.Elapsed += WebKeepAlive_Elapsed;
webKeepAlive.Start();
}


private void WebKeepAlive_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
webKeepAlive.Stop();
try
{
// ONLY the first time it retrieves the content it will print the string
String finalHtml = GetWebContent();
if (counter < 1)
{
Console.WriteLine(finalHtml);
}
counter++;
}
finally
{
webKeepAlive.Interval = 480000; // every 8 minutes
webKeepAlive.Start();
}
}


public String GetWebContent()
{
try
{
String URL = "http://YOURURL.COM";
WebRequest request = WebRequest.Create(URL);
WebResponse response = request.GetResponse();
Stream data = response.GetResponseStream();
string html = String.Empty;
using (StreamReader sr = new StreamReader(data))
{
html = sr.ReadToEnd();
}
Console.WriteLine (String.Format("{0} : success",DateTime.Now));
return html;
}
catch (Exception ex)
{
Console.WriteLine (String.Format("{0} -- GetWebContent() : {1}",DateTime.Now,ex.Message));
return "fail";
}
}

按计划 ping 站点的一个好选择是使用 Microsoft Flow,它是免费的,每月最多可以运行750次。这是非常容易创建一个流,每小时点击您的网站,以保持它的温暖。您甚至可以通过创建一个带有延迟的单个流来分隔站点的多个点击,从而在750的限制附近工作。

Https://flow.microsoft.com

我在第一个请求上得到了持续15秒的延迟在4分钟的闲置之后。我的问题是,我的应用程序使用的是 SQL Server 的 Windows 集成身份验证,而服务配置文件位于与服务器不同的域中。这导致了应用程序初始化时从 IIS 到 SQL 的跨域身份验证——这是我延迟的真正原因。我更改为使用 SQL 登录而不是 Windows 身份验证。延误很快就消失了。我仍然有所有的应用程序初始化设置到位,以帮助提高性能,但他们可能根本不需要在我的情况下。