ASP.NET MVC4页面在Microsoft Azure上加载速度极慢

问题描述 投票:1回答:2

在将ASP.NET MVC4应用程序部署到Microsoft Azure之后,我正在处理非常烦人的性能问题。在重新启动应用程序后(或在几分钟不活动后),一些页面第一次加载大约需要15秒。在此之后,即使清除客户端缓存,这些页面也将在大约2秒钟内加载(这仍然需要改进,但优于15秒,这是一个巨大的用户体验杀手)。

这是我到目前为止已经尝试过的内容:

  • 我梳理了Global.asax中的每个事件,以便用虚拟代码替换与数据库相关的代码
  • 将发布设置更改为:«发布期间预编译»(将所有输出合并到单个程序集)
  • 根据Azure的“应用程序性能分析”,我的应用程序被视为“健康”
  • «Always On»在门户网站的应用程序设置中激活(定价层为B1 [基本,1核心,1.75GB RAM],因此我假设永远在线的交换机不会被共享运行时配置覆盖)

由于以上没有一个子弹解决了我的问题,我尝试使用Quartz.NET编写一个keppalive-Job,定期请求网站如下:

new System.Net.WebClient().OpenRead("https://foo.azurewebsites.net");

(在我的情况下,我认为效果或多或少与在Web.Config中声明initializationPages相同,如提到的here,不是吗?)

结果:它有效,但仅适用于此特定URL。保持每个可能路线的清单肯定不是要走的路。

你有没有处理过这个问题?我非常感谢您的投入!

asp.net performance azure asp.net-mvc-4 azure-web-sites
2个回答
3
投票

自从我在一个托管在azure上的组织工作已经有一段时间但是他们曾经有一个可以配置标记为“Always On”的选项,这实际上相当于在应用程序池上将空闲超时设置为零并将您的应用程序加载到内存中。如果没有流量,那么您的站点将被卸载并在首次命中时被强制转换为JIT(有点像初始部署后)。

我已经读过其他人为他们的网站创建模拟http请求以保持流量上升并避免在他们订阅不提供“永远在线”选项的较低价格层时从内存中卸载。

编辑:这是解决它的另一个SO帖子:App pool timeout for azure web sites


1
投票

除了接受的答案,我想详细解释我最终如何处理这个问题。也许这可能在将来帮助别人。我写了一些代码,通过简单地在关键站点上触发Web请求来启动应用程序(我已经获得了每个页面都需要完成的经验。只需预热根域地址是不够的)。

private void WarmUp()
{
  var baseUrl = "https://foo.azurewebsites.net";

  /**
   * Requests to protected pages need to be authenticated and authorized, otherwise the JIT-Compile won't work
   * For ASP.NET apps that are using FormsAuthentication just send a POST-request as you normally would do using a html form,
   * then grab the cookie you get in the response and pass it to the subsequent requests
   * */
  var email = "[email protected]";
  var password = "verysecure";
  var cookies = new CookieContainer();

  var webRequest = WebRequest.Create($"{baseUrl}/Account/Login") as HttpWebRequest;
  webRequest.Method = "POST";
  webRequest.ContentType = "application/x-www-form-urlencoded";
  webRequest.CookieContainer = cookies;

  var requestWriter = new StreamWriter(webRequest.GetRequestStream());
  requestWriter.Write($"user={email}&password={password}");//Small example for brevity. Don't forget to extract the requestVerificationToken in production :-)
  requestWriter.Close();
  webRequest.GetResponse().Close();

  var urls = new[] {
    baseUrl,
    $"{baseUrl}/Home/Contact",
    $"{baseUrl}/Protected/Stuff",
    //...
  };
  foreach (var url in urls)//trigger web-requests
  {
    webRequest = WebRequest.Create(url) as HttpWebRequest;
    webRequest.CookieContainer = cookies;
    webRequest.GetResponse().Close();
  }
}

这会在应用程序启动时/部署后触发耗时的JIT内容,从而阻止我们的用户在请求页面时遇到可怕的性能。如果您的应用的定价计划是S1或更高,您可以使用deployment slots进一步提高性能。它们允许您在部署到生产之前预热应用程序。

在我的情况下(保留定价层,B1),我认为在Application_Start中运行上面的代码就足够了,因为«Always on»应该阻止我的应用程序的工作进程自动关闭,以防网站没有得到任何一段时间内的流量(如果您的应用程序在共享资源上运行,请确保使用Cron作业或类似工具保持您的应用程序存活)。

© www.soinside.com 2019 - 2024. All rights reserved.