2013-07-15 20 views
8

Używam kombinacji Dragonfly i rack/cache hostowanych na Heroku.Jak buforować pliki powyżej 1 MB z szafą/pamięcią podręczną na Heroku?

Używam Dragonfly do przesłanych zasobów. Miniatury są przetwarzane "w locie" i przechowywane w stelażu/pamięci podręcznej w celu szybkiej dostawy z memcached (poprzez Memcachier addon).

Regularne aktywa statyczne są buforowane w memcached poprzez rack/cache.

Moim problemem jest to, że wszystkie przesłane pliki ponad 1MB powodują błąd 500 w mojej aplikacji.

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 ma limit 1MB, więc mogę zrozumieć, dlaczego mój składnik nie został buforowane, ale wolałbym go nie złamał aktywów stanowiących.

Nie jestem nawet pewien, skąd ten błąd pochodzi. Prawdopodobnie z jednego z innych middleware?

Zwiększenie maksymalnego rozmiaru pliku nie wydaje się mieć żadnego wpływu.

config.cache_store = :dalli_store, ENV["MEMCACHIER_SERVERS"].split(","), {¬ 
    :username  => ENV["MEMCACHIER_USERNAME"],¬ 
    :password  => ENV["MEMCACHIER_PASSWORD"],¬ 
    :value_max_bytes => 5242880 # 5MB¬ 
} 

długoterminowe, wiem, że przejście tego rodzaju aktywów off Heroku to sensowne posunięcie, ale to nie będzie szybka praca.

Co mogę zrobić, aby służyć te aktywa na Heroku w międzyczasie bez błędów?

Odpowiedz

7

miałem ten sam problem jak @jordelver i udało się granice okrągłego memcachier poprzez małpa łatanie 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 

Zasadniczo, jeśli rozmiar jest ponad 1048576 bajtów, wysyłać nagłówek no-cache.

+0

to rozwiązanie z powodzeniem działało dla mnie. Dzięki! – Francois

+1

FYI jest API do zmiany nagłówków bez poprawiania małp - patrz http://markevans.github.io/dragonfly/configuration/ (bit "response_header") –

9

Więc wbrew użytkownika @ jordelver pytanie, uważam, że ustawienie opcji Dalli :value_max_bytes działa. Konfiguruję Rack :: Cache w nieco inny sposób, co być może robi różnicę.

To właśnie mój production.rb zawiera skonfigurować 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" 

z powyższym niektóre błędy zostaną wydrukowane w dziennikach o wartości ponad 1 MB, ale nie spowoduje błąd 5xx dla klienta brakuje tylko pamięci podręcznej.

P.S pracuję MemCachier :) więc jesteśmy zainteresowani starają się to rozwiązać. Daj mi znać, jeśli to działa.

+0

Ustawienie wyższej wartości value_max_bytes nie zadziałało w moim przypadku. – Francois

+0

Pomogło mi to we właściwym kierunku na nieco inny problem, więc dziękuję David :) – robotmay

+0

Aby to zrobić w ten sposób, musisz zainstalować klejnot szafy rack. Zwykle włączasz dalli w 'environments/development.rb', dodając' config.cache_store =: dalli_store'.Czy możesz podać tutaj wartość_max_bytes? Dziękuję –

0

My application.js był zbyt duży dla rack-cache tak zrobiłem:

# in config/environments/development.rb 
config.action_dispatch.rack_cache = { 
    metastore: 'file:/var/cache/rack/meta', 
    entitystore: 'file:tmp/cache/rack/body' 
} 

I to działa! metadane

Sklepy w memcache ale rzeczywistego pliku w systemie plików, a nie w pamięci.

+1

To nie jest dobry pomysł, jeśli używasz Heroku jako Dynos podzieli metastore, ale nie system plików. Oznacza to, że czasami twój plik zostanie zbuforowany zgodnie z metastorem, ale brakuje go w systemie plików i nie zostanie odnaleziony. – jordelver

+0

Czy zalecamy przechowywanie plików w Memcache? – Dorian

+0

I BTW, to jest dla 'development.rb' – Dorian

Powiązane problemy