Я создаю веб-сайт, используя Ruby on Rails. Для загрузки изображений я использую Active Storage и Amazon S3. Здесь все хорошо. Пользователи могут загружать изображения, и изображения доступны для просмотра на веб-сайте (изображения являются общедоступными).
Сейчас в производстве используются изображения: https://example.com/rails/active_storage/presentations/1ej21h ...
Что возвращает 302 в ведро S3: https://my-bucket.amazonaws.com/variants/9jdh2 ...
Я не большой поклонник:
И я бы предпочел использовать Cloudfront для обслуживания этих изображений.
Я искал в Rails Guides, в Google и StackOverflow, но пока не нашел правильного ответа.
Есть ли в настоящее время какое-либо решение для использования Cloudfront с Active Storage?
Редактировать: Больше контекста: каждое изображение будет загружаться 1000 раз в минуту, по крайней мере, при нормальном трафике и из разных стран. Я не хочу подвергать сервер этому давлению (у него есть другие запросы для обработки). И я хочу, чтобы пользователи загружали эти изображения как можно быстрее. Следовательно, Cloudfront как CDN для этих изображений (общедоступные изображения, нет необходимости получать подписанный URL-адрес).
@ Verty00 Изображение не мигает: оно загружается довольно медленно, а запросы изображений обрабатываются сервером rails (действительно, для генерации нового подписанного URL-адреса). Мне не нужна подпись, изображения публичные. Когда пользователь отображает страницу, я хочу, чтобы URL-адрес для изображений, отображаемых сервером, был my-distribution.cloudfront.net/my-image-url.jpg. Таким образом, серверу rails не нужно обрабатывать ненужные запросы изображений (например, «обход подписи»).
Посмотрите мой ответ ниже. Это помогает?
Попробуй это...
в 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 вообще.
Это очень близко. Он подписывает URL только в первый раз. Затем каждый последующий запрос проходит напрямую через ведро.
да. но это все равно будет оказывать давление на сервер. Корзины S3 не предназначены для распространения контента. Если у меня 10 изображений на странице и эта страница запрашивается 1k раз, я все равно буду получать 1k + 10k запросов к серверу.
Я не думаю, что это правильно. Это 1k запросов с не более чем 10 запросами к вашей БД на каждый запрос для доступа к BLOB-объекту и получения уже подписанного URL-адреса. Может быть, попробуйте реализовать стратегию кеширования.
Да для главной страницы. Но тогда каждый пользователь также будет запускать запрос для каждого изображения с URL-адресом «/ rails / active_storage / views /». Которые запускают вызов действия «ПредставлениеКонтроллер» (отсюда и запросы сервера +10 тыс., Я не говорю здесь о запросах БД, которые можно кэшировать).
Не думаю, что вы понимаете, что делает этот код. 10К серверных запросов точно нет. Этот код позволяет получать предварительно подписанный большой двоичный объект, не обращаясь к контроллеру представлений при каждом запросе. Попытайся. Я думаю, вы обнаружите, что он делает именно то, что вам нужно.
Извините за путаницу, действительно, Контроллер представлений не будет вызываться 10 тысяч раз. Тем не менее, я получу 10 тысяч запросов на свой сервер, которые будут использовать Rack: Cache, верно? Я мог бы использовать memcached или Redis для кеширования этих страниц, но я не хочу этого (как указано в контексте моего вопроса, каждое изображение должно использовать URL-адрес Cloudfront, а не рельсы). Кроме того, после вашего ответа я все еще полагаюсь на S3 для обслуживания файлов, что не является жизнеспособным решением.
У тебя что-нибудь получилось с этим @gpichot? Та же ситуация, когда у меня есть приложение Rails с изображениями в ActiveStorage, сохраненными в S3, и я хочу работать с помощью CloudFront. Вы правы в том, что никто не должен предоставлять изображения конечным пользователям через S3.
@PaulWatson В какой-то момент я обратил внимание на следующую проблему Github github.com/rails/rails/issues/31419 и начал «исправлять» бэкэнд ActiveStorage S3, используя некоторые из сущностей, которые люди предложили в этой ветке. Мне удалось вернуть URL-адрес облачного интерфейса для моих ресурсов, которого может быть достаточно, но они не были «чистыми» (без расширения в имени). Но в конце концов я откатился к нулю, так как ценность для бизнеса менее важна, чем другие функции, и я предпочел иметь что-то несовершенное, чем что-то хакерское ...
Я всегда помещаю свои балансировщики нагрузки за облачным распределением, и я помещаю домен Route53, указывающий на распределение, а не на балансировщик нагрузки. Таким образом, вы можете кэшировать любое поведение, какое захотите. Вы можете, конечно, кэшировать любой запрос к rails / active_storage / views / redirect / *, и он сохранит любые заголовки кеша, возвращаемые сервером приложений при первом получении изображения.
Вы имеете в виду тот факт, что рельсы попадут на сервер, чтобы позволить active_job сгенерировать новый подписанный URL-адрес вашей корзины? Это заставляет изображения мигать при загрузке страницы, в то время как интерфейс ожидает на сервере генерации подписанного URL-адреса. Есть патч, который вы можете применить, чтобы исправить это. Можете ли вы подтвердить, что вы об этом говорите?