Использование Cloudfront с Active Storage

Я создаю веб-сайт, используя Ruby on Rails. Для загрузки изображений я использую Active Storage и Amazon S3. Здесь все хорошо. Пользователи могут загружать изображения, и изображения доступны для просмотра на веб-сайте (изображения являются общедоступными).

Сейчас в производстве используются изображения: https://example.com/rails/active_storage/presentations/1ej21h ...

Что возвращает 302 в ведро S3: https://my-bucket.amazonaws.com/variants/9jdh2 ...

Я не большой поклонник:

  • два пути туда и обратно, чтобы получить изображение;
  • отправка запросов изображений на сервер Rails;
  • ощущение медлительности на этих изображениях.

И я бы предпочел использовать Cloudfront для обслуживания этих изображений.

Я искал в Rails Guides, в Google и StackOverflow, но пока не нашел правильного ответа.

Есть ли в настоящее время какое-либо решение для использования Cloudfront с Active Storage?

Редактировать: Больше контекста: каждое изображение будет загружаться 1000 раз в минуту, по крайней мере, при нормальном трафике и из разных стран. Я не хочу подвергать сервер этому давлению (у него есть другие запросы для обработки). И я хочу, чтобы пользователи загружали эти изображения как можно быстрее. Следовательно, Cloudfront как CDN для этих изображений (общедоступные изображения, нет необходимости получать подписанный URL-адрес).

Вы имеете в виду тот факт, что рельсы попадут на сервер, чтобы позволить active_job сгенерировать новый подписанный URL-адрес вашей корзины? Это заставляет изображения мигать при загрузке страницы, в то время как интерфейс ожидает на сервере генерации подписанного URL-адреса. Есть патч, который вы можете применить, чтобы исправить это. Можете ли вы подтвердить, что вы об этом говорите?

Verty00 12.09.2018 12:30

@ Verty00 Изображение не мигает: оно загружается довольно медленно, а запросы изображений обрабатываются сервером rails (действительно, для генерации нового подписанного URL-адреса). Мне не нужна подпись, изображения публичные. Когда пользователь отображает страницу, я хочу, чтобы URL-адрес для изображений, отображаемых сервером, был my-distribution.cloudfront.net/my-image-url.jpg. Таким образом, серверу rails не нужно обрабатывать ненужные запросы изображений (например, «обход подписи»).

gpichot 12.09.2018 12:36

Посмотрите мой ответ ниже. Это помогает?

Verty00 12.09.2018 12:44
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
10
3
2 791
2

Ответы 2

Попробуй это...

в controllers/active_storage/representations_controller.rb <- создать, если его нет. Вы должны поставить ...

module ActiveStorage
  class RepresentationsController < BaseController
    include ActiveStorage::SetBlob

    def show
      expires_in 1.year, public: true
      variant = @blob.representation(params[:variation_key]).processed
      send_data @blob.service.download(variant.key),
            type: @blob.content_type || DEFAULT_SEND_FILE_TYPE,
            disposition: 'inline'
    end
  end
end

Затем, когда вы вызываете изображение с помощью @model.image.variant(resize: '250x250'), убедитесь, что вы заменили желаемые размеры. На данный момент это хак. Я думаю, это должно быть исправлено выпуском rails 6.

Спасибо @ Verty00, но он не отвечает на мой вопрос и не решает проблему. Я не хочу, чтобы изображения запрашивались через ContentationsController вообще.

gpichot 13.09.2018 11:37

Это очень близко. Он подписывает URL только в первый раз. Затем каждый последующий запрос проходит напрямую через ведро.

Verty00 13.09.2018 13:02

да. но это все равно будет оказывать давление на сервер. Корзины S3 не предназначены для распространения контента. Если у меня 10 изображений на странице и эта страница запрашивается 1k раз, я все равно буду получать 1k + 10k запросов к серверу.

gpichot 13.09.2018 17:38

Я не думаю, что это правильно. Это 1k запросов с не более чем 10 запросами к вашей БД на каждый запрос для доступа к BLOB-объекту и получения уже подписанного URL-адреса. Может быть, попробуйте реализовать стратегию кеширования.

Verty00 13.09.2018 17:50

Да для главной страницы. Но тогда каждый пользователь также будет запускать запрос для каждого изображения с URL-адресом «/ rails / active_storage / views /». Которые запускают вызов действия «ПредставлениеКонтроллер» (отсюда и запросы сервера +10 тыс., Я не говорю здесь о запросах БД, которые можно кэшировать).

gpichot 17.09.2018 07:15

Не думаю, что вы понимаете, что делает этот код. 10К серверных запросов точно нет. Этот код позволяет получать предварительно подписанный большой двоичный объект, не обращаясь к контроллеру представлений при каждом запросе. Попытайся. Я думаю, вы обнаружите, что он делает именно то, что вам нужно.

Verty00 17.09.2018 16:19

Извините за путаницу, действительно, Контроллер представлений не будет вызываться 10 тысяч раз. Тем не менее, я получу 10 тысяч запросов на свой сервер, которые будут использовать Rack: Cache, верно? Я мог бы использовать memcached или Redis для кеширования этих страниц, но я не хочу этого (как указано в контексте моего вопроса, каждое изображение должно использовать URL-адрес Cloudfront, а не рельсы). Кроме того, после вашего ответа я все еще полагаюсь на S3 для обслуживания файлов, что не является жизнеспособным решением.

gpichot 17.09.2018 17:42

У тебя что-нибудь получилось с этим @gpichot? Та же ситуация, когда у меня есть приложение Rails с изображениями в ActiveStorage, сохраненными в S3, и я хочу работать с помощью CloudFront. Вы правы в том, что никто не должен предоставлять изображения конечным пользователям через S3.

Paul Watson 12.11.2018 12:58

@PaulWatson В какой-то момент я обратил внимание на следующую проблему Github github.com/rails/rails/issues/31419 и начал «исправлять» бэкэнд ActiveStorage S3, используя некоторые из сущностей, которые люди предложили в этой ветке. Мне удалось вернуть URL-адрес облачного интерфейса для моих ресурсов, которого может быть достаточно, но они не были «чистыми» (без расширения в имени). Но в конце концов я откатился к нулю, так как ценность для бизнеса менее важна, чем другие функции, и я предпочел иметь что-то несовершенное, чем что-то хакерское ...

gpichot 12.11.2018 16:29
gist.github.com/timm-oh/10c4f06effa536ff32c5d038e0dd57e1 Пожалуйста, не стесняйтесь оставлять комментарии по своему усмотрению :)
timm_oh 15.01.2020 07:40

Я всегда помещаю свои балансировщики нагрузки за облачным распределением, и я помещаю домен Route53, указывающий на распределение, а не на балансировщик нагрузки. Таким образом, вы можете кэшировать любое поведение, какое захотите. Вы можете, конечно, кэшировать любой запрос к rails / active_storage / views / redirect / *, и он сохранит любые заголовки кеша, возвращаемые сервером приложений при первом получении изображения.

Другие вопросы по теме