Как предотвратить Rails 3.1 от кэширования статических ресурсов в Rails.cache? - PullRequest
19 голосов
/ 06 августа 2011

Я использую CloudFlare CDN в своем приложении Rails 3.1. Cloudflare - это CDN, который работает на уровне DNS. При первом обращении к статическому ресурсу CloudFlare загружает его из вашего приложения, а затем кэширует в своем CDN. Будущие запросы на загрузку этого ресурса из CDN вместо вашего приложения.

Проблема, с которой я столкнулся, заключается в том, что если вы установите для кэширования контроллера значение true:

config.action_controller.perform_caching = true

включает промежуточное программное обеспечение Rack :: Cache. Поскольку Rails устанавливает параметр управления кэшем по умолчанию для статических ресурсов, эти активы записываются в хранилище Rails.cache. В результате мое хранилище кеша (в моем случае redis) заполняется статическими ресурсами с URL-адресом в качестве хеш-ключа.

К сожалению, я не могу отключить заголовки управления статическим кэшем ресурсов, не влияя на то, как Cloudflare и браузеры моих пользователей кэшируют активы. Я не могу отключить кэширование контроллера или теряю кэширование страницы / действия / фрагмента. Тот же результат, если я удаляю промежуточное ПО Rack :: Cache.

У кого-нибудь есть другие идеи?

Обновление: я открыл тикет на GitHub здесь .

Ответы [ 4 ]

8 голосов
/ 10 августа 2011

После долгих экспериментов я сделал это в моем config / application.rb:

if !Rails.env.development? && !Rails.env.test?
  config.middleware.insert_before Rack::Cache, Rack::Static, urls: [config.assets.prefix], root: 'public'
end

Для этого нужно добавить промежуточное ПО Rack :: Static rack перед запросами в Rack:: Cache.Промежуточное программное обеспечение Rack :: Static предоставляет URL-адреса с соответствующим префиксом в корневой каталог.Здесь я даю config.assets.prefix в качестве моего префикса url, который по умолчанию равен «/ assets».Я устанавливаю корень для общедоступного каталога.

Запросы по этому пути:

/ assets / jquery-e8da439bbc8fd345e34ac57c6a216318.min.js

должен найти его в этом файле:

public / assets / jquery-e8da439bbc8fd345e34ac57c6a216318.min.js

Это должно обслуживать любые активы непосредственно из открытых источников / активовдиректории вместо того, чтобы нажимать Rails :: Cache вообще, что предотвратит сохранение ресурсов в Rails cache_store.Это будет работать только в том случае, если вы используете 'rake assets: precompile' на производстве, иначе в 'public / assets' не будет предварительно скомпилированных активов.

7 голосов
/ 29 мая 2012

Оригинальный плакат хотел предотвратить попадание статических ресурсов в общий кеш Rails, из-за чего они захотели отключить Rack :: Cache.Вместо этого лучше настроить Rack :: Cache на использование отдельного кэша, чем общего кэша Rails.

Rack :: Cache должен быть настроен по-разному для хранения сущностей и хранилищ мета.Rack :: Cache имеет две разные области хранения: мета и хранилища сущностей.Метасторка хранит информацию высокого уровня о каждой записи в кэше, включая HTTP-запрос и заголовки ответа.В этой области хранятся небольшие фрагменты данных, к которым осуществляется доступ с высокой частотой.Хранилище сущностей кэширует содержимое тела ответа, которое может представлять собой относительно большой объем данных, хотя к нему обращаются реже, чем в метастазах.

Приведенная ниже конфигурация кэширует информацию о метастазах в memcached, но фактическое тело активов вфайловая система.

Использование memcached gem:

config.action_dispatch.rack_cache = {
  :metastore    => 'memcached://localhost:11211/meta',
  :entitystore  => 'file:tmp/cache/rack/body',
  :allow_reload => false
}

Использование dalli gem

config.action_dispatch.rack_cache = {
  :metastore    => Dalli::Client.new,
  :entitystore  => 'file:tmp/cache/rack/body',
  :allow_reload => false
}

Кстати, эта конфигурация является рекомендацией для Heroku: https://devcenter.heroku.com/articles/rack-cache-memcached-static-assets-rails31

3 голосов
/ 22 июня 2013

Вы можете отключить кэширование файлов конвейера активов, оставив другое кэширование на месте с помощью:

config.assets.cache_store = :null_store

Это должно помешать Sprockets что-либо кэшировать.

1 голос
/ 17 февраля 2012

Другим способом решения той же проблемы, и этой проблемы, является использование промежуточного программного обеспечения ActionDispatch :: Static вместо Rack :: Static, например:

if !Rails.env.development? && !Rails.env.test?
  config.middleware.insert_before Rack::Cache, ::ActionDispatch::Static, 'public', config.static_cache_control
end

В чем разница между Rack :: Static и ActionDispatch :: Static, спросите вы?

  • Rack :: Static принимает массив префиксов url для сверки с URL-адресом запроса. Таким образом, в нашем случае он будет проверять файлы только в том случае, если путь запроса начинается с '/assets' .

  • ActionDispatch :: Static будет проверять наличие файла в 'public' при каждом запросе GET / HEAD, независимо от пути.

  • Rack :: Static сначала не проверяет файл, он вызывает Rack :: File.new для файла, поэтому, если он не существует, он возвращает 404, он не пропустит запрос вниз по цепочке промежуточного программного обеспечения.

  • Если ActionDispatch :: Static не найдет файл в своем пути, он продолжит цепочку промежуточного программного обеспечения стойки (остальная часть стека Rails).

В конце концов, независимо от того, что ActionDispatch :: Static не найдет в 'public', оно будет просто передано в стек Rails. Таким образом, Rails будет обслуживать ресурсы, которые ActionDispatch :: Static не может найти. Это решает мою проблему с ресурсами, не найденными Rack :: Cache, но это также более ресурсоемкое, так как каждый запрос вызывает проверку файла.

...