2012-03-31 2 views
17

Я использую fog с carrierwave на моем сайте. Но изображения загружаются очень медленно.Использование CDN с несущей волной + туман в s3 + облачный с рельсами 3.1

Затем я хочу ускорить загрузку изображений с CDN.

Я следовал этому учебнику для создания CDN для изображений:

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

Я теперь мое распределение развертывается для изображений, но я не знаю, как работает отлично КДС. Я имею в инициализаторах/fog.rb следующей конфигурации:

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 

Я не знаю, если это правильно, но в моей локальной машине это не работает для меня. Я вижу, расположение изображения, тот же маршрут, как и раньше:

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 

Как я могу добавить CDN тумана файл в carrierwave с s3 и CloudFront?

+0

Если я использую эту настройку: 'fog_host', то я получаю эту ошибку: undefined method' fog_host = 'для CarrierWave :: Uploader :: Base: Class. Какую версию несущей поддерживают люди? –

+0

Вы должны использовать 'config.asset_host' вместо' config.fog_host'. Я добавил этот вопрос к вопросу. Удачи! – hyperrjas

+0

Да, я заметил, что после некоторого рытья :) Спасибо. –

ответ

7

Похоже, вы не добавили строку ниже в свою конфигурацию. Вам нужно будет заменить адрес образца ниже с вашим облачным адресом от Amazon.

Из GitHub README: https://github.com/jnicklas/carrierwave

«При желании вы можете включить ваш CDN имя хоста в конфигурации Это настоятельно рекомендуется, так как без него каждый запрос требует поиска этой информации.»

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

+0

Это не работает с частным контентом CloudFront. – Allen

6

кажется, что амазонки не CDN работать с config.fog_public = false, поэтому частные файлы доступны только с s3, а не от CDN

10

CarrierWave не приста k, когда вы установили config.fog_public = falseиconfig.asset_host для распределения CloudFront. Это было документально подтверждено несколько раз:

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

В недавнем проекте я был счастлив, используя CarrierWave для обработки загрузки в S3, но хотел, чтобы вернуть подписанный URL CloudFront при использовании Model.attribute_url. Я придумал следующее (по общему признанию, уродливое) решение, которое я надеюсь, что другие могут извлечь выгоду или улучшить:

Добавьте в проект проект 'cloudfront-signer' и настройте его в соответствии с инструкциями. Затем добавьте следующее переопределение /lib/carrierwave/uploader/url.rb в новом файле в конфигурации/инициализаторах (обратите внимание на несколько вставок 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 

Затем переопределить /lib/carrierwave/хранение/туман.гь, добавив следующее в нижней части того же файла:

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 

Наконец, в конфигурации/Инициализаторы/carrierwave.rb:

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

config.fog_public = false

Вот так. Теперь вы можете использовать Model.attribute_url, и он вернет подписанный URL CloudFront в приватный файл, загруженный CarrierWave в ваш ведро S3.

1

После некоторого поиска и борьбы с этим в течение длительного времени я нашел страницу, в которой говорится, что CarrierWave не поддерживает подписанные URL-адреса CloudFront. Подписанные URL-адреса CloudFront отличаются от подписанных URL-адресов S3, что вызвало у меня некоторую путаницу. Как только я понял это, было намного легче узнать, что делать.

При настройке CarrierWave с config.fog_public = false то он автоматически начнет подписывать S3 URLs, но он не может быть сконфигурирован для работы с Fog и CloudFront частного содержания в версии CarrierWave я использую (1.0.0). Я даже попытался использовать драгоценный камень carrierwave-aws, и это тоже не помогло.

Так что же случится, что CarrierWave подпишет URL и хост будет выглядеть примерно так:

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

Это указывает непосредственно на ведро S3, но мне нужно, чтобы она указывала на CloudFront. Я нужен хозяин, чтобы выглядеть следующим образом:

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

А что произойдет, если я установить config.asset_host равного моей CloudFront место, я бы получить это (с двойной косой чертой перед «загрузкой»):

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

Это тоже показало, что CarrierWave еще не предназначен для использования с CloudFront. Надеюсь, они улучшат его. Это была моя работа. Это уродливо, но он работал, чтобы сделать то, что мне нужно, без необходимости изменять CarrierWave, так как я надеюсь, что CarrierWave в какой-то момент добавит поддержку CloudFront.

  1. Сначала я сделал регулярное выражение поиска/замены на моих URL и удалил часть хоста S3 и положить на моей CloudFront узловой части. cf_url = s3_url.gsub("my_bucket_name.s3-us-west-2.amazonaws.com", "s3.cloudfront_domain_name.com")
  2. Далее я еще регулярное выражение поиска/замены для удаления S3 подписали URL в конце строки: non_signed_cf_url = cf_url.gsub(/\?.+/, '') Это происходит потому, что подпись будет неправильно, потому что он был с помощью API для S3, а не для CloudFront для подписывая URL.
  3. Теперь я заново подписывать URL сам, используя cloudfront-signer перл: signed_cf_url = Aws::CF::Signer.sign_url(non_signed_cf_url, :expires => 1.day.from_now)

Есть несколько других вещей, которые вы должны знать при обслуживании частного контента на CloudFront:

  • В настройках поведения кэша для вашего шаблона пути (не обязательно по умолчанию) установите: «Ограничить доступ к просмотру (Использовать подписи или Подписанные файлы cookie)» на «Да»
  • Установить «Надежный Signers "to" self "
  • Установите« Query String Forwarding and Caching »на« Переслать все, кеш на основе всех », если вы хотите использовать другие строки запроса больше, чем подпись CloudFront в вашем URL-адресе, например response-content-disposition и response-content-type (Я смог заставить их работать успешно, но они должны быть правильно установлены url_encoded.)
  • В настройках Origin для CloudFront задайте свой идентификатор доступа и установите «Разрешения на получение прав на ведро» на «Да, обновить политику ведра»,
  • В настройках общего распространения убедитесь, что «Состояние распространения» «Включено», и что вы добавили CNAME в «Альтернативные имена доменов (CNAME)», если вы используете его.
  • Если вы используете CNAME, убедитесь, что ваш DNS настроен правильно, чтобы указать его на имя вашего CloudFront.
  • Наконец, после установки конфигураций существует долгое ожидание, в то время как AWS обновляет дистрибутив, поэтому вы не увидите, как ваши изменения произойдут сразу. Может показаться, что ваше приложение/веб-сайт все еще сломан, пока изменения не распространяются через CloudFront. Это может затруднить настройку, потому что, если вы ошибаетесь, вам придется долго ждать, прежде чем вы сможете увидеть, как ваши изменения вступают в силу, и вы не можете быть уверены, что произошло. Но с этими настройками я смог заставить его работать на меня.
  • Вы также можете создать несколько шаблонов пути кэширования, чтобы некоторый контент был приватным и ему нужен подписанный URL CloudFront, а другой контент - нет. Например, я устанавливаю шаблон пути *.mp4, который требует подписи для всех файлов mp4 и помещает его выше по умолчанию. И тогда у меня установлен режим кэширования по умолчанию, чтобы НЕ требовать подписанные URL-адреса, что позволяет публично открывать все другие файлы, такие как изображения, через дистрибутив CloudFront.
Смежные вопросы