Pull to refresh

Изменение размеров изображений на сайте

Reading time 6 min
Views 12K
Добрый день. Я разработчик с более чем 10-летним стажем. Для того, чтобы оценить качество исходного кода сайтов, не без доли самоиронии, я создал небольшой чек-лист. Сегодня я поговорю о важном для меня пункте — изображения на сайтах. Я умышленно опустил конкретную технологию, потому что эта проблема встречалась и встречается повсеместно, я буду очень признателен, если в комментариях вы раскроете свои подходы с использованием вашего стека технологий, в конечном итоге мы все очень похожи.



Опытным путем, я установил, что способ работы с изображением на сайте – лакмусовая бумажка качества. Посмотри как человек работает с изображениями в пяти размерах и можно сделать вывод обо всем проекте. Причина вполне понятна, я не встречал книги или статьи, где описана логика хранения, обновления и работы с изображением, если кто-то укажет её в комментариях – буду признателен. Каждый придумывал свой велосипед сервисов, который умел сохранять по определённой структуре каталогов или в базе. Шло время, сайты на поддержке развивались, где-то менялись размеры изображений, где-то добавлялся новый функционал, который требовал нового размера ранее загруженных изображений. Каждый шаг добавлял новый виток уже отлаженной процедуры: походим по всем изображениям – оригиналам, меняем размер и сохраняем в нужных параметрах. Долго, дорого.

Ручное управление рано или поздно приведет к сбою, потребует лишних денег для проверки в тестовой среде. Я приступил к поиску подобной проблемы у других, ведь давно известно, что если у тебя какая-то проблема, то ты не первый, кто с ней столкнулся. Достаточно быстро я вышел на облачные сервисы изменения изображений, кэширования и размещения. Я был восхищен простотой решения, используя ссылку на оригинал изображения и управляющие параметры в ней можно получать обрезанные, сжатые, перевернутые, сдвинутые, прозрачные, изображения с нанесенным текстом и эффектами и многое, многое другое. Один из таких сервисов, показавшийся мне наиболее простым и удобным, я решил опробовать. Для этого я составил список необходимого мне функционала и решил снять временные характеристики, ведь ни для кого не секрет, что скорость работы сайта является очень важным параметром с точки зрения пользователя и поисковых систем.

Примерный список по памяти:

  • Изменение ширины, пропорциональное изменение высоты.
  • Изменение высоты, пропорциональное изменение ширины.
  • Обрезка изображения в заданных границах.
  • Вписывание изображения в границы прямоугольника.
  • Кэширование и хранение результатов на стороне сервиса, при этом его регулярное обновление в зависимости от ETag и MaxAge.
  • Время получения измененного изображения новым пользователем из России.
  • Доступность https.
  • Приемлемая цена сервиса и прозрачность его оплаты.

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

Параллельно я смотрел скорость и, сказать честно, я не ожидал хороших результатов по скорости, так как на карте расположения серверов обработки и хранения России не оказалось. Но раньше замечал, что скорость в Европу и США бывает значительно лучше, чем до соседнего города, потому решил проверить. Результаты оказались приемлемыми, около 35-60 ms на изображение при изменении ширины изображения с 3000 до 500 и 30-150KB результате.

Дальше кэширование было основано на MaxAge и Last-modified, ETag отсутствовал и никак не транслировался с исходного сервера хранилища, но я не смог придумать ситуации, когда он может понадобится, если есть Last-modified. MaxAge, при правильной настройке, спокойно перетекал на сервис. Мне стало интересно, каким образом сервис отрабатывает изменение оригинального изображения на сервере хранилище. В голове было три алгоритма, по первому он должен был перед тем, как вернуть изображение – обратиться к исходному хранилищу и посмотреть у него Last-modified, по второму он должен был в фоне сравнивать информацию о том, что хранится на сервисе и у хранилища раз в какое-то время, например, полученное через MaxAge и третий, когда следующее обновление назначалось через MaxAge, но происходило только если клиент делает запрос. Решил установить простым экспериментом, изменив оригинал и запросив от сервиса изображение. Тогда я обнаружил, что изображение не изменилось, значит сервис не обращается к хранилищу до определенного момента. При этом если изменить изображение снова, то оригинальное изображение будет взято из кэша сервиса, а не с хранилища. Дальше, меняя MaxAge, я добился обновления оригинального изображения в кэше сервиса.

В моем списке цена стояла на последнем месте по порядку, но не по приоритету. Я был неприятно расстроен ценой (цены привожу на сегодняшний день) от 500$ за план с SLA, при этом план по количеству доступов к оригинальному изображению тоже устраивал плохо, каждая 1000 изображений оплачивалась отдельно. При этом было непонятно, как считаются доступы к оригинальному изображению. Считается ли доступом повторный запрос ранее измененного изображения из кэша сервиса, без использования кэша браузера, т.е. новым пользователем, но раньше кто-то его уже вызывал и изменил. Вопрос этот возник потому, что у нас на одном из проектов было больше 150 новых оригинальных изображений каждый день, которые просматривали не менее 5 тысяч человек ежедневно. На запросы из кэша приходились только ~50% запросов. Ответ был простым, после загрузки в кэш сервиса изображения, все операции с ним безлимитные и ограничение только по расходуемому трафику. Прикинув количество изображений выходило порядка 150 долларов ежемесячно без учета трафика.



Все бы хорошо, но настал 2014 год и доллар стал уверенно преодолевать границы разумного, доброго, вечного. Бабло начало побеждать зло и было принято решение, создать свой сервис по изменению изображений налету. Так появился внутренний проект, а недавно (около года назад) я и команда опубликовали бета версию для публичного тестирования. Сервис построен с использованием технологий Microsoft .NET, и NoSQL Redis для кэширования оригинальных изображений. С нами работают разные страны, в совокупности около 15 сайтов. Один из наших клиентов, сайт из Вьетнама популярной вьетнамской музыки, насколько мы можем судить, откуда он узнал о нашем сервисе до сих пор остаётся загадкой. Посещаемость каждого из сайтов от 50 до 30 000 человек в день. Наша целевая аудитория это относительно небольшие (до 50 000 – 100 000 человек в день. Размер оригиналов изображений до 10MB каждого, ограничен внутри системы) информационный сайты, интернет-магазины, каталоги продукций и просто сайты с отзывчивым дизайном и желанием уменьшить трафик или восполнить пробелы с пережатием изображений в старом IE.

Архитектура


Первой версией проекта была прямолинейная обработка, никакой авторизации и полная свобода действий для пользователей сервиса. Скажу сразу – это плохая идея, по всем параметрам кроме удобства пользователя, пока сервис не упадёт под нагрузкой недобросовестных пользователей или напрямую нарушающих законодательство. Лучше всего это показать на схеме и обозначить основные компоненты.



Всю статистику запросов, все параметры кэширования мы хранили на Redis. Там же хранили оригиналы и обработанные файлы, потому что хотели добиться максимальной скорости отдачи контента пользователю, минимизировав участия дисков. Запустив наш прототип, поняли, что он вполне жизнеспособен и покрывает требования по одному из сайтов с лихвой (5 000 — 10 000 пользователей в сутки). Разместили на собственном железе, приступили к использованию. Проблемы начались, когда мы захотели масштабироваться. Не потому, что мы получили какой-то предел решения, а потому, что к нам начали проявлять интерес другие клиенты и мы стали опасаться, что не справимся с нарастающей нагрузкой.

Так родилась вторая версия сервиса. Версия, построенная на очереди поверх Redis и микросервисах, слушающих события этой очереди. Фасад остался за IIS, но сильно похудел и стал проксировать запросы к нужным сервисам. Появились ограничения как на количество файлов, так и на их размер, привязка к доменному имени, чтобы избежать недобросовестных пользователей и указать владельца соответствующим структурам, в случае их интереса. Появился DNS с Round Robin и возможностью выдавать адреса относительно предполагаемого адреса клиента (CDN).



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

Вторую версию сервиса мы продолжаем развивать. Мы очень хотим получить от пользователей обратную связь. У нас есть список возможного развития, с новыми функциональными возможностями:

  • Нанесение текста на изображение — уже реализовано
  • Установка качества в контексте домена, правил и/или операции (сейчас это жесткое значение OptimalCompression)
  • Добавление выбора системы — плана кэширования оригинальных изображений
  • Добавление источников, отличных от сайта (например Amazon или новоиспеченный Mail с его холодным хранилищем)
  • Размещение дополнительных сервисов за пределами центрального региона

Нужно – не нужно, важно – не важно, поэтому при регистрации выдается план Early Adopter, с 500MB хранилища, до 5 доменов, 2000 оригинальных изображений. Он останется с вами, только если вы не удалите аккаунт (это можно сделать самостоятельно из панели управления в любой момент времени). Все предложения можно и нужно отправлять по контактам поддержки или в комментариях тут. Учитывайте, что план Early Adopter гибкий и, если вам необходимы большие масштабы, просто напишите в поддержку. Высока вероятность, что вам помогут. Также если интересно, как какая-то из частей устроена внутри – пишите. Я постараюсь ответить на все вопросы, где-то просто привести примеры кода.

Спасибо!


Контакты. Я старался подойти к статье объективно, не нарушать правила топиков и рекламы, чтобы поделиться с вами своими мыслями о простоте подхода. Больше вам спасибо за внимание и время. Контакты сообщу в личном сообщении или комментарии, при наличии интереса.
Tags:
Hubs:
+14
Comments 19
Comments Comments 19

Articles