В этой статье мы не откроем ничего нового об устройстве монолита и микросервисной архитектуры. Про это сказано немало слов, написано ещё больше. Мы расскажем о том, как через это прошла наша компания и какие преимущества и недостатки микросервисной архитектуры мы для себя обнаружили.
Как и многие другие, IVI начинал свой путь в разработке с монолита. Изначально сервис был b2b-решением, которое предоставляло фильмы для размещения на других площадках. Одной из таких площадок был и собственный сайт IVI, который работал с нашим монолитом. И этот монолит отвечал за раздачу информации о контенте, ссылки на контент, подбор рекламы, загрузку и кодирование новых фильмов.
В 2011 году мы поняли, что запросов к сервису становится много и необходимо масштабировать наше решение. Причём основную массу составляли запросы от пользователей к монолиту за ссылками на фильмы и за рекламой. И не было необходимости масштабировать всё остальное. Мы решили вынести минимальную функциональность в микросервис и сделать некий «лёгкий» сервис. Так мы воспользовались первым преимуществом микросервисной архитектуры — лёгкостью масштабирования микросервисов.
К тому же мы получили бонус в виде простоты разработки. Этот сервис был небольшого размера и отвечал за небольшой набор функций, поэтому новому разработчику было просто в нём разобраться. К тому же у сервиса был небольшой набор тестов, которые быстро выполнялись и можно было быстро запустить их все и проверить, что доработки ничего не сломали. Да, этот сервис был не в полном смысле микросервисом. Он лежал в том же репозитории, что и монолит, имел с ним общий код, при правке которого необходимо было проверять всю функциональность, и, как следствие, имел общие языковые зависимости с монолитом. Но это был первый шаг.
Затем мы решили вынести из монолита систему управления контентом. Тут уже использовалась независимая кодовая база, оставалась только связь со схемой базы данных и средствами описания этой схемы. И примерно в то же время мы начали показывать фильмы на различных устройствах, для которых потребовался некий программный интерфейс. Так родился сервис, отвечающий за интерфейс общения с мобильными приложениями (MAPI). Он был совсем независимым, со своей кодовой базой и хранилищем, которое специальные скрипты синхронизировали с основным хранилищем.
Тут мы столкнулись с другой проблемой, которую, в том числе, позволяют решать микросервисы, правда мы этим не воспользовались. Название этой проблеме — монорепозиторий. С ростом команды разработка в одном репозитории становилась проблемой. Росло количество тестов, и нам пришлось усложнять CI, чтобы распараллелить запуск тестов различных независимых частей репозитория. Но даже это не сильно спасало. Дело в том, что из-за активной разработки скапливалась очередь задач на слияние веток, и разрабатываемая тобой ветка могла быть слита только через пол дня. Если повезёт и кто-то другой не объединит раньше тебя ветку, которая ломает твои тесты.
Поэтому следующие наши микросервисы создавались уже в отдельных репозиториях. И тут мы начали осознавать другое преимущество микросервисов: на них можно пробовать новые технологии, новые языки программирования, новые СУБД. Мы уже не были привязаны к монолиту. Так, например, в нашу разработку ворвался язык Go.
Но в это же время мы столкнулись и со множеством недостатков микросервисов. Первым таким недостатком была сложность разработки. Да, выше мы писали, что микросервисы когда-то позволили нам упростить разработку, так как сервис, отвечающий за маленький кусочек бизнес логики, проще понять, доработать и протестировать. Но микросервисы не работают сами по себе. Они работают в связке с другими микросервисами. И чтобы доработать какой-то один, нужно развернуть локально несколько других. Да и тестировать тоже стало сложно, потому что было несколько тестовых стендов, на которые очень быстро выстраивалась очередь из желающих протестировать доработку в том или ином микросервисе. Для решения этой проблемы мы собрали систему, предоставляющую каждому разработчику или тестировщику свой кластер со всеми необходимыми микросервисами — свой маленький IVI. Эта система позволяла создать такой кластер и быстро развёртывать в нём нужные версии микросервисов. И разработчикам уже не нужно было развёртывать всё локально, достаточно было создать разрабатываемый сервис и ходить из него в свой виртуальный кластер.
Другой проблемой микросервисов стали распределённые транзакции. Так, например, на IVI есть процедура объединения аккаунтов. Когда пользователь открывает только что установленное приложение, у него уже есть аккаунт, привязанный к устройству. И он может смотреть фильмы, добавлять их в очередь просмотра, оценивать. Но через некоторое время пользователь вспоминает, что у него есть зарегистрированный на сайте аккаунт, и он авторизуется под ним на устройстве. Наша задача — объединить пользовательские оценки, очереди со старого и нового аккаунта. Объединение этой информации происходит во множестве микросервисов, и, в теории, должно происходить или везде, или нигде. То есть нужны распределённые транзакции, которые привносят очень большие сложности в бизнес-логику и в разрабатываемую систему. Решать эту проблему мы в итоге не стали: максимально обезопасили критическую для пользователя информацию (его покупки), а если при работе с другими данными возникнут ошибки, то их обнаружат или скрипты валидации данных, или сам пользователь придёт с жалобой в поддержку и ему там помогут.
И ещё одной проблемой стала сложность добавления нового сервиса в production. Средства CD позволяли быстро обновлять существующие сервисы, но это не касалось первоначальной установки. Она подразумевала необходимость установить новые машины в ДЦ или создать виртуалки, установить всё необходимое ПО, настроить CD. И это был небыстрый процесс, а новые доработки обычно требовались довольно срочно. Да, в будущем будут появляться различные средства для решения этой проблемы, но в то время их ещё не было. Хотя даже когда у нас начали появляться средства виртуализации, контейнеризации, оркестрации и эта проблема стала исчезать, на смену пришла другая — сложность эксплуатации. Уже нельзя справиться с десятками сервисов без автоматизации доставки новых версий приложений. Сложность эксплуатации также возрастает в связи с повышением требований к мониторингу и управлению большим количеством сервисов. Решение таких эксплуатационных проблем требует множества навыков и инструментов.
Всё это очень сильно поубавило пыл в написании новых микросервисов. При реализации новых задач мы старались это сделать в рамках уже существующих сервисов. И выделяли микросервисы только в случае крайней необходимости, или если требования к реализуемой задаче совсем не укладывались ни в один из существующих сервисов.
Но компания развивалась, появлялись новые направления разработки, и среди прочего появились сервисы для аналитики. Тут мы столкнулись ещё с одной проблемой микросервисов — согласованность данных. Для различной аналитической обработки требуются данные из множества сервисов. И поддерживать их согласованность очень сложно. Например, мы формируем и отправляем пользователям письма с персональными рекомендациями, предложениями посмотреть тот или иной фильм. Но поскольку данные не согласованы, то может получиться так, что пользователь этот фильм уже посмотрел, и письмо будет неактуальным. Несогласованность данных усложняет бизнес-процессы для работы с этими данными. Например, мы должны были непосредственно перед отправкой проверять в оригинальном хранилище, посмотрел ли пользователь уже этот фильм или ещё нет.
Помимо появления новых микросервисов у нас активно дорабатывались старые микросервисы, туда добавляли больше функциональности, больше различной бизнес-логики. Некоторые сервисы настолько разрастались, что стали походить на монолиты, превратились в своего рода big ball of mud, с большой энтропией кода, сильной связанностью между различными частями сервиса, сложностью масштабирования.
Происходило это из-за того, что продукт активно развивался, в него интенсивно добавляли новые функции, и при этом не было какой-либо единой ответственности, не было небольшой группы человек, отвечающих за архитектуру сервиса, через которых проходили бы все правки. В результате в таких сервисах нередко появлялось дублирование реализации какой-либо функциональности. Например, в одном из сервисов мы нашли три различных варианта работы с AB-тестами.
При этом и наша компания разрасталась, менялась её структура, появлялись команды, развивавшие конкретные направления. И тут мы осознали ещё один недостаток монолитов и преимущество микросервисов — разграничение ответственности. Для каждого микросервиса у нас появились свои ответственные команды. Чего нельзя сказать о разросшихся в размерах сервисах: за них отвечали все и одновременно никто. Стали происходить диалоги вида: «Кто отвечает за сервис X? — Команда A. — У меня вопрос по функциональности F. — А, за этим тебе надо идти в команду B.».
Со временем обнаружились ещё некоторые проблемы монолита. Первой из них стали высокие требования к отказоустойчивости и многочисленные усилия по поддержанию этой отказоустойчивости. Если с каждым из микросервисов мы провели работу и добились деградации функциональности при полной потере микросервиса, то при потере «больших сервисов» мы теряем слишком много функциональности, и весь сервис становится неработоспособным.
Другой проблемой стала сложность поддержки актуального стека технологий. Уже давно закончилась поддержка второго Python, но один из наших сервисов до сих пор на нём работает. А другой сервис мы полгода переводили на третий Python. Да и в целом любой рефакторинг сервисов с большой кодовой базой — это очень сложная задача, которая требует больших усилий для организации плавного перехода на новые технологии, или может потребовать feature freeze на длительный период. К тому же после написания всего необходимого кода очень долгое время занимает тестирование таких изменений. Тогда как микросервисы переводились на Python 3 за пару дней и очень быстро тестировались.
Поэтому сейчас мы приветствуем новые микросервисы. Их становится всё больше. И тут мы начали замечать ещё один недостаток — сложность распространения общих практик на все микросервисы. Например, решили мы собирать все ошибки в Sentry. И теперь нужно пройтись по командам разработки и микросервисам и везде добавить необходимую функциональность. Да и с ростом компании и количества микросервисов их преимущество в виде возможности попробовать новые технологии приобрело негативный оттенок. Зоопарк технологий разрастается, переход людей из команды в команду сопровождается некоторым переобучением. Да и какие-то выбранные практики не всегда можно внедрить в стек технологий, используемый в отдельно выбранном микросервисе.
И несмотря на то, что у нас активно развиваются всё новые и новые микросервисы, их количество превысило 50 штук, у нас остаётся проблема с осознанием того, что некоторые новые куски бизнес-логики лучше выделить в отдельный микросервис, а не добавлять к уже существующим. Обычно это аргументируется тем, что создавать новый сервис долго, а доработки нужны уже сейчас. Мы даже как-то провели небольшой эксперимент и показали, что реализовать новый сервис, настроить его CI, добавить манифесты для Kubernetes и выгрузить в dev-кластер можно за несколько часов, что не сильно дольше, чем пытаться добавить эту же функциональность в уже существующий сервис.
Так что на текущий момент мы видим будущее нашей разработки за микросервисами. Да, у них есть свои проблемы, но каждая такая проблема — это интересный технологический, и местами организационный вызов.
maxim_ge
Интересно, что недавно была статья противоположной направленности...
kuznetsovkd
0x1000000
Статья, вроде как, должна ратовать за микро-сервисы, но после прочтения не покидает ощущение, что идея была “так себе”. Заметил общий шаблон подобных историй: “Был монолит и мы тратили X усилий на его поддержку, но потом нам все надоело и мы потратили 10X усилий на микросервисы и теперь все хорошо, но некоторые проблемы ещё остаются.”
В целом статья классная — очень многие недостатки микросервисов хорошо подмечены.
upagge
Тоже хотел написать подобный комментарий, какая-то антиреклама микросервисов :D
Еще порадовало: Решать эту проблему мы не стали :)
grey-fox
Статья не ставила целью сделать антирекламу микросервисам, как и их рекламу. Мы думаем, что наша компания не единственная, которая столкнулась с трудностями при переходе к микросервисам. И подсветили те, с которыми столкнулись лично мы. Часть из проблем мы решили, часть приняли как риск. Но для себя мы решили что микросервисы лучше монолита. Но этот выбор каждый должен сделать сам, нет единственно правильного ответа что лучше.
denaspireone
схема просто шикарнейшая ;)
картинка в тему
BellaLugoshi
я понимаю что пишу не туда, но мне в целом не так интересно как оно там у вас работает по сравнению с тем как это выглядит со стороны клиента. И я объясню почему я не пользуюсь IVI или любым другим подобным сервисом, например каршерингом.
1) необходимость привязки карты (с этого всё начинается и на этом и заканчивается)
2) огромная цена «за воздух» (когда поход в кинотеатр стоит 90 рублей, а тот же самый фильм в онлайн 400-800 руб или обязанность на подписку на самый дорогой тарифный план)
3) отсутствие контента (зачем платить каждый месяц 2000 рублей за возможность два раза в год что-то посмотреть? слабо себе представляю адекватного человека который платит 24000 за просмотр двух фильмов)
valery1707
У меня сейчас есть подписка на
IVI
и вот что я могу сказать:2 990
рублей в год, то есть примерно249
рублей в месяц299
/399
рублей (взял цену с фильма "День курка" 2021 года, но они в среднем везде такие), что сравнимо с ценой билета в кинотеатр на двоих (Воронеж, кинотеатр "Синема Парк" в ТРК "Центр Галереи Чижова", фильм "Майор Гром: Чумной доктор", 2021 года:180
/260
рублей в зависимости от сеанса) — при том чтоЯ себе такого человека тоже не могу представить, но все ваши исходные предпосылки совершенно не верные:
24 000
, а2 990
Не знаю где "поход в кинотеатр" стоит "90 рублей" — в Воронеже в самом дешёвом кинотеатре билеты стартуют от
140
, при средней цене в200
-250
, что для одного человека, конечно, дешевле покупки фильма онлайн, но при походе семьёй/компанией — уже дороже.При том что кинотеатр дешев по стандартной причине — он внутри тоже не слишком блещет крутостью, в том числе оборудования.
ponkratv
В России в целом мало кто готов платить за фильмы)
1) Вроде бы у большинства на мобильных устройствах оплатам через in-app, привязывать не надо
2) Тут манипуляция) в Спб поход в нормальный кинотеатр вечером — 200-400р с человека. А покупка фильма обычно 100-300, больше 400 это уже редкие исключения. Причем со временем фильм из отдельной продажи уходит в подписку.
3) Подписка 400р в месяц в среднем по рынку? Какие 2000? Если смотреть что-то два раза в год то можно покупать эти фильмы отдельно, подписка и не нужна. 24000 высосанная из пальца сумма, надо прям постараться, чтобы столько потратить и посмотреть)
Я не из ИВИ, если что) В целом в отрасли ситуация такая, что требования по монетизации диктуются студиями-правообладателями, а не сервисами. Конечно, любой сервис хочет предоставить максимальный объем контента за минимальные деньги, тем самым в разы увеличив аудиторию, но такого никогда не случится, правообладателя всегда пытается выжать максимум из каждого своего фильма.
gecube
Я бы добавил, что основная проблема в том, что новинки обычно все еще сначала появляются в кинотеатрах. И только спустя долгое время появляются на стриминговых платформах вроде ivi/okko/кинопоиск/wink (от Ростелека) и т.д. Т.е. я готов заплатить ivi стоимость похода в кинотеатр на несколько персон за просмотр "новинки", лишь бы не тащить свою попку в кинотеатр, но нет — у меня такой возможности нет. Надеюсь, что ситуация поменяется.
valery1707 что думаете?
По финансовым раскладам я с вами обоими согласен. Подписка не такая уж дорогая, но тут начинается другая проблема — у каждого из онлайн-кинотеатров достаточно бедный набор фильмов. И приходится одно кинцо смотреть в appleTV, второе — на Кинопоиске, третье — на ivi. А подписок тупо не напасешься на всех :-) И это будет круглая сумма.
yar3333
Мой опыт — нередко микросервисы пользуют там, что они совершенно не нужны. В результате перехода к микросервисам, команды получают кучу накладных расходов на работу с несколькими репозиториями кода, с развёртыванием, зоопарком технологий и подходов к разработке. И главное — сильно усложнённый рефакторинг проекта в целом. На мой взгляд, чтобы отказываться от монолита должна быть очень серьёзная причина.
greenxxl
Не верьте им, они FireFox под Linux забанили. :)
upagge
Что значит забанили?
greenxxl
Это означает, что когда нажимаешь воспроизведение выводят:
«Просмотр недоступен в этом браузере» и предлагают открыть это в хроме.
В переписке саппорт сказал, что якобы правообладетили запретили.
grey-fox
Тоже интересно, что значит «забанили»?
Сам часто смотрю ivi на ubuntu в firefox и просто обожаю функционал «картинка в картинке».
Правда нужен drm плагин: support.mozilla.org/ru/kb/smotrite-drm.
Но требование к drm — это, к сожалению, требование правообладателей. И с этим просто приходится мириться.
greenxxl
Включено по дефолту. Однако: «Просмотр недоступен в этом браузере»