Yandex Cloud: on the fly thumbnails.
UPD: Yandex Cloud представили новый runtime для функций — C#. Ну и мне тут же захотелось его попробовать. Поэтому я дописал реализацию этой функции еще и на csharp. https://github.com/nikolaymatrosov/yc-on-the-fly-thumbnailer-csharp/blob/master/OnTheFlyResize/Handler.cs
В прошлом посте я рассказал как создавать превью картинок загружаемых в объектное хранилище Яндекс Облака. У того решения было пара ограничений:
- Превью создавались только для новых изображений. Если картинка уже лежит в бакете, то для нее не появится уменьшенная версия.
- Нужно было заранее определить высоту и ширину. Если вам понадобилось бы поменять соотношение сторон или размеры, то пришлось бы заново масштабировать все картинки.
Как же будет работать новая схема?
Первое обращение за превью
- Пользователь запрашивает картинку, указав в URL ее желаемые размеры.
- Объектное хранилище не находит нужного файла и согласно настроенным правилам, переадресует запрос в функцию.
- Функция идет за оригинальным изображением в объектное хранилище.
- Масштабирует его до нужных размеров и сохраняет по ключу содержащему эти размеры.
- И тут же отдает готовый файл пользователю.
Что произойдет при повторном обращении к этому изображению?
Все последующие запросы
Пользователь сразу получит файл из объектного хранилища. Функция даже не будет вызвана.
Как это работает?
Чтобы 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 схему кэширования.