部署后预加载Web应用程序页面以防止加载缓慢

时间:2017-04-07 13:57:28

标签: asp.net iis web-applications

我们每晚自动构建和部署我们的Web应用程序到我们的开发环境(使用VSTS)。当我们早上进入办公室时,第一个访问应用程序的人必须等待一段时间才能在第一次加载每个页面。后续加载非常快。

这个问题对我们的实时环境产生了更大的影响,在部署之后,它可能是最终用户,他是第一个访问应用程序并抱怨速度缓慢的人。为了缓解这种情况,团队成员当前在部署到实时环境后手动访问应用程序的每个页面,以便他们预先加载'每一页都有效,但显然很耗时!

我已经对该主题进行了相当多的搜索,并在我们的IIS服务器(IIS 8.5)中配置了相应的应用程序池,以便将其Start Mode设置为" AlwaysRunning&# 34 ;.我还编辑了我们的applicationHost文件,并使用preloadEnabled="true"属性设置了相应的网站。我在阅读了非常有帮助的Microsoft documentation中的说明后这样做了。

但是,如果我正确地阅读了该文档,那么网站的任何预加载都可能会缓解我们所遇到的问题(而且我甚至不确定这是什么类型的我想到的预加载仅在服务器,应用程序池的IIS服务重新启动时发生。在我们的案例中并没有发生这种情况。我们需要在将应用程序部署到IIS服务器之后进行预加载。

有没有办法自动预加载?

1 个答案:

答案 0 :(得分:1)

执行此操作的一种方法是自动执行HTTP请求:

  • 部署应用程序后(通过从部署计算机运行任务)
  • 在应用程序池有机会自行关闭之前(例如使用任务计划程序)

就个人而言,我使用在两种情况下都运行的工具来保持网站的预热。

优点

  • 强有力地控制执行此预热的方式和时间。
  • 它完全独立于任何IIS或web.config设置。

缺点

  • 生成“虚假”日志信息。
  • 将应用永久保留在内存中(池永远不会超时,实际上是为访问者数量较少的网站浪费服务器资源)。

示例

这样的工具可以是一个简单的控制台应用程序,其编写如下:

var taskInfo = new {
    Url = "http://www.a-website-to-keep-warm.url",
    UseHostHeader = true,
    HostHeader = "www.a-website-to-keep-warm.url",
    HttpMethod = "head"
};

HttpStatusCode statusCode = HttpStatusCode.Unused;
long contentLength = 0;

try
{
    Dictionary<string, string> headers = new Dictionary<string, string>();
    HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(taskInfo.Url);

    webRequest.Method = taskInfo.HttpMethod.ToUpper();
    if(taskInfo.UseHostHeader)
        webRequest.Host = taskInfo.HostHeader;

    using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
    {
        //did we warm-up the site successfully?
        statusCode = webResponse.StatusCode;
        contentLength = webResponse.ContentLength;

        //optionally read response headers
        foreach (string header in webResponse.Headers)
        {
            headers.Add(header, webResponse.Headers[header]);
        }
    }

    decimal kilobytes = Math.Round(contentLength / 1024M, 1);
    Debug.WriteLine($"Got {kilobytes:F1} kB with statuscode: \"{statusCode} \" ...");
}
catch (Exception ex)
{
    Debug.WriteLine($"taskInfo failed with exception: {ex.Message}");
}

就我而言,我从json文件中读取了一堆taskInfo对象,并且每隔X分钟异步执行一次,确保X低于Pool-timeout值。它也会在每次部署后立即运行。

因为我们对获取整个内容不感兴趣,所以它使用HTTP HEAD请求而不是GET。最后,它通过向请求添加Host头来支持同一主机上的多个站点。