2012-03-31 30 views
17

Tôi đang sử dụng sương mù với carrierwave trong trang web của mình. Nhưng hình ảnh tải rất chậm.Sử dụng CDN với carrierwave + fog trong s3 + cloudfront với đường ray 3.1

Sau đó, tôi muốn tăng tốc độ tải hình ảnh bằng CDN.

Tôi đã theo hướng dẫn này để tạo ra các CDN cho hình ảnh:

http://maketecheasier.com/configure-amazon-s3-as-a-content-delivery-network/2011/06/25

bây giờ tôi đã phân phối của mình triển khai cho hình ảnh nhưng tôi không biết làm thế nào hoạt động tốt các cdn. Tôi có trong initializers/fog.rb cấu hình tiếp theo:

CarrierWave.configure do |config| 
    config.fog_credentials = { 
    :provider    => 'AWS', 
    :aws_access_key_id  => 'key', 
    :aws_secret_access_key => 'key', 
    :region     => 'eu-west-1' 
    } 
    config.fog_host = "http://da33ii2cvf53u.cloudfront.net" #config.asset_host instead of config.fog_host for new fog gem versions 
    config.fog_directory = 'pin-pro' 
    config.fog_public  = false 
    #config.fog_attributes = {'Cache-Control' => 'max-age=315576000'} 
end 

Tôi không biết nếu điều này là chính xác, nhưng trong máy địa phương của tôi nó không hoạt động tốt cho tôi. Tôi thấy vị trí hình ảnh, là con đường giống như trước:

https://s3-eu-west-1.amazonaws.com/pin-pro/uploads/pins/medium_610cafbe-5d43-4223-ab0e-daa4990863c4.jpg?AWSAccessKeyId=AKIAIDX34WHYKB3ZKFVA&Signature=RwQriNpiRXaTxyfYVvYjsvclUa8%3D&Expires=1333203059 

Làm thế nào tôi có thể thêm một CDN để sương mù tập tin trong carrierwave với s3 và CloudFront?

+0

Nếu tôi sử dụng cài đặt đó: 'fog_host', sau đó tôi nhận được lỗi này: phương thức chưa xác định' fog_host = 'cho CarrierWave :: Trình tải lên :: Cơ sở: Lớp Phiên bản nào của carrierwave là những người đang sử dụng? –

+0

Bạn nên sử dụng 'config.asset_host' thay vì' config.fog_host'. Tôi đã thêm vấn đề này vào câu hỏi. Chúc may mắn! – hyperrjas

+0

Có, tôi nhận thấy rằng, sau khi đào một số :) Cảm ơn. –

Trả lời

7

Có vẻ như bạn chưa thêm dòng bên dưới vào cấu hình của mình. Bạn sẽ cần phải thay thế địa chỉ mẫu bên dưới bằng địa chỉ trên đám mây của bạn từ Amazon.

Từ README github: https://github.com/jnicklas/carrierwave

"Bạn có thể tùy chọn bao gồm tên máy chủ CDN của bạn trong cấu hình này là rất khuyến khích, như không có nó mọi yêu cầu đòi hỏi một tra cứu các thông tin này."

config.asset_host = "http://c000000.cdn.rackspacecloud.com"

+0

Tính năng này không hoạt động với nội dung riêng tư của CloudFront. – Allen

6

có vẻ như amazon cdn không hoạt động với config.fog_public = false, do đó, các tệp riêng tư chỉ có thể truy cập từ s3, không phải từ cdn

10

CarrierWave sẽ không wor k khi bạn đặt config.fog_public = false điểm config.asset_host thành phân phối CloudFront. Điều này đã được ghi nhận nhiều lần:

https://github.com/carrierwaveuploader/carrierwave/issues/1158 https://github.com/carrierwaveuploader/carrierwave/issues/1215

Trong một dự án gần đây tôi đã hạnh phúc bằng CarrierWave để xử lý tải lên S3, nhưng muốn nó trả về một URL CloudFront ký khi sử dụng Model.attribute_url. Tôi đã đưa ra giải pháp sau (phải thừa nhận xấu xí) mà tôi hy vọng những người khác có thể hưởng lợi từ hoặc cải thiện:

Thêm đá quý 'cloudfront-signer' vào dự án của bạn và định cấu hình theo hướng dẫn. Sau đó, thêm ghi đè sau /lib/carrierwave/uploader/url.rb trong một file mới trong config/initializers (chú ý nhiều chèn của AWS :: CF :: Signer.sign_url):

module CarrierWave 
     module Uploader 
     module Url 
      extend ActiveSupport::Concern 
      include CarrierWave::Uploader::Configuration 
      include CarrierWave::Utilities::Uri 

      ## 
      # === Parameters 
      # 
      # [Hash] optional, the query params (only AWS) 
      # 
      # === Returns 
      # 
      # [String] the location where this file is accessible via a url 
      # 
      def url(options = {}) 
      if file.respond_to?(:url) and not file.url.blank? 
       file.method(:url).arity == 0 ? AWS::CF::Signer.sign_url(file.url) : AWS::CF::Signer.sign_url(file.url(options)) 
      elsif file.respond_to?(:path) 
       path = encode_path(file.path.gsub(File.expand_path(root), '')) 

       if host = asset_host 
       if host.respond_to? :call 
        AWS::CF::Signer.sign_url("#{host.call(file)}#{path}") 
       else 
        AWS::CF::Signer.sign_url("#{host}#{path}") 
       end 
       else 
       AWS::CF::Signer.sign_url((base_path || "") + path) 
       end 
      end 
      end 

     end # Url 
    end # Uploader 
end # CarrierWave 

Sau đó ghi đè /lib/carrierwave/storage/fog.rb bằng cách thêm dòng sau vào dưới cùng của cùng một tập tin:

require "fog" 

module CarrierWave 
    module Storage 
    class Fog < Abstract 
     class File 
      include CarrierWave::Utilities::Uri 
      def url 
      # Delete 'if statement' related to fog_public 
      public_url 
      end 
     end 
    end 
    end 
end 

Cuối cùng, trong config/initializers/carrierwave.rb:

config.asset_host = " http://d12345678.cloudfront.net "

config.fog_public = false

Vậy là xong. Bây giờ bạn có thể sử dụng Model.attribute_url và nó sẽ trả về một CloudFront URL đã ký cho một tệp tin riêng được tải lên bởi CarrierWave vào thùng S3 của bạn.

1

Sau khi một số tìm kiếm và đấu tranh với điều này trong một thời gian dài, tôi đã tìm thấy một trang có nội dung rằng CarrierWave không hỗ trợ các url được ký CloudFront. Các url được đăng nhập CloudFront khác với các url đã đăng ký của S3, điều này khiến tôi bị nhầm lẫn. Một khi tôi đã tìm ra điều đó, nó dễ dàng hơn nhiều để biết phải làm gì.

Nếu bạn định cấu hình CarrierWave với config.fog_public = false thì nó sẽ tự động bắt đầu ký S3 url, nhưng không thể định cấu hình để hoạt động với Fog và nội dung riêng tư CloudFront trong phiên bản CarrierWave tôi đang sử dụng (1.0.0). Tôi thậm chí đã thử sử dụng đá quý carrierwave-aws và điều đó cũng không giúp được gì.

Vậy điều gì sẽ xảy ra là CarrierWave sẽ ký vào URL và dẫn chương trình sẽ giống như thế này:

https://my_bucket_name.s3-us-west-2.amazonaws.com/uploads/...?signature... 

Đó chỉ trực tiếp đến xô S3, nhưng tôi cần nó để trỏ đến CloudFront. Tôi cần các máy chủ để trông như thế này:

https://s3.cloudfront_domain_name.com/uploads/... 

Và điều gì sẽ xảy ra nếu tôi đặt config.asset_host bằng vị trí CloudFront của tôi là tôi muốn có được điều này, (với dấu gạch chéo kép trước khi "cập nhật"):

https://s3.cloudfront_domain_name.com//uploads/... 

Điều đó cũng đã làm rõ rằng CarrierWave chưa được thiết kế để sử dụng với CloudFront. Hy vọng rằng họ sẽ cải thiện nó. Đây là công việc của tôi. Đó là xấu xí, nhưng nó đã làm việc để có được những gì tôi cần mà không cần phải sửa đổi CarrierWave, vì tôi hy vọng CarrierWave sẽ hỗ trợ cho CloudFront tại một số điểm.

  1. Trước tiên, tôi đã tìm regex/thay thế url của mình và xóa phần máy chủ S3 và đặt vào phần lưu trữ CloudFront của tôi. cf_url = s3_url.gsub("my_bucket_name.s3-us-west-2.amazonaws.com", "s3.cloudfront_domain_name.com")
  2. Tiếp theo, tôi đã regex khác tìm/thay thế để loại bỏ các S3 ký url vào cuối của chuỗi: non_signed_cf_url = cf_url.gsub(/\?.+/, '') Điều này là do chữ ký sẽ không chính xác vì nó được sử dụng API cho S3 và không cho CloudFront cho ký URL.
  3. Bây giờ tôi ký lại URL bản thân mình, bằng cách sử dụng cloudfront-signer đá quý: signed_cf_url = Aws::CF::Signer.sign_url(non_signed_cf_url, :expires => 1.day.from_now)

Có một vài điều khác mà bạn cần phải nhận thức được khi phục vụ nội dung riêng tư trên CloudFront:

  • Trong Cài đặt Hành vi Cache cho mẫu đường dẫn của bạn (không nhất thiết là mẫu mặc định), hãy đặt: "Hạn chế quyền truy cập của người xem (Sử dụng URL đã ký hoặc Cookie đã ký)" tới "Có"
  • Đặt "Trusted Người ký "tới" tự "
  • Đặt" Chuyển tiếp chuỗi truy vấn và lưu vào bộ đệm "để" Chuyển tiếp tất cả, bộ đệm dựa trên tất cả "nếu bạn muốn sử dụng các chuỗi truy vấn khác nhiều hơn chữ ký CloudFront trong url của mình, chẳng hạn như response-content-dispositionresponse-content-type (Tôi có thể làm cho chúng hoạt động thành công, nhưng chúng phải được url_encoded đúng cách.)
  • Trong Cài đặt nguồn gốc CloudFront, đặt danh tính truy cập và đặt "Cấp quyền đọc trên nhóm" thành "Có, Cập nhật chính sách nhóm"
  • Trong Cài đặt phân phối chung, hãy đảm bảo "Trạng thái phân phối" được "Bật" và bạn đã thêm CNAME vào "Tên miền thay thế (CNAME)" nếu bạn đang sử dụng.
  • Nếu sử dụng CNAME, hãy đảm bảo DNS của bạn được định cấu hình chính xác để trỏ đến tên phân phối CloudFront của bạn.
  • Cuối cùng, sau khi bạn đặt cấu hình có thời gian chờ lâu trong khi AWS cập nhật phân phối, vì vậy bạn sẽ không thấy các thay đổi của mình xảy ra ngay lập tức. Có vẻ như ứng dụng/trang web của bạn vẫn bị hỏng cho đến khi các thay đổi lan truyền qua CloudFront. Điều này có thể làm cho việc cấu hình nó trở nên khó khăn bởi vì nếu bạn hiểu sai, bạn phải chờ một thời gian dài trước khi bạn thấy các thay đổi của mình có hiệu lực và bạn có thể không chắc chắn điều gì đã xảy ra. Nhưng với những cài đặt này tôi có thể làm cho nó hoạt động cho tôi.
  • Bạn cũng có thể tạo nhiều mẫu đường dẫn bộ nhớ đệm để một số nội dung riêng tư và yêu cầu url được CloudFront ký và nội dung khác thì không. Ví dụ: tôi đặt mẫu đường dẫn là *.mp4 yêu cầu chữ ký cho tất cả các tệp mp4 và được đặt ở trên hành vi mặc định. Và sau đó tôi có hành vi bộ nhớ cache mặc định được đặt thành KHÔNG yêu cầu các url đã ký, cho phép tất cả các tệp khác - chẳng hạn như hình ảnh - có thể truy cập công khai thông qua phân phối CloudFront.
Các vấn đề liên quan