2012-03-31 14 views
17

Używam mgła z carrierwave na mojej stronie. Ale obrazy ładują się bardzo powoli.Użyj CDN ze źródłemodncji + mgła w s3 + chmurze z szynami 3.1

Następnie chcę przyspieszyć ładowanie obrazów za pomocą CDN.

Śledzę ten poradnik dla utworzenia CDN dla obrazów:

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

Mam teraz mój rozkład wdrożony do obrazów, ale nie wiem jak działa dobrze CDN. Mam w inicjalizatorów/fog.rb kolejnej konfiguracji:

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 

Nie wiem, czy to prawda, ale w moim komputerze lokalnym nie działa dobrze dla mnie. Widzę lokalizację obrazu jest taka sama droga jak poprzednio:

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 

Jak mogę dodać CDN mgły plik w carrierwave z s3 i CloudFront?

+0

Jeśli używam tego ustawienia: 'fog_host', to pojawia się ten błąd: niezdefiniowana metoda' fog_host = 'dla CarrierWave :: Uploader :: Base: Class Jaką wersję nosicieli noszą użytkownicy? –

+0

Powinieneś użyć 'config.asset_host' zamiast' config.fog_host'. Dodałem ten problem do pytania. Powodzenia! – hyperrjas

+0

Tak, zauważyłem to, po pewnym kopaniu :) Dzięki. –

Odpowiedz

7

Wygląda na to, że nie dodałeś poniższej linii do swojej konfiguracji. Będziesz musiał zastąpić przykładowy adres poniżej swoim adresem w chmurze z Amazon.

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

„Można ewentualnie zawierać nazwę hosta CDN w konfiguracji ta jest wysoce zalecane, ponieważ bez niego każdy wniosek wymaga wyszukiwanie tych informacji.”

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

+0

To nie działa z prywatnymi treściami CloudFront. – Allen

6

wydaje się, że Amazon cdn nie działa z config.fog_public = false, więc pliki prywatne są dostępne tylko z S3, a nie z cdn

10

CarrierWave nie będzie Wor k po ustawieniu config.fog_public = falsei punkt config.asset_host na dystrybucję CloudFront. Zostało to udokumentowane wielokrotne:

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

W ostatnim projekcie byłem zadowolony z wykorzystaniem CarrierWave obsługiwać przesyłanie do S3, ale chciał, żeby powrócić podpisaną CloudFront URL przy użyciu Model.attribute_url. Wymyśliłem następujące (wprawdzie brzydkie) obejście, które mam nadzieję, że inni mogą skorzystać lub ulepszyć:

Dodaj klejnot 'cloudfront-signer' do swojego projektu i skonfiguruj go zgodnie z instrukcjami. Następnie dodać następujące override /lib/carrierwave/uploader/url.rb w nowym pliku w config/inicjalizatorów (nota wielokrotne insercje 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 

Następnie przesuń /lib/carrierwave/storage/fog.rb przez dodanie następujących do dolnej części tego samego pliku:

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 

Wreszcie w config/inicjalizatory/carrierwave.rb:

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

config.fog_public = false

To wszystko. Możesz teraz użyć Model.attribute_url, a zwróci on podpisany adres URL CloudFront do prywatnego pliku przesłanego przez CarrierWave do swojego zasobnika S3.

1

Po kilku poszukiwaniach i zmaganiach z tym przez długi czas znalazłem stronę, która mówi, że CarrierWave nie obsługuje adresów URL podpisanych przez CloudFront. Podpisane adresy URL CloudFront różnią się od adresów URL podpisanych przez S3, co spowodowało pewne zamieszanie. Kiedy już to rozgryzłem, o wiele łatwiej było wiedzieć, co robić.

przypadku skonfigurowania CarrierWave z config.fog_public = false następnie zostanie ona automatycznie rozpocząć podpisywanie URL-S3, ale nie może być skonfigurowany do pracy z Fog i CloudFront prywatnych treści w wersji CarrierWave używam (1.0.0). Próbowałem nawet użyć klejnotu carrierwave-aws i to też nie pomogło.

Więc co by się stało, jest to, że CarrierWave podpisze URL i gospodarz będzie wyglądać mniej więcej tak:

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

że punkty bezpośrednio do wiadra S3, ale potrzebowałem go, aby wskazywał CloudFront. Potrzebowałem gościć wyglądać następująco:

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

A co by się stało, gdybym ustawić config.asset_host równą mojej lokalizacji CloudFront to bym się tym (podwójne ukośniki przed „aktualizacje”):

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

To także wyraźnie pokazało, że CarrierWave nie został jeszcze zaprojektowany do użycia z CloudFront. Mam nadzieję, że go poprawią. To była moja praca. To brzydkie, ale udało się zrobić to, czego potrzebowałem, bez potrzeby modyfikacji samego CarrierWave, ponieważ mam nadzieję, że CarrierWave w pewnym momencie doda wsparcie dla CloudFront.

  1. Najpierw zrobiłem regex Znajdź/Zamień na mój adres URL i usunął część hosta S3 i umieścić na mojej części hosta CloudFront. cf_url = s3_url.gsub("my_bucket_name.s3-us-west-2.amazonaws.com", "s3.cloudfront_domain_name.com")
  2. Następny zrobiłem kolejny regex znaleźć/zastąpić usunąć S3 podpisane url na końcu łańcucha: non_signed_cf_url = cf_url.gsub(/\?.+/, '') To dlatego, że podpis będzie nieprawidłowa, ponieważ był za pomocą interfejsu API do S3, a nie dla CloudFront dla podpisywanie adresu URL.
  3. Teraz ponownie podpisać URL siebie, używając cloudfront-signer GEM: signed_cf_url = Aws::CF::Signer.sign_url(non_signed_cf_url, :expires => 1.day.from_now)

Istnieje kilka innych rzeczy, które trzeba mieć świadomość, gdy służąc treść prywatnej na CloudFront:

  • W ustawieniach Zachowania pamięci podręcznej dla wzorca ścieżki (niekoniecznie domyślnego) ustaw: "Ogranicz dostęp do przeglądarki (Użyj podpisanych adresów URL lub Podpisanych plików cookie)" na "Tak"
  • Zestaw "Zaufany Osoby podpisujące się "na" siebie "
  • Ustaw" Przekazywanie i buforowanie ciągów kwerend "na" Prześlij wszystkie, pamięć podręczną na podstawie wszystkich ", jeśli chcesz używać innych zapytań bardziej niż podpis CloudFront w adresie URL, na przykład response-content-disposition i response-content-type (Udało mi się je poprawnie uruchomić, ale muszą być poprawnie poprawione.)
  • W ustawieniach CloudFront Origin ustaw swoją tożsamość dostępową i ustaw "Przyznaj prawa odczytu na wiadrze" na "Tak, zaktualizuj zasady wiadra"
  • W ogólnych ustawieniach dystrybucji upewnij się, że "Stan dystrybucji" ma wartość "Włączone", a dodatek CNAME został dodany do "Alternatywne nazwy domen (CNAME)", jeśli używasz tego.
  • Jeśli używasz rekordu CNAME, upewnij się, że Twój DNS jest poprawnie skonfigurowany tak, aby wskazywał go na nazwę dystrybucji CloudFront.
  • Na koniec, po skonfigurowaniu konfiguracji długo czekać, podczas gdy AWS aktualizuje dystrybucję, więc zmiany nie będą widoczne od razu. Może się wydawać, że twoja aplikacja/strona internetowa wciąż jest uszkodzona, dopóki zmiany nie będą rozpowszechniane za pośrednictwem CloudFront. Może to utrudnić konfigurację, ponieważ jeśli źle zrobisz, musisz długo czekać, zanim zauważysz, że zmiany odniosły skutek i możesz nie wiedzieć, co się stało. Ale dzięki tym ustawieniom mogłem sprawić, żeby działał dla mnie.
  • Można także utworzyć więcej niż jeden wzór ścieżki buforowania, aby niektóre treści były prywatne i wymagały podpisu podpisanego CloudFront, a inne nie. Na przykład ustawiłem ścieżkę *.mp4 wymagającą podpisu dla wszystkich plików mp4 i umieszczonego powyżej domyślnego zachowania. A następnie mam domyślne zachowanie pamięci podręcznej NIE wymagające podpisanych adresów URL, dzięki czemu wszystkie inne pliki - takie jak obrazy - będą publicznie dostępne za pośrednictwem dystrybucji CloudFront.
Powiązane problemy