Перейти к основному содержимому

Yandex Cloud: on the fly thumbnails.

· 3 мин. чтения

UPD: Yandex Cloud представили новый runtime для функций — C#. Ну и мне тут же захотелось его попробовать. Поэтому я дописал реализацию этой функции еще и на csharp. https://github.com/nikolaymatrosov/yc-on-the-fly-thumbnailer-csharp/blob/master/OnTheFlyResize/Handler.cs

В прошлом посте я рассказал как создавать превью картинок загружаемых в объектное хранилище Яндекс Облака. У того решения было пара ограничений:

  1. Превью создавались только для новых изображений. Если картинка уже лежит в бакете, то для нее не появится уменьшенная версия.
  2. Нужно было заранее определить высоту и ширину. Если вам понадобилось бы поменять соотношение сторон или размеры, то пришлось бы заново масштабировать все картинки.

Как же будет работать новая схема?

Первое обращение за превью

  1. Пользователь запрашивает картинку, указав в URL ее желаемые размеры.
  2. Объектное хранилище не находит нужного файла и согласно настроенным правилам, переадресует запрос в функцию.
  3. Функция идет за оригинальным изображением в объектное хранилище.
  4. Масштабирует его до нужных размеров и сохраняет по ключу содержащему эти размеры.
  5. И тут же отдает готовый файл пользователю.

Что произойдет при повторном обращении к этому изображению?

Все последующие запросы

Пользователь сразу получит файл из объектного хранилища. Функция даже не будет вызвана.

Как это работает?

Чтобы Object Storage и Cloud Functions заработали в связке нам необходимо прописать правила переадресации для бакета.

s3.putBucketWebsite({
Bucket: "%bucket_name%",
WebsiteConfiguration: {
IndexDocument: {
Suffix: "index.html"
},
RoutingRules: [
{
Condition: {
HttpErrorCodeReturnedEquals: "404",
KeyPrefixEquals: "images/"
},
Redirect: {
HttpRedirectCode: "302",
HostName: "functions.yandexcloud.net",
Protocol: "https",
ReplaceKeyPrefixWith: "%function_id%?path="
}
}
]
}
})

Если объектное хранилище не найдет (HttpErrorCodeReturnedEquals: "404") запрошенный файл с указанным KeyPrefixEquals , то применит указанный ниже редирект. Подробнее можно посмотреть в документации к AWS S3.

Код функции можно найти в репозитории. https://github.com/nikolaymatrosov/yc-on-the-fly-thumbnailer

Стоит так же отметить, что с момента написания предыдущего поста, создание функций из CLI yc стало гораздо удобнее. Теперь не нужно самому заморачиваться на архивирование кода и загрузку его в объектное хранилище. Достаточно лишь сложить все файлы в директорию и указать на нее при создании версии функции в ключе --source-path .

Так же стало возможным не передавать все node_modules, а загрузить лишь package.json и выбрать --runtime nodejs12-preview. Все зависимости будут подтянуты в момент создания версии функции.

Как обращаться к файлам?

По обычному хосту %bucket_name%.storage.yandexcloud.netредиректы отрабатывать не будут, к объектам нужно обращаться через %bucket_name%.website.yandexcloud.net/PREFIX/%width%x%height%/%path%. Например:

%bucket_name%.website.yandexcloud.net/images/500x500/cats/meow.png

Мы получим картинку, которую положили в бакет %bucket_name%по ключу images/cats/meow.png, но отмасштабированную до размеров 500x500px.

Чтобы не выстрелить себе в ногу

Если не задать значение переменной окружения ALLOWED_DIMENSIONS, то в функции не будут накладываться ограничений на размеры. Это значит, что если будут запрошены много разных вариантов размеров, то они будут созданы и загружены в объектное хранилище. Поэтому если вы точно знаете, что вам понадобятся определенные размеры картинок лучше их указать.

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