2013-07-15 35 views
8

Tôi đang sử dụng kết hợp Dragonflyrack/cache được lưu trữ trên Heroku.Làm cách nào để lưu trữ các tệp trên 1MB với giá/bộ nhớ cache trên Heroku?

Tôi đang sử dụng Dragonfly cho nội dung được tải lên. Hình thu nhỏ được xử lý nhanh chóng và được lưu trữ trong giá/bộ nhớ cache để phân phối nhanh từ memcached (thông qua Memcachier addon).

Nội dung tĩnh thông thường cũng được lưu trong bộ nhớ đệm qua giá/bộ nhớ cache.

Vấn đề của tôi là bất kỳ tệp tải lên nào trên 1MB đều gây ra lỗi 500 trong ứng dụng của tôi.

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 có giới hạn 1MB, vì vậy tôi có thể hiểu tại sao nội dung của tôi không được lưu vào bộ nhớ cache nhưng tôi không muốn phân phối nội dung.

Tôi thậm chí không chắc chắn lỗi này đến từ đâu. Có lẽ từ một trong những phần mềm giá khác?

Tăng kích thước tệp tối đa dường như không có bất kỳ ảnh hưởng nào.

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

Dài hạn, tôi biết việc di chuyển loại tài sản này ra khỏi Heroku là một động thái hợp lý, nhưng đó không phải là công việc nhanh.

Tôi có thể làm gì để phân phát các nội dung này trên Heroku trong thời gian chờ đợi mà không có lỗi?

Trả lời

7

tôi đã có vấn đề tương tự như @jordelver và quản lý để có được giới hạn vòng memcachier bằng khỉ vá 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 

Về cơ bản, nếu kích thước là hơn 1.048.576 byte, gửi một tiêu đề no-cache.

+0

giải pháp này đã thành công với tôi. Cảm ơn! – Francois

+1

FYI có API để thay đổi tiêu đề mà không cần vá lỗi khỉ - xem http://markevans.github.io/dragonfly/configuration/ (bit "response_header") –

9

Vì vậy, trái với câu hỏi của @ jordelver, tôi thấy rằng thiết lập tùy chọn :value_max_bytes của dalli không hoạt động. Tôi đang thiết lập Rack :: Cache theo một cách hơi khác có thể tạo nên sự khác biệt.

Đây là những gì tôi production.rb chứa để cấu hình 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" 

Với trên, một số lỗi sẽ được in vào nhật ký cho các giá trị trên 1MB, nhưng họ sẽ không gây ra một lỗi 5xx cho khách hàng, chỉ cần một bộ nhớ cache bỏ lỡ.

P.S Tôi làm việc cho MemCachier :) vì vậy chúng tôi quan tâm đến việc cố gắng sắp xếp điều này. Xin vui lòng cho tôi biết nếu nó hoạt động.

+0

đặt giá trị value_max_bytes cao hơn không hoạt động trong trường hợp của tôi. – Francois

+0

Điều này đã giúp tôi đi đúng hướng trên một vấn đề hơi khác, vì vậy cảm ơn David :) – robotmay

+0

Để làm điều đó theo cách này, bạn phải cài đặt giá-bộ nhớ đệm đá quý. Bình thường, bạn bật dalli trong 'environment/development.rb' bằng cách thêm' config.cache_store =: dalli_store'.Bạn có thể chỉ định value_max_bytes ở đây không? Cảm ơn bạn –

0

application.js của tôi là quá lớn cho rack-cache vì vậy tôi đã làm:

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

Và nó hoạt động!

Lưu trữ siêu dữ liệu trong memcache nhưng tệp thực trong hệ thống tệp chứ không phải trong bộ nhớ.

+1

Đây không phải là ý tưởng hay nếu bạn đang chạy trên Heroku Dynos sẽ chia sẻ metastore nhưng không chia sẻ hệ thống tập tin. Điều này có nghĩa rằng đôi khi tập tin của bạn sẽ được lưu trữ theo metastore nhưng thiếu từ hệ thống tập tin và nó sẽ không được tìm thấy. – jordelver

+0

Bạn có đề xuất lưu trữ tệp trong Memcache không? – Dorian

+0

Và BTW, đây là dành cho 'development.rb' – Dorian

Các vấn đề liên quan