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

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 схему кэширования.