Rails: как лучше заново заполнить кеш при аннулировании - PullRequest
0 голосов
/ 05 марта 2012

для дорогостоящей генерируемой страницы или действия, стандартный подход Rails к кешированию требует аннулирования страницы / действия, когда их базовые данные становятся достаточно устаревшими. Затем следующий пользователь, который запрашивает эту страницу, должен сидеть там в течение N секунд, когда происходит потеря кэша и создается страница. Если N достаточно большое, это сделает этого пользователя грустным. Конечно, это только один пользователь, но если аннулирования достаточно часты, у нас может быть много грустных пользователей.

Одно из решений заключается в том, чтобы всякий раз, когда я отменял действие некоторых страниц / действий, также запускал рендеринг новых версий страниц / действий и помещал их в кэш. Для создания нужной мне версии потребуется несколько часов.

Но, конечно, кто-то еще уже занимался этой проблемой? Я оглянулся и не смог найти подходящих камней или ответов.

Спасибо!

Ответы [ 3 ]

0 голосов
/ 05 марта 2012

Типичным решением для аннулирования кэша в рельсах является подметальные машины. Это техника для автоматического аннулирования кэша. Вы можете прочитать больше о подметальных машинах в этом руководстве

0 голосов
/ 06 марта 2012

Наконец-то нашли вопрос и ответ:
В: «Кэш прогрева» при развертывании
A: https://stackoverflow.com/a/942774/593053

Оставив здесь мой вопрос, чтобы другие могли идти по следу и учиться от моей боли.

Также актуально: Rails 3.2: Предварительный рендеринг (запекание) кеша новой страницы сразу после истечения срока действия?

Мое полное решение состояло в том, чтобы принять соглашение, что если cache=regen находится в запрошенном URL, это означает, что сгенерированная страница должна быть помещена в кеш.

Для контроллеров, для которых требуется кэширование, include CacheRegen. CacheRegen заставляет контроллер не читать из кэша, когда cache = regen, и не помещать cache = regen в ключ при хранении в кэше.

Код для которого:

module CacheRegen
  def read_fragment(key, options = nil)
    if /cache=regen/.match(key)
      logger.info("forcing cache miss due to param cache=regen, key=#{key}")
      return nil
    end
    super(key, options)
  end

  def write_fragment(key, content, options = nil)
    unless key.sub!(/cache=regen/, '').nil?
      key.sub!(/\?\&/, '?')
      key.sub!(/\&\&/, '&')
      key.sub!(/\?$/, '')
      key.sub!(/\&$/, '')
      logger.info("wrote page to cache with key #{key}")
    end
    super(key, content, options)
  end
end

Наконец, я поместил следующий код в new_pages.rake:

require 'action_dispatch'

def get_url(sess, url)
      uri = "http://YOURSITE.com/" + url + "cache=regen"
      puts "retrieving " + uri
      foo = sess.get(uri)
      puts "got it. #{foo}, #{sess.response.body.length} bytes"
end

desc "If necessary, generate new versions of the most expensive pages"
task :new_pages => :environment do
    puts "Updating pages..."
    sess = ActionDispatch::Integration::Session.new(Rails.application)
    ["controller1", "controller2", "controller3"].each { |noun|
      get_url(sess, noun + "?")
    }

    puts "done."
end

И в моем окружении у меня есть задача deploy, которая зависит от задачи new_pages.

Есть ли какой-нибудь драгоценный камень, который делает все это более автоматическим?

0 голосов
/ 05 марта 2012

Я предполагаю, что дорогостоящие вычисления - это не рендеринг HTML-страницы, а запросы и / или вычисления, необходимые для заполнения страницы.

Как вы сказали, вы должны инициировать этот расчет / запрос, когда он станет недействительным, чтобы он был мгновенно доступен при следующем доступе к странице.

Вы можете хранить данные в различных форматах: YAML, дамп Marshal, JSON, CSV и т. Д. Кроме того, если вы пойдете по этому пути, я бы сохранил его где-нибудь постоянно, например, в файловой системе или вашей базе данных, а не в Rails. кеш, потому что кеш Rails не всегда содержит ваши данные.

...