【问题标题】:Pre-Load Web Application Pages After Deployment to Prevent Slow Loading部署后预加载 Web 应用程序页面以防止加载缓慢
【发布时间】:2017-04-07 13:57:28
【问题描述】:

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

该问题对我们的实际环境影响更大,在部署后,可能是最终用户第一个访问应用程序并抱怨运行缓慢。为了缓解这种情况,团队成员目前正在部署到实时环境后手动访问应用程序的每个页面,以便他们“预加载”每个页面,这可行,但显然很耗时!

我对该主题进行了大量搜索,并在我们的 IIS 服务器 (IIS 8.5) 中配置了适当的应用程序池,以便将其 Start Mode 设置为“AlwaysRunning”。我还编辑了我们的 applicationHost 文件并使用 preloadEnabled="true" 属性设置了适当的站点。在阅读了这个很有帮助的Microsoft documentation 中的说明后,我这样做了。

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

有没有办法自动预加载?

【问题讨论】:

    标签: asp.net iis web-applications


    【解决方案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 标头来支持同一主机上的多个站点。

    【讨论】:

    • 我还不能让它工作(我认为从控制台应用程序对我们的 Web 应用程序进行身份验证的问题,我认为),但原理似乎是合理的。
    猜你喜欢
    • 2013-03-28
    • 2019-01-07
    • 1970-01-01
    • 2015-03-15
    • 1970-01-01
    • 2011-03-18
    • 2012-04-10
    • 1970-01-01
    相关资源
    最近更新 更多