В статье рассказано про опыт организации бюджетного хранения архива изображений для сайта с миллионами объявлений.
Под изображениями в моем случае понимаются фотографии квартир, домов, участков и т.д. У меня есть собственный проект который представляет из себя сайт с объявлениями о продаже и аренде недвижимости. Сайту уже что-то около 6 лет и за это время скопилось достаточно большое количество объявлений. На каждой карточке объекта отображаются фотографии, в среднем 8 фотографий на объявление. Собственно эти фотографии я и собираюсь хранить в облаке чтобы потом показывать их посетителям на карточках объектов.
Как я хранил их раньше? — никак. Я не хранил у себя изображения кроме тех которые были размещены вручную. В большинстве же случаев объявления попадают на сайт через партнеров посредством автоматической загрузки фида. В фиде для каждого объекта есть ссылки на фотографии — вот ссылки я и храню, и отдаю посетителю фотографию напрямую от партнера. Эта схема прекрасно работает и экономит кучу ресурсов.
Фотографии которые видят посетители в подборке объявлений или в карточке объекта на самом деле подгружаются со сторонних ресурсов.
Есть один нюанс связанный со спецификой сайта — архивные объекты не удаляются никогда. Т.е. после того как объявление снято с публикации, оно конечно пропадает из поисковой выдачи, но по прямой ссылке доступно всегда (без контактов продавца). Какое-то время ссылки на фотографии еще живут, бывает что годами, но рано или поздно они умирают. Архивные объекты имеют ценность потому что на них продолжают приходить посетители из поисковых систем. Также по архиву строится карта цен (я уже писал про нее), а еще я случайно открыл дополнительный источник дохода для проекта в виде продажи контактных данных архивных объектов. Зачем они их покупают — я точно не знаю, но предполагаю, что посетители хотят получить контакты потому что думают что объявление снято с публикации случайно или по ошибке. Также наверное бывает что хотят узнать что-то у предыдущих владельцев. Так или иначе, объявление с фотографиями в данном случае имеет больше шансов на то чтобы быть купленным. Ценность фотографий возрастает после осознания этого нюанса.
Объемы данных которые я собираюсь хранить в облаке составляют около 3-4 терабайт. Плюс ежедневный прирост в несколько гигабайт. Учитывая что напрямую данное нововведение денег не принесет, а лишь косвенно может повлиять на принятие решения посетителем, бюджет в который я хотел уложиться очень скромный — это 1000-2000 р. в месяц. Хорошо бы вообще бесплатно, но такой возможности я не нашел.
Я как-то сразу посмотрел в сторону Azure потому что работаю на .net, и часто вижу красивые рекламные статьи по этой теме. Плюс приходится пользоваться данной платформой по основной работе, но там мои возможности ограничены требованиями бизнеса и желаниями руководства.
Azure предлагает BLOB-storage с тремя уровнями хранилища: Hot, Cool и Archive. Цены на всех уровнях разные. В общих словах, чем горячее — тем дешевле чтение\запись и дороже ежемесячная плата за хранение, и наоборот. На Hot — выгодно много писать\читать и удалять, но дорого долго хранить. А на Archive дешево хранить но дорого читать\писать. Также на архивном и холодном уровнях есть плата за раннее удаление — это означает что если я удаляю (или перевожу на другой уровень) объект раньше чем определенный срок, то с меня все-равно возьмут плату как за весь этот срок. Для архивного уровня — это 180 дней, для холодного — 30.
Стоимость хранения составляет $0.0023 за Гб в месяц на архивном уровне, $0.01 на холодном и $0.0196 на горячем. По текущему курсу это примерно 0.15, 0.65 и 1.28 рубля соответственно.
Я сравнил со стоимостью в Amazon и Google, получается что в Azure дешевле.
Помимо стоимости хранения необходимо учитывать стоимость операций — они тоже на всех уровнях разные. Цены приводятся за 10 000 операций.
Hot
Чтение: $0.0043, запись: $0.054
Cool
Чтение: $0.01, запись: $0.10
Archive
Чтение: $6, запись: $0.12
Пока объявление активно, фотографии в нем отображаются по ссылкам со сторонних ресурсов (от партнеров). После снятия объявления с публикации, оно становится архивным, но ссылки на фотографии еще какое-то время живы. Рано или поздно они умирают, и нужно позаботиться чтобы к этому времени была в наличии архивная копия.
Процесс обработки фотографий можно описать следующими шагами:
Когда процесс был написан и протестирован, настало время опытной эксплуатации, и тут ожидаемо возникли неприятности. В очереди на тот момент было около 10 миллионов объектов, я решил начать миграцию с 30 000 объектов в день. Настроил красивые графики на дашборде и стал наблюдать. В статистике я увидел странные “выпады” с запросами GetBlobProperties. Они происходят с примерно равным интервалом в один час, начинаются всегда спустя примерно полтора часа после запуска миграции, и длятся еще какое-то время после ее завершения.
Количество таких запросов было слишком большим чтобы не обращать на них внимание. Я смотрел логи и видел что эти запросы идут не от моего сервера а с иностранных IP-адресов. Платить за них мне совсем не хотелось.
Я искал на стэке и в документации, но безрезультатно. Написал вопрос на Stackoverflow и в техподдержку. В итоге после длительной переписки с техподдержкой, и предоставления им логов, они мне сообщили что могут воспроизвести ситуацию и это баг на их стороне.
Интересный нюанс, что на мой вопрос на Stackoverflow был дан ответ не объясняющий причин, а только подтверждающий что я буду платить за эти запросы, но человек давший ответ настойчиво просил чтобы я пометил его как правильный. Он также вскользь намекнул мне что у них (в поддержке) не приветствуется распространяться об ошибках в собственных продуктах. Я дал ему понять что не сделаю этого пока он не напишет правду. Я мог бы написать это сам, но подумал что у сотрудников техподдержки наверняка результативность измеряется в том числе и количеством подтвержденных ответов, так что я предложил ему написать истинную причину и в этом случае отмечу его ответ как правильный. После недолгих колебаний, он согласился и дополнил свой комментарий сообщением о баге. В целом мне понравилось как работает техподдержка — меня даже перевели на русскую девушку которая до сих пор держит меня в курсе изменений по этой проблеме.
Факт признания бага меня удовлетворил только морально, но мне хотелось запустить механизм в работу, и при этом не платить деньги за левые запросы. Особенно учитывая что я нормально так заморочился чтобы максимально снизить количество запросов и тем самым стоимость.
В техподдержке мне посоветовали подождать с запуском а спустя пару недель написали что баг исправлен, но когда будет релиз с исправлением — неизвестно. Предложили включить логирование и работать так, а после релиза запросить компенсацию в Microsoft. Собственно, в таком режиме это пока и работает. Я ежедневно запускаю миграцию небольшого количества объектов и жду релиза.
Стоимость ежедневных 30000 объектов обходится пока в 900 р. в месяц — и это вполне приемлемо. Большая часть расходов — это операции записи. Так что когда вся очередь будет обработана и наступит этап плановой работы, будет понятно какова реальная стоимость такого хранилища. Но по моим подсчетам это произойдет примерно через год.
Когда будет релиз в Azure Blob-storage я допишу здесь удалось ли получить компенсацию. Относительно ежемесячных трат — это около 10% стоимости.
Под изображениями в моем случае понимаются фотографии квартир, домов, участков и т.д. У меня есть собственный проект который представляет из себя сайт с объявлениями о продаже и аренде недвижимости. Сайту уже что-то около 6 лет и за это время скопилось достаточно большое количество объявлений. На каждой карточке объекта отображаются фотографии, в среднем 8 фотографий на объявление. Собственно эти фотографии я и собираюсь хранить в облаке чтобы потом показывать их посетителям на карточках объектов.
Как я хранил их раньше? — никак. Я не хранил у себя изображения кроме тех которые были размещены вручную. В большинстве же случаев объявления попадают на сайт через партнеров посредством автоматической загрузки фида. В фиде для каждого объекта есть ссылки на фотографии — вот ссылки я и храню, и отдаю посетителю фотографию напрямую от партнера. Эта схема прекрасно работает и экономит кучу ресурсов.
Фотографии которые видят посетители в подборке объявлений или в карточке объекта на самом деле подгружаются со сторонних ресурсов.
Есть один нюанс связанный со спецификой сайта — архивные объекты не удаляются никогда. Т.е. после того как объявление снято с публикации, оно конечно пропадает из поисковой выдачи, но по прямой ссылке доступно всегда (без контактов продавца). Какое-то время ссылки на фотографии еще живут, бывает что годами, но рано или поздно они умирают. Архивные объекты имеют ценность потому что на них продолжают приходить посетители из поисковых систем. Также по архиву строится карта цен (я уже писал про нее), а еще я случайно открыл дополнительный источник дохода для проекта в виде продажи контактных данных архивных объектов. Зачем они их покупают — я точно не знаю, но предполагаю, что посетители хотят получить контакты потому что думают что объявление снято с публикации случайно или по ошибке. Также наверное бывает что хотят узнать что-то у предыдущих владельцев. Так или иначе, объявление с фотографиями в данном случае имеет больше шансов на то чтобы быть купленным. Ценность фотографий возрастает после осознания этого нюанса.
Объемы данных которые я собираюсь хранить в облаке составляют около 3-4 терабайт. Плюс ежедневный прирост в несколько гигабайт. Учитывая что напрямую данное нововведение денег не принесет, а лишь косвенно может повлиять на принятие решения посетителем, бюджет в который я хотел уложиться очень скромный — это 1000-2000 р. в месяц. Хорошо бы вообще бесплатно, но такой возможности я не нашел.
Azure
Я как-то сразу посмотрел в сторону Azure потому что работаю на .net, и часто вижу красивые рекламные статьи по этой теме. Плюс приходится пользоваться данной платформой по основной работе, но там мои возможности ограничены требованиями бизнеса и желаниями руководства.
Azure предлагает BLOB-storage с тремя уровнями хранилища: Hot, Cool и Archive. Цены на всех уровнях разные. В общих словах, чем горячее — тем дешевле чтение\запись и дороже ежемесячная плата за хранение, и наоборот. На Hot — выгодно много писать\читать и удалять, но дорого долго хранить. А на Archive дешево хранить но дорого читать\писать. Также на архивном и холодном уровнях есть плата за раннее удаление — это означает что если я удаляю (или перевожу на другой уровень) объект раньше чем определенный срок, то с меня все-равно возьмут плату как за весь этот срок. Для архивного уровня — это 180 дней, для холодного — 30.
Цены
Стоимость хранения составляет $0.0023 за Гб в месяц на архивном уровне, $0.01 на холодном и $0.0196 на горячем. По текущему курсу это примерно 0.15, 0.65 и 1.28 рубля соответственно.
Я сравнил со стоимостью в Amazon и Google, получается что в Azure дешевле.
Azure | Amazon (S3) | ||
Hot | $0.0196 | $0.024 | $0.026 |
Cool | $0.01 | $0.01 | $0.01 |
Archive | $0.0023 | $0.0045 | $0.007 |
Помимо стоимости хранения необходимо учитывать стоимость операций — они тоже на всех уровнях разные. Цены приводятся за 10 000 операций.
Hot
Чтение: $0.0043, запись: $0.054
Cool
Чтение: $0.01, запись: $0.10
Archive
Чтение: $6, запись: $0.12
Логика работы
Пока объявление активно, фотографии в нем отображаются по ссылкам со сторонних ресурсов (от партнеров). После снятия объявления с публикации, оно становится архивным, но ссылки на фотографии еще какое-то время живы. Рано или поздно они умирают, и нужно позаботиться чтобы к этому времени была в наличии архивная копия.
Процесс обработки фотографий можно описать следующими шагами:
- Как только объявление пропадает из файла импорта партнера, т.е. партнер перестал его публиковать, формируется запись в приоритетную очередь, где приоритетом считается количество просмотров посетителями — чем больше просмотров, тем больше вероятность что будучи архивным, объект будет просматриваться и дальше.
- При обработке записи из очереди формируется BLOB-объект содержащий в себе уменьшенные (до 800х600) фотографии для объявления. Использование композитных объектов вместо непосредственно фотографий тоже обусловлено экономией — вместо 8 операций записи (в среднем 8 фоток на объект) производится одна, а каждая операция стоит денег.
- BLOB загружается сначала в Hot, а потом сразу же перемещается в архив. Возможности писать напрямую в архив нет, а поскольку в Cool есть плата за раннее удаление, то дешевле в качестве транзита использовать Hot.
- В архиве BLOB лежит до тех пор пока ссылки на оригинальные фотографии активны (фотогафии пока что показываются по ссылкам от партнеров).
- Проверка на работоспособность ссылок производится при заходе посетителя на карточку объекта — если на нее ходят, значит объект популярен и восстанавливать фотографии из архива имеет смысл.
- Если ссылки на оригинальные фотографии умерли, проверяю, есть ли архивная копия, и если есть, отправляю запрос на восстановление из архива в Cool (восстановление BLOB-объекта из архива может занимать до 15 часов — у Microsoft это называется rehydration).
- Как только BLOB был восстановлен из архива, он копируется в локальное хранилище и разделяется на нормальные фотографии. Локальное хранилище — это жесткий диск моего сервера.
- Фотографии на карточку объявления отдаются уже из локального хранилища.
- В локальном хранилище фотографии хранятся несколько дней. Если за эти это время были просмотры — срок локального хранения продлевается. Если просмотров не было, фотографии удаляются из локального хранилища, но остаются на Cool-уровне в Azure.
- Из Cool в Archive они копируются если просмотров не было в течении двух месяцев — объект явно не популярен и соответственно нет смысла переплачивать за хранение в Cool.
Первый запуск
Когда процесс был написан и протестирован, настало время опытной эксплуатации, и тут ожидаемо возникли неприятности. В очереди на тот момент было около 10 миллионов объектов, я решил начать миграцию с 30 000 объектов в день. Настроил красивые графики на дашборде и стал наблюдать. В статистике я увидел странные “выпады” с запросами GetBlobProperties. Они происходят с примерно равным интервалом в один час, начинаются всегда спустя примерно полтора часа после запуска миграции, и длятся еще какое-то время после ее завершения.
Количество таких запросов было слишком большим чтобы не обращать на них внимание. Я смотрел логи и видел что эти запросы идут не от моего сервера а с иностранных IP-адресов. Платить за них мне совсем не хотелось.
Я искал на стэке и в документации, но безрезультатно. Написал вопрос на Stackoverflow и в техподдержку. В итоге после длительной переписки с техподдержкой, и предоставления им логов, они мне сообщили что могут воспроизвести ситуацию и это баг на их стороне.
Интересный нюанс, что на мой вопрос на Stackoverflow был дан ответ не объясняющий причин, а только подтверждающий что я буду платить за эти запросы, но человек давший ответ настойчиво просил чтобы я пометил его как правильный. Он также вскользь намекнул мне что у них (в поддержке) не приветствуется распространяться об ошибках в собственных продуктах. Я дал ему понять что не сделаю этого пока он не напишет правду. Я мог бы написать это сам, но подумал что у сотрудников техподдержки наверняка результативность измеряется в том числе и количеством подтвержденных ответов, так что я предложил ему написать истинную причину и в этом случае отмечу его ответ как правильный. После недолгих колебаний, он согласился и дополнил свой комментарий сообщением о баге. В целом мне понравилось как работает техподдержка — меня даже перевели на русскую девушку которая до сих пор держит меня в курсе изменений по этой проблеме.
Факт признания бага меня удовлетворил только морально, но мне хотелось запустить механизм в работу, и при этом не платить деньги за левые запросы. Особенно учитывая что я нормально так заморочился чтобы максимально снизить количество запросов и тем самым стоимость.
В техподдержке мне посоветовали подождать с запуском а спустя пару недель написали что баг исправлен, но когда будет релиз с исправлением — неизвестно. Предложили включить логирование и работать так, а после релиза запросить компенсацию в Microsoft. Собственно, в таком режиме это пока и работает. Я ежедневно запускаю миграцию небольшого количества объектов и жду релиза.
Заключение
Стоимость ежедневных 30000 объектов обходится пока в 900 р. в месяц — и это вполне приемлемо. Большая часть расходов — это операции записи. Так что когда вся очередь будет обработана и наступит этап плановой работы, будет понятно какова реальная стоимость такого хранилища. Но по моим подсчетам это произойдет примерно через год.
Когда будет релиз в Azure Blob-storage я допишу здесь удалось ли получить компенсацию. Относительно ежемесячных трат — это около 10% стоимости.