- PVSM.RU - https://www.pvsm.ru -

По следам недавней статьи [1] об изменении размеров изображений на сервере, я решил поделиться опытом внедрения модуля ImageResizer [2] для IIS. Конечно написать простой обзор было бы слишком скучно, но мы не ограничились простым внедрением модуля.
Итак, у нас в распоряжении был купленный ImageResizer + набор плагинов Cloud Bundle [3] для работы с облаками.
К сожалению мне запрещено называть проекты, в которых внедрено данное решение, но я могу обрисовать суть. Это новостные порталы ориентированные на северную америку. На сайте представлены статьи и видео ролики.
Статьи хранятся в БД, редактор может прикрепить к статье заглавную картинку. Изображение хранится в Amazon S3. Как Вы понимаете, редактор может загрузить изображение как маленькое, так и огромное и при этом нельзя терять оригинал.
Видео файлы загружаются, обрабатываются и хранятся в облачном хранилище видео BrightCove [4]. После загрузки видео в хранилище, оно всячески обрабатывается, перекодируется в несколько потоков разного формата и для видео автоматически выбирается миниатюра (thumbnail).
Естественно, раз все это происходит в облаке, то и картинка хранится в облаке, а мы получаем прямую ссылку для вставки. Но и тут картинка не всегда может соответствовать требуемому размеру.
Итого мы имеем набор изображений в Amazon S3, набор изображений в BrightCove и все изображения нужно уметь быстро отдавать уже подогнанными под нужный размер. Кроме того, в разных частях сайта могут использоваться различные размеры изображений. При этом набора плагинов для кеширования [5] у нас не было, зато у нас был CloudFront.

Как ни странно, товарищ bitmap [6] в своей статье не упомянул, как именно он изменяет размер изображения, ибо есть множество способов (муки выяснения необходимого варианта с заказчиком Вы можете лицезреть на фото). Можно растягивать в рамку, получая растянутые лица, можно сохранять пропорции и заполнять освободившееся пространство цветом. Можно сохранять пропорции и обрезать края. Модуль также позволяет еще кучу не нужных нам рюшечек, типа наложения фильтров и прочего. В итоге, на одном проекте мы стали растягивать аналогично растягиванию css, а на другом проекте заполнение цветом.
По умолчанию из коробки предполагается что изображения и IIS расположены на одном сервере и изменение размеров осуществляется простым добавлением параметров к ссылке:
/image.jpg?height=200&width=300
или
/image.jpg?h=200&w=300.
Отлично, но как забрать изображения из Amazon S3?
Тут нам на помощь приходит первый из набора плагинов Cloud Bundle: S3 Reader [7]. Путем нехитрых настроек web.config, он позволяет использовать ссылку следующего формата:
/s3/bucket/folder/image.jpg?h=200&w=300
Ок, теперь мы можем отдавать картинки из S3, но S3 это довольно популярная вещь, как насчет совершенно стороннего сервера? Здесь включается RemoteReader plugin [8]. Тут уже не все так просто. Конечная ссылка имеет следующий формат:
/remote.jpg.ashx?w=200&height=300&urlb64=45b45c4a2099b...&hmac=a2099ba2099b.
Где remote.jpg.ashx это конечная точка для перехвата ссылки модулем, параметр urlb64 — это нехитро зашифрованная при помощи HMAC SHA-256 конечная ссылка на удаленный сервер с картинкой. Данную ссылку генерирует специальный метод:
RemoteReaderPlugin.Current.CreateSignedUrl("http://remote.com/image.jpg");
Ок, с основной задачей мы справились. Теперь нужно как-то кешировать результат, иначе быстро все это работать не будет.
Кеширующих плагинов у нас нет, зато есть такая волшебная вещь, как CloudFront custom origin. Мы создали новую дистрибуцию CloudFront, указывающую на наш домен. Так что теперь у нас есть ссылки формата:
httр://my-distribution-name.cloudfront.com/remote.jpg.ashx?w=200&height=300&urlb64=45b45c4a2099b...&hmac=a2099ba2099b
и
httр://my-distribution-name.cloudfront.com/s3/bucket/folder/image.jpg?h=200&w=300
Но теперь наш сайт стал открываться по адресу httр://my-distribution-name.cloudfront.com, забивая cloudfront. Тогда мы быстро добавили раздел для картинок. И CloudFront со ссылки
httр://my-distribution-name.cloudfront.com/s3/bucket/folder/image.jpg?h=200&w=300
cтал перенаправлять запрос на
httр://my-site.com/images/s3/bucket/folder/image.jpg?h=200&w=300
Вроде бы вся должно работать, но внезапно выяснилось, что CloudFront нещадно рубит длинные строки параметров и мы получили тонны ошибок и не открывающихся картинок. Тут нам помог CloudFront plugin [9], позволивший преобразовать ссылки к следующему формату:
httр://my-distribution-name.cloudfront.com/remote.jpg.ashx;w=200;height=300;urlb64=45b45c4a2099b...;hmac=a2099ba2099b
и
httр://my-distribution-name.cloudfront.com/s3/bucket/folder/image.jpg;h=200;w=300
Все это отлично работало, но инженерная мысль пошла еще дальше. Что если кто-то начнет генерировать не нужные нам разрешения картинок? Максимальный размер увеличения конечно ограничен, но все равно так можно заDDOSить сайт, да еще и полученные картинки разнесутся по сотням серверов CloudFront по всему миру. Ну и конечно длина ссылки просто ужасна. Тогда мы решили реализовать функционал коротких ссылок.
При генерации ссылки мы складываем в базу полученную длинную ссылку вида:
/remote.jpg.ashx;w=200;height=300;urlb64=45b45c4a2099b...;hmac=a2099ba2099b
и получаем её id в таблице. В вёрстку же выплевываем ссылку формата:
httр://my-distribution-name.cloudfront.com/42
CloudFront обращается к нам по адресу:
httр://my-site.com/i/42
Мы перехватываем запрос, выбираем длинную ссылку по ключу 42 из БД, в серверном коде делаем HttpRequest к самому себе, чтобы его перехватил ImageResizer и в ответ выдаем результат его работы. CloudFront складывает полученную картинку на своих серверах и больше мы не получаем этот запрос до следующей инвалидации кеша.
И последний штрих это сокрытие страшного префикса CloudFront ссылки, представляющей собой беспорядочный набор цифр и букв, что тоже не очень красиво, при помощи дополнительного домена.
В итоге конечная для пользователя ссылка имеет вид:
httр://short.com/42
При этом изображение закешировано, легко доступно с ближайшего к пользователю сервера, злобный хакер не может самостоятельно изменить размер, заDDOSив наш модуль, мы имеем короткую ссылку и самое главное все картинки с нужными размерами красиво смотрятся на своих местах.
В заключение хочу сказать, что плагин прекрасно работает, имеет кучу различных настроек и плагинов на все случаи жизни, имеет режим отладки на случай непредвиденных ситуаций. Автор отвечает при обращении по проблемам и даже вроде бы платит за найденные баги. Конечно, модуль платный, но он того стоит.
Автор: ST-bobr
Источник [10]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/net/21478
Ссылки в тексте:
[1] статьи: http://habrahabr.ru/post/160059/
[2] ImageResizer: http://imageresizing.net/
[3] Cloud Bundle: http://imageresizing.net/plugins/bundles/3
[4] BrightCove: http://www.brightcove.com/en/
[5] плагинов для кеширования: http://imageresizing.net/plugins/bundles/1
[6] bitmap: http://habrahabr.ru/users/bitmap/
[7] S3 Reader: http://imageresizing.net/plugins/s3reader
[8] RemoteReader plugin: http://imageresizing.net/plugins/remotereader
[9] CloudFront plugin: http://imageresizing.net/plugins/cloudfront
[10] Источник: http://habrahabr.ru/post/160843/
Нажмите здесь для печати.