Используйте CDN с несущей волной + туман в s3 + cloudfront с рельсами 3.1
Я использую туман с carrierwave на моем веб-сайте. Но изображения загружаются очень медленно.
Затем я хочу ускорить загрузку изображений с CDN.
Я следил за этим руководством для создания CDN для изображений:
http://maketecheasier.com/configure-amazon-s3-as-a-content-delivery-network/2011/06/25
Теперь у меня есть дистрибутив для изображений, но я не знаю, как отлично работает cdn. У меня в инициализаторах /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 в файл fog в несущей с s3 и облачным?
Ответы
Ответ 1
Похоже, вы не добавили строку ниже в свою конфигурацию. Вам нужно будет заменить адрес образца ниже адресом облачного интерфейса от Amazon.
Из github README: https://github.com/jnicklas/carrierwave
"Вы можете дополнительно указать имя хоста CDN в конфигурации. Это настоятельно рекомендуется, так как без него каждый запрос требует поиска этой информации"
config.asset_host = "http://c000000.cdn.rackspacecloud.com"
Ответ 2
CarrierWave не будет работать, если вы установите 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 в новый файл в 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.
Ответ 3
кажется, что amazon cdn не работает с config.fog_public = false
, поэтому частные файлы доступны только из s3, а не из cdn
Ответ 4
После некоторого поиска и борьбы с этим в течение долгого времени я нашел страницу, в которой говорится, что CarrierWave не поддерживает подписанные URL-адреса CloudFront. Подписанные URL-адреса CloudFront отличаются от подписанных URL-адресов S3, что вызвало у меня некоторую путаницу. Как только я понял это, было намного легче узнать, что делать.
Если вы настроите CarrierWave с помощью config.fog_public = false
, то он автоматически начнет подписывать S3-URL, но он не может быть настроен для работы с 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, я бы это получил (с двойными косыми чертами перед "uploads" ):
https://s3.cloudfront_domain_name.com//uploads/...
Это тоже показало, что CarrierWave еще не был разработан для использования с CloudFront. Надеюсь, они улучшат его. Это была моя работа. Это уродливо, но он работал, чтобы сделать то, что мне было нужно, без необходимости модифицировать CarrierWave, так как я надеюсь, что CarrierWave в какой-то момент добавит поддержку CloudFront.
- Сначала я выполнил поиск/замену регулярного выражения на моем URL-адресе и удалил часть узла S3
и добавьте часть хоста CloudFront.
cf_url = s3_url.gsub("my_bucket_name.s3-us-west-2.amazonaws.com", "s3.cloudfront_domain_name.com")
- Далее я снова нашел/заменил регулярное выражение
для удаления подписанного URL S3 в конце строки:
non_signed_cf_url = cf_url.gsub(/\?.+/, '')
Это потому, что подпись будет неправильной, потому что она использовала API для S3, а не для CloudFront для подписания URL-адреса.
- Теперь я снова переписываю URL, используя
cloudfront-signer
gem:
signed_cf_url = Aws::CF::Signer.sign_url(non_signed_cf_url, :expires => 1.day.from_now)
Есть несколько других вещей, о которых вам нужно знать при обслуживании личного контента на CloudFront:
- В настройках поведения кэша для вашего шаблона пути (не обязательно по умолчанию) установите: "Ограничить доступ к просмотру
(Использовать подписанные URL-адреса или
Подпись Cookies) "на" Да "
- Установите "доверенные подписчики" на "self"
- Установите "Переадресация и кеширование строки запроса" на "Переслать все, кеш на основе всех", если вы хотите использовать другие строки запроса больше, чем подпись CloudFront в вашем URL-адресе, например
response-content-disposition
и response-content-type
(я был чтобы заставить их работать успешно, но они должны быть правильно закодированы url_encoded.)
- В настройках источника CloudFront укажите свой идентификатор доступа и установите "Разрешения на получение прав на ведро" на "Да, обновить политику ведра".
- В ваших общих настройках распространения убедитесь, что "Состояние распространения" "Включено", и что вы добавили CNAME в "Альтернативные имена доменов"
(CNAME) ", если вы используете его.
- Если вы используете CNAME, убедитесь, что ваш DNS правильно настроен, чтобы указать его на ваше имя распространения CloudFront.
- Наконец, после того, как вы установили конфигурации, существует долгое ожидание, пока AWS обновляет дистрибутив, поэтому вы не увидите, что ваши изменения произойдут сразу. Может показаться, что ваше приложение/веб-сайт все еще сломан, пока изменения не распространяются через CloudFront. Это может затруднить настройку, потому что, если вы ошибаетесь, вам придется долго ждать, прежде чем вы сможете увидеть, как ваши изменения вступают в силу, и вы не можете быть уверены, что произошло. Но с этими настройками я смог заставить его работать для меня.
- Вы также можете создать более одного шаблона пути кэширования, чтобы некоторый контент был приватным и для него требовался подписанный URL CloudFront, а другой контент - нет. Например, я устанавливаю шаблон пути
*.mp4
, который требует подписи для всех файлов mp4 и помещает его выше по умолчанию. И тогда у меня установлен режим кэширования по умолчанию, для которого НЕ требуется подписанные URL-адреса, что позволяет публиковать все другие файлы, такие как изображения, через дистрибутив CloudFront.