【问题标题】:Strategies for "Pre-Warming" an ASP.NET Cache“预热” ASP.NET 缓存的策略
【发布时间】:2011-02-08 04:23:37
【问题描述】:

我有一个 ASP.NET MVC 3 / .NET Web 应用程序,它大量由数据驱动,主要围绕“位置”的概念(纽约、加利福尼亚等)。 p>

无论如何,我们有一些非常繁忙的数据库查询,它们在完成后会被缓存。

例如:

public ICollection<Location> FindXForX(string x)
{
   var result = _cache.Get(x.ToKey()) as Locaiton; // try cache

   if (result == null) {
      result = _repo.Get(x.ToKey()); // call db
      _cache.Add(x.ToKey(), result); // add to cache
   }

   return result;
}

但我不想让倒霉的第一个用户等待这个数据库调用。

数据库调用可能需要 40-60 秒,远远超过 ASP.NET 请求的默认超时时间。

我想在我的应用启动时或之后不久为某些“热门”位置(例如纽约、加利福尼亚)“预热”这些呼叫。

我不想简单地在 Global asax (Application_Start) 中执行此操作,因为启动应用程序需要很长时间。 (我计划预先缓存大约 15 个位置,因此只需几分钟的工作时间)。

有什么方法可以异步触发这个逻辑?也许旁边的服务是更好的选择?

我能想到的唯一其他选择是有一个管理页面,其中包含用于这些操作的按钮。因此,一旦应用程序启动,管理员(例如我)就可以触发这些查询。这将是最简单的解决方案。

有什么建议吗?

【问题讨论】:

  • “数据库调用可能需要 40-60 秒” - 我假设您有适当的索引?
  • 是的,这似乎是一个很长的查询。您应该尝试提高效率——甚至可以摆脱这个预热问题! :)
  • @Mitch 什么 - 是的,我们有索引。这是我能做到的最快的。如果我们有一个查询“查找纽约的所有位置”,它需要查找所有城市、社区、街道。可能是 500 万条记录。一个错误的查询可以节省 500 万个其他查询,这些查询现在由于缓存而变得多余。值得,相信我 - 有一种疯狂的方法。 :)
  • "我能做到的一样快" - 你确定吗?多少逻辑读?
  • @RPM1984:旁注,真棒 gravatar!

标签: asp.net asp.net-mvc caching .net-4.0 asp.net-mvc-3


【解决方案1】:

查看 IIS 7.5 的 "Always running" 应用设置。这基本上要做的是在现有应用程序池要回收时准备好一个应用程序池。当然,第一次需要 40-60 秒,但之后会很快,除非你重新启动机器。

【讨论】:

    【解决方案2】:

    快速而肮脏的方法是从Application_Start 触发Task

    但是我发现将这个功能封装到一些基础设施中是很好的,这样您就可以创建一个 ~/Admin/CacheInfo 页面来让您监控可能正在处理的进度、状态和异常加载缓存。

    【讨论】:

      【解决方案3】:

      在开始缓存预热之前,我建议您首先查看查询正在执行多少逻辑读取,以检查查询是否“尽可能快”。

      【讨论】:

        【解决方案4】:

        听起来您应该只是将结果转储到单独的表中,并有一个计划任务定期重新填充该表。

        如果一个预先计算的表格不够用,因为它最终包含太多需要搜索的数据,您可以使用多个。

        【讨论】:

          【解决方案5】:

          一种解决方案是在您的Application_Start 方法中启动一个工作线程,该线程在后台进行预热。如果你做对了,你的应用启动就不会花更长的时间,因为线程会异步执行。

          【讨论】:

          • 他在他的问题中说他不想这样做。
          • @Shan Plourde - 我说我不想在 application_start 方法中等待,但工作线程会很好。不过目前,我倾向于我最初的提议(一个管理页面,这样我可以更好地监控缓存,手动使项目无效,预热它们等)。
          • 嗯,您的声明“我不想简单地在 Global asax (Application_Start) 中执行此操作,因为该应用程序启动时间太长。(我计划预缓存大约 15 个位置) ,所以这是几分钟的工作)。”似乎与您的评论有点不同......所以是的,Application_Start 会很好用
          【解决方案6】:

          一种选择是使用网站健康监测服务。它既可用于检查网站的健康状况,也可用于在足够频繁的情况下调用您的常用 URL。

          【讨论】:

            【解决方案7】:

            正如 Scott 所说,在 Task 中从 Application_Start 加载是可行的方法。

            请注意 - 如果您的网站重新启动并且有 10 个人尝试查看加利福尼亚,您不希望有 10 个 _repo.Get(x.ToKey()); // call db 实例同时尝试加载相同的数据。

            在应用程序状态中存储一个布尔值"IsPreloading" 可能是个好主意。在预加载函数的开头将其设置为true,在末尾设置为false。如果设置了该值,请确保您不加载 FindXForX 中的 15 个预加载位置中的任何一个。

            【讨论】:

            【解决方案8】:

            建议查看auto-starting 您的应用,尤其是在负载平衡的情况下。

            【讨论】:

              猜你喜欢
              • 2011-11-12
              • 2010-10-26
              • 2011-04-09
              • 1970-01-01
              • 2017-11-30
              • 1970-01-01
              • 2010-12-12
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多