Масштабируя до 100 миллионов: архитектура, определяемая уровнем сервиса

Это третья часть цикла «Масштабирование Wix до 100 миллионов пользователей». Вступление и второй пост.

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

Развертывание новой версии нашей системы в некоторых случаях требовало изменения схемы MySQL. Поскольку Hibernate не прощает несовпадений между ожидаемой им схемой и реальной схемой базы данных (БД), мы использовали общую практику развертывания программного обеспечения: плановая двухчасовая остановка в период наименьшего трафика (полночь в США на выходных). За время этой плановой остановки мы должны были остановить сервис, выключить сервер, внести изменения в схему MySQL, развернуть новую версию и перезапустить сервер.

Эта плановая двухчасовая остановка часто превращалась в нечто более сложное из-за проблем, которые могли случаться при развертывании. В некоторых случаях внесение изменений в схему MySQL занимало заметно больше времени, чем планировалось (изменение больших таблиц, перестройка индексов, отмена ограничений на миграцию данных и т.д.). Иногда после изменения схемы и попытки перезапустить сервер он не запускался из-за каких-то непредусмотренных проблем с развертыванием, конфигурацией или схемой, которые не давали ему работать. А в некоторых случаях новая версия нашего программного обеспечения оказывалась неработоспособной, поэтому для восстановления сервиса нам приходилось снова менять схему MySQL (чтобы привести ее в соответствие с предыдущей версией) и вновь разворачивать предыдущую версию системы.
Но самое худшее случалось, если через несколько дней после «успешного» развертывания мы обнаруживали в новой версии критический, хоть и редкий, баг, приводивший к повреждению пользовательских сайтов. В этом случае самым лучшим было откатиться к предыдущей версии (по крайней мере до момента исправления бага), а для этого требовалось снова менять схему, что означало внеплановую остановку сервиса.
Важно отметить, что, поскольку мы использовали одно серверное приложение для обслуживания всех систем Wix, остановка затрагивала весь сервис, включая опубликованные сайты. Поскольку наша пользовательская база росла, все больше и больше сайтов оказывались затронутыми нашими плановыми и внеплановыми остановками.

А потом нас осенило


Wix выполняет две разные функции: обслуживание действующих сайтов и создание новых сайтов. Остановка создания сайтов оказывает прямое воздействие на наши ежедневные продажи, но остановка действующих сайтов оказывает прямое воздействие на наших существующих и платящих пользователей. Нам нужно было определить и создать разные уровни сервиса для каждой из функций.
Кроме того, после дополнительного анализа мы обнаружили, что большая часть наших нововведений относилась к разработке новых сайтов, и только малое число изменений касалось действующих сайтов. Это означало, что мы делали частые релизы программного обеспечения, которое подвергало риску функционирование как создаваемых, так и уже работающих сайтов, даже если изменения касались только создаваемых сайтов.

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

Технологический стек, выбранный для выстраивания публичного сегмента, был намеренно простым. Мы больше не использовали Hibernate, мы отказались от любых форм кэша, и мы начали использовать Spring MVC 3.0. Важным принципом проектирования было сделать сегменты не связанными друг с другом в терминах программного обеспечения, цикла релизов и хранения данных, а также сделать программный стек простым для понимания и оптимизированным для обслуживания сайтов.

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

cccbe93757aa488ea31e88f122d2c516.jpg

В результате развертывания публичного сегмента стали редкими и низкорискованными. Он по-прежнему функционирует в системе Wix, спустя шесть лет после первого развертывания (хотя кое-что изменилось с тех пор).

Чему мы научились


Мы уже понимали, что цикл релиза связан с риском, но теперь осознали, что две наши ключевые бизнес-функции — строительство и обслуживание сайтов — по-разному подвержены риску. Мы поняли, что нам нужно обеспечить разные уровни сервиса для этих функций и что именно вокруг них мы должны выстраивать нашу систему. Что это за разные уровни сервиса? Мы рассматривали следующие аспекты: доступность, производительность, рискованность изменений и время восстановления после сбоя. Публичный сегмент, который затрагивает всех пользователей и все сайты Wix, должен иметь наивысший уровень сервиса по этим аспектам. Но в редакторском сегменте сбой затрагивает только пользователей, непосредственно занятых созданием сайта, поэтому последствия для бизнеса менее значительные. Поэтому мы несколько поступились высоким уровнем сервиса ради большей гибкости, что позволило снизить усилия, необходимые для разработки.

Главный архитектор программного обеспечения конструктора сайтов Wix,
Йоав Абрахами
Оригинал статьи: блог инженеров компании Wix

© Habrahabr.ru