Как Мы Вдвое Сократили Затраты На Хранение И Передачу Изображений Без Потери Качества

Изображения играют важную роль в продаже фирменных туров.

Когда стартап в сфере туризма, маркетплейс оригинальных туров YouTravel.me, начал обрабатывать 2,5 миллиона запросов на изображения и раздавать по 50 ГБ в день, команда разработчиков задумалась о том, как хранить изображения, чтобы они не теряли качество.

, причем без траты космических бюджетов.

Технический директор проекта Иван Михеев рассказывает, как сделал собственный ресайзер изображений и снизил стоимость в 2 раза.

YouTravel.me — международная площадка оригинальных туров от независимых гидов.

Путешествие – это всегда эмоции и впечатления, поэтому в таком продукте ключевую роль играют не рациональные доводы, а картинки, которые ярче слов описывают тот опыт, который вы в конечном итоге получите в путешествии.

Нам нужно было сохранить все изображения и быстро отправить их клиенту, чтобы не падала скорость получения и качество изображения.

Плюс нужно было адаптировать их под разное количество устройств и витрин.

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

Мы задумались о новом способе хранения и передачи изображений, потому что:

  • Я начал получать 50 ГБ трафика в день.

  • Нагрузка выросла до 2,5 млн запросов.

  • Мы тратили 400 долларов в месяц на стороннее SaaS-решение, которое позволяло нам менять изображения на лету и распространять их через сеть доставки контента (CDN).

Это решение оказалось для нас довольно дорогим, поэтому мы задумались, есть ли более дешевые варианты.

Мы сравнили Cloudinary, Imagekit и Uploadcare и увидели, что некоторые сервисы создают свои продукты на AWS или его аналогах.

Чтобы сравнение было более точным, за общую единицу измерения мы взяли 1 ГБ.

В таблице мы указали, сколько стоит гигабайт трафика и общую ежемесячную стоимость за 1500ГБ, включая доплаты.



Как мы вдвое сократили затраты на хранение и передачу изображений без потери качества

Мы решили разобраться, как работают CDN-платформы.

Схема была довольно простой — функции хранения и Lambda, сжимающие, изменяющие размер и передающие изображения пользователю.

Сравнив все варианты, мы решили подробнее изучить Amazon CloudFront, поскольку по сути из всех сервисов нам нужен был только CDN и их Image API, который позволяет конвертировать изображения на лету.

Чтобы не платить комиссию сторонним платформам, мы решили сами сделать решение, которое позволит нам самостоятельно и быстро обрабатывать изображения.

Кроме того, у нас был грант в размере 5000 долларов от Amazon, который позволил нам провести этот эксперимент практически бесплатно.

Задача оказалась проще и быстрее, чем мы думали; ниже мы поделимся фрагментом кода.

План действий был следующий:

  1. Создайте хранилище S3 для измененных изображений.

  2. Создайте дистрибутив CDN.
  3. Напишите лямбда-функцию.



Создание хранилища S3

  1. Сначала нам нужно создать хранилище S3. Для этого в главном меню консоли зайдите в сервис S3 и нажмите кнопку «Создать ведро».



Как мы вдвое сократили затраты на хранение и передачу изображений без потери качества

2. На следующем экране укажите имя (1) этого хранилища и регион (2), в котором оно будет развернуто.



Как мы вдвое сократили затраты на хранение и передачу изображений без потери качества

3. Если все сделано правильно, в списке появится созданное нами хранилище.



Как мы вдвое сократили затраты на хранение и передачу изображений без потери качества

4. Далее для тестирования загрузите в него любое случайное изображение.

Нам это пригодится в следующих шагах.



Как мы вдвое сократили затраты на хранение и передачу изображений без потери качества



Создайте точку распространения CloudFront.

  1. Первым шагом является создание идентификатора доступа источника (OAI), чтобы мы могли предоставить созданной точке CDN доступ к хранилищу S3. Для этого зайдите в сервис CloudFront и выберите в меню слева (1) Идентификатор доступа Origin.
Далее на экране настроек нажмите кнопку «Создать учетную запись Origin Access».



Как мы вдвое сократили затраты на хранение и передачу изображений без потери качества

2. После этого нажмите «Создать раздачу», создайте точку распространения контента.



Как мы вдвое сократили затраты на хранение и передачу изображений без потери качества

3. Выберите метод доставки контента и нажмите «Начать».



Как мы вдвое сократили затраты на хранение и передачу изображений без потери качества

4. Укажите основные настройки как на скриншоте:

  • Выберите созданное хранилище S3 из списка.

  • Мы указываем Restrict Bucket Access, поскольку создали закрытое хранилище, и выбираем созданную нами политику OAI.
  • Мы позволяем автоматически прописывать политики в настройках S3.


Как мы вдвое сократили затраты на хранение и передачу изображений без потери качества

5. Настройте заголовки, которые будут отправляться на S3 по запросу.



Как мы вдвое сократили затраты на хранение и передачу изображений без потери качества

6. Также очень важно выбрать необходимый ценовой класс.

Если вам не нужно активно обслуживать клиентов из Индии, Африки и Азии, то вам просто нужно выбрать США, Канаду и Европу.

Тогда каждый Гб данных обойдется вам всего в 0,085 доллара.



Как мы вдвое сократили затраты на хранение и передачу изображений без потери качества

7. Теперь возвращаемся к хранилищу S3, которое мы создали на первом шаге, и убеждаемся, что политика была зарегистрирована корректно.



Как мы вдвое сократили затраты на хранение и передачу изображений без потери качества

8. Перейдите к списку точек распространения и подождите около минуты, пока служба будет развернута.



Как мы вдвое сократили затраты на хранение и передачу изображений без потери качества

9. Чтобы проверить работоспособность сервиса, достаточно зайти по адресу, указанному в графе Доменное имя: http://%cloud-font-id%.

cloudfront.net/testPhoto.jpg .

Теперь у вас есть работающий CDN. 10. Также при необходимости вы можете настроить свой домен, установить SSL-сертификат и включить необходимое вам логирование.

Мы оставим это вам самому.



Создание лямбда-функции

Ключевой частью системы является функция Lambda. Она отвечает за обработку изображений.

Давайте объясним, как работают CloudFront и Lambda@Edge. AWS Lambda позволяет запускать код без подготовки серверов и управления ими.

Вы платите только за затраченное время вычислений — с вас не взимается плата, когда ваш код не выполняется.

Lambda автоматически масштабируется и обеспечивает высокую доступность.

Lambda@Edge расширяет возможности Lambda, позволяя запускать код в нескольких местах AWS ближе к зрителю.

Для каждого поведения кэша в раздаче Amazon CloudFront можно добавить до четырех триггеров, которые вызывают выполнение функции Lambda при возникновении одного или нескольких событий CloudFront:

Как мы вдвое сократили затраты на хранение и передачу изображений без потери качества

Как работает CloudFront Как работает CloudFront. Источник

  • Запрос CloudFront Viewer — эта функция выполняется, когда CloudFront получает запрос от средства просмотра и перед проверкой, находится ли запрошенный объект в пограничном кэше.

  • CloudFront Origin Request — функция выполняется только тогда, когда CloudFront пересылает запрос вашему источнику.

    Когда запрошенный объект находится в пограничном кэше, функция не выполняется.

  • Ответ CloudFront от источника.

    Функция запускается после того, как CloudFront получает ответ от источника и до кэширования объекта в ответе.

  • Ответ CloudFront Viewer — функция выполняется до того, как запрошенный объект возвращается средству просмотра.

    Функция выполняется независимо от того, находится ли объект уже в пограничном кэше.

Принцип работы нашей Lambda прост: мы передаем параметры обработки изображения непосредственно в URL — https://domain.ltd/tr:w-XXX,h-XXX/path/to/image.jpg .

Для этого наши действия будут следующими:

  1. Создаем функцию-обработчик запроса Viewer. Его задача — взять заголовки браузера и понять, принимает ли он webp или нужно отдавать jpg/png и соответствующим образом скорректировать строку запроса.

В этом случае мы добавляем папку с именем в формате /webp/tr:w-XXX,h-XXX/path/to/image.jpg или /original/tr:w-XXX,h-XXX/path/ to/ в начале запроса image.jpg Можно обойтись и без него и просто проксировать заголовок Accept, но тогда он будет частью ключа кэша, и кэширование будет неэффективным, так как вариантов значений заголовка может быть много.

2. Далее мы создаем функцию происхождения-ответа.

Это работает следующим образом:

  • Смотрим, есть ли эта картинка на S3, которую мы получили благодаря коду ответа, полученному от S3.
  • Если изображение есть, мы ничего не делаем и просто позволяем CloudFront кэшировать его.

  • Если образа на S3 нет, то нам нужно его создать.

  • Поскольку в качестве ресурса мы используем внешний веб-сервер, то делаем http-запрос изображения, обрабатываем его в соответствии с настройками (сжимаем, изменяем размер).

    Вы также можете использовать ту же корзину S3 в качестве хранилища, тогда вместо http-запроса вам нужно будет сделать внутренний запрос образа через AWS SDK.

  • После этого сохраняем обработанное изображение в S3 по новому пути и отправляем в CloudFront.
  • В следующий раз, когда кеш изображений потеряет свою актуальность, нужное нам изображение уже будет в S3, и весь алгоритм завершится в точке b.
Мы разместили код нашей функции Lambda на GitHub .

Мы делимся им с вами, чтобы вы могли применить его в своих экспериментах.

Можно взять и сразу запустить в производство.

Мы не настаиваем на том, что наш код будет самым оптимальным решением для вашего случая.

Лучше протестировать, понять, как работает наше решение, а затем уже осознанно внедрять свое.

Прежде чем мы начнем создавать нашу функцию, давайте объясним несколько основных частей функции origin-response:

  • Exports.handler — это основная функция, которая будет выполняться службой Lambda@Edge.
  • Прежде всего, внутри этого обработчика мы получаем исходный путь к файлу.

    Это то, что делает класс ImageRequest. Он также отвечает за понимание, какие преобразования необходимо произвести и в каком формате нужно отправить файл (webp или в исходном формате).

  • Далее функция проверяет наличие файла на S3 — это делается просто путем определения кода ответа от исходного сервера.

  • Если S3 ответил нам кодом 404 или 403, значит файл не найден и нам необходимо его создать.

    Для этого мы отправляем запрос на наш сервер по HTTP. Скачиваем изображение, делаем необходимые преобразования через библиотеку Sharp и сохраняем все на S3.

  • Если файл найден, то завершаем функцию и даем ответ, который планировал дать S3.
Сам код мы снабдили дополнительными комментариями.

Давайте теперь создадим эти функции для мгновенного изменения размера:

  1. Давайте перейдем в IAM и создадим роль, которая позволит функции Lambda читать и записывать данные в S3, а также иметь возможность выполняться.



Как мы вдвое сократили затраты на хранение и передачу изображений без потери качества

Источник 2. Добавьте политики AmazonS3FullAccess, AWSLambdaExecute.

Как мы вдвое сократили затраты на хранение и передачу изображений без потери качества

3. На последнем шаге укажите имя.

4. Создайте две функции для просмотра-запроса и происхождения-ответа, выберите вариант с нуля и укажите там роль, которую вы создали на шаге 3.

Как мы вдвое сократили затраты на хранение и передачу изображений без потери качества

5. Далее необходимо подготовить код для скачивания.

6. Нам понадобится установленный Docker для сборки Sharp с поддержкой libvips. 7. Загрузите репозиторий.

8. Выполните сценарий build.sh. 9. Заливаем код в соответствующие функции.



Как мы вдвое сократили затраты на хранение и передачу изображений без потери качества

10. Проверьте по ссылке.

Чтобы протестировать ваши функции локально, просто используйте:

  • AWS CLI и AWC SAM
  • cd лямбда/origin-response
  • Сэм локальный вызов -e s3-event.json
Итак, немного разобравшись, мы сэкономили почти $200 ежемесячно, не потеряв при этом качества и скорости для пользователя.

Мы потратили неделю на работу и тестирование.

Мы пользуемся этим решением с марта, и оно показывает себя достаточно стабильно: изображения доставляются быстро и без потери качества.

Теги: #Хранение данных #Amazon Web Services #node.js #lambda

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.