Используйте CDN с несущей волной + туман в s3 + облачный фронт с рельсами 3.1 - PullRequest
20 голосов
/ 31 марта 2012

Я использую туман с carrierwave на моем веб-сайте. Но изображения загружаются очень и очень медленно.

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

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

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

Сейчас у меня развернут дистрибутив для образов, но я не знаю, как хорошо работает cdn. У меня в initializer / 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 и облачным фронтом?

Ответы [ 4 ]

10 голосов
/ 31 марта 2014

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

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

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

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

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

Наконец, в config / initializers / carrierwave.rb :

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

config.fog_public= false

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

9 голосов
/ 11 октября 2012

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

С github README: https://github.com/jnicklas/carrierwave

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

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

6 голосов
/ 19 октября 2012

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

2 голосов
/ 28 декабря 2016

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

Если вы настроите CarrierWave с config.fog_public = false, тогда он автоматически начнет подписывать URL-адреса S3, но его нельзя будет настроить для работы с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. Затем я сделал еще одно регулярное выражение поиска / замены, чтобы удалить подписанный URL-адрес S3 в конце строки: non_signed_cf_url = cf_url.gsub(/\?.+/, '') Это связано с тем, что подпись будет неверной, поскольку она использует API для S3 ине для CloudFront для подписи URL.
  3. Теперь я сам переподписываю URL, используя cloudfront-signer gem: signed_cf_url = Aws::CF::Signer.sign_url(non_signed_cf_url, :expires => 1.day.from_now)

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

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