Как кэшировать файлы более 1 МБ с помощью rack / cache на Heroku?
Я использую комбинацию Стрекоза и стойки/кэш размещенного на Heroku.
Я использую Dragonfly для загруженных активов. Миниатюры обрабатываются на лету и хранятся в стойке / кэше для быстрой доставки из memcached (через Memcachier аддон).
регулярные статические активы также кэшируются в memcached через rack / cache.
моя проблема в том, что любые загруженные файлы более 1 МБ вызывают ошибку 500 в моем приложение.
2013-07-15T10:38:27.040992+00:00 app[web.1]: DalliError: Value too large, memcached can only store 1048576 bytes per key [key: d49c36d5db74ef45e957cf169a0b27b83b9e84de, size: 1502314]
2013-07-15T10:38:27.052255+00:00 app[web.1]: cache: [GET /media/BAhbBlsHOgZmSSIdNTA3Njk3ZWFiODBmNDEwMDEzMDAzNjA4BjoGRVQ/WTW_A5Flyer_HealthcareMedicalObsGynae_WEB.pdf] miss, store
2013-07-15T10:38:27.060583+00:00 app[web.1]: !! Unexpected error while processing request: undefined method `each' for nil:NilClass
Memcache имеет предел 1 МБ, поэтому я могу понять, почему мой актив не был кэширован, но я бы предпочел, чтобы он не нарушал обслуживающие активы.
Я даже не уверен, откуда эта ошибка. Предположительно, от одного из других промежуточных устройств rack?
увеличение максимального размера файла, похоже, не влияет.
config.cache_store = :dalli_store, ENV["MEMCACHIER_SERVERS"].split(","), {¬
:username => ENV["MEMCACHIER_USERNAME"],¬
:password => ENV["MEMCACHIER_PASSWORD"],¬
:value_max_bytes => 5242880 # 5MB¬
}
в долгосрочной перспективе я знаю, что перемещение такого рода активов с Heroku является разумным шагом, но это не быстрая работа.
что я могу сделать, чтобы обслуживать эти активы на Heroku, в то же время без ошибок?
3 ответов
у меня была та же проблема, что и @jordelver, и мне удалось обойти пределы memcachier, исправив обезьяну Dragonfly::Response
:
module Dragonfly
class Response
private
def cache_headers
if job.size > 1048576
{
"Cache-Control" => "no-cache, no-store",
"Pragma" => "no-cache"
}
else
{
"Cache-Control" => "public, max-age=31536000", # (1 year)
"ETag" => %("#{job.signature}")
}
end
end
end
end
по существу, если размер превышает 1048576 байт, отправьте заголовок без кэша.
Так вопреки вопросу @jordelver, я нахожу, что установка :value_max_bytes
опция dalli работает. Я настраиваю Rack:: Cache немного по-другому, что, возможно, имеет значение.
Это то, что моя production.rb
содержит для настройки Rack:: Cache:
client = Dalli::Client.new(ENV["MEMCACHIER_SERVERS"],
:username => ENV["MEMCACHIER_USERNAME"],
:password => ENV["MEMCACHIER_PASSWORD"],
:value_max_bytes => 10485760)
config.action_dispatch.rack_cache = {
:metastore => client,
:entitystore => client
}
config.static_cache_control = "public, max-age=2592000"
с вышеизложенным некоторые ошибки будут напечатаны в журналах для значений более 1 МБ, но они не вызовут ошибку 5xx для клиента, просто пропуск кэша.
P. S Я работаю на MemCachier:) Итак мы заинтересованы в том, чтобы разобраться с этим. Пожалуйста, дайте мне знать, если это работает.
мой application.js
был слишком велик для rack-cache
Так я и сделал:
# in config/environments/development.rb
config.action_dispatch.rack_cache = {
metastore: 'file:/var/cache/rack/meta',
entitystore: 'file:tmp/cache/rack/body'
}
и это работает!
хранит метаданные в memcache, но фактический файл в файловой системе, а не в памяти.