Pull to refresh

Comments 36

Почините, пожалуйста, баг с пуш уведомлениями. Стреляет с сентября прошлого года, раздражает. Суппорт по почте отвечает отписками.

Постоянно прилетают пуши с рекламой «ближайших» общепитов, при том что я нахожусь в стране, где сервисы еды/такси не работают в принципе. Геолокация разрешена. При попытке перехода по уведомлению получаю сообщение что Яндекса тут нет. Совсем отключать пуши не хочу, потому что моей картой через семейный аккаунт пользуются родственники.

Было интересно почитать. Немного подумав - я-бы сказал, что мочь локально установить сервис на нотбуке например - это самое важное из всех здесь перечисленных причин. Для меня. Все остальные - какие-то имхо искусственные. Например - Зона ответственности

При рефакторинге всё равно ведь надо будет эту ответственность за кем-либо закреплять. Так почему только при распиле, почему не заранее?

Но, всё равно - полезные мысли. Есть, что взять на заметку.

Где-то умную мысль прочитал, что при долгой разработке структура информационных систем начинает повторять иерархию отделов. Соглашусь! Это к слову об "зоне ответственности".

Так и есть. У нас в компании это четко прослеживается. Так что если я хочу выделить часть логики отдельно, то самый простой способ - это выделить людей в отдельный отдел :)

Развернуть монолит в Docker на маке локально стало проблематично
Чего только не придумают, лишь бы с маков на линукс не пересаживаться.

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

предварительно рассчитав предполагаемый RPS

А как вы рассчитывали, сколько ресурсов необходимо выделить на новый сервис? Вы знаете, какая нагрузка приходится на эту часть монолита, или вы сначала выделяете какой-то базовый лимит для 1% пользователей, потом увеличиваете их число до 10% от общего трафика, смотрите как себя чувствует сервис, и если что - подкручиваете новый лимит?

И второй вопрос: а как вы рассчитывали/прогнозировали время ответа после переезда на новый сервис? Вот был раньше джоин в несколько табличек в монолите, это занимает N миллисекунд на запрос, и мы знаем, что при высокой нагрузке этот запрос не просядет, а теперь надо пойти в несколько новых, как быть в данном случае?

Спасибо за хорошие вопросы!

Ответ на первый. Мы выносим сущностями. Это значит, что, скорее всего, уедет или вся табличка, или ее часть, или даже несколько. Чтобы посчитать нагрузку, мы начали собирать метрики запросов. В Симфони есть листнеры, и мы подписались на события запроса в базу данных. Там ловим SQL-запрос, парсим его и шлем в метрики в особом формате. После чего в метриках мы можем увидеть, сколько было запросов, к какой табличке, через какие эндпоинты, скрипты или консьюмеры. Если, например, при инсерте будет добавлено 100 строк, то мы увидим только одно обращение, но это дает нам примерное понимание профиля нагрузки. Для более тонкого понимания можно посмотреть метрики MYSQL или просто посчитать количество добавленных данных.

То есть мы смотрим на RPS ручки, которую выносим, и/или на RPS табличек, которые выносим. Смотрим на сами таблички: для чего они, что делают, какой у них профиль нагрузки. Может быть, это табличка с логами, где только INSERT, или табличка со статической информацией, где только SELECT.

По этим данным чаще всего становится понятно, что нужно делать, но момент докручивания никто не отменял. Действительно, при запуске какой-то фичи нам может понадобиться, например, увеличить флейвор базы сервиса. Да, такое бывало, но в основном мы попадаем.

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

Спасибо большое за развернутый ответ!

А как вы решали проблему дублирования функционала в сервисах при распиле? Вынос части функционала в новый сервис явно занимает не пару дней, как балансировать между переписыванием и новыми большими фичами, которые хочет бизнес? Делать их параллельно на php и C++ в монолите и микросервисе, или договаривались с бизнесом, что пока идет распил, вот конкретно эти фичи ставим на паузу?

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

И очень помогает подход, который я описал в статье в разделе "Вынос эндпоинта получения оффера". То есть мы просто поднимаем сервис прокси, и там добавляй функциональность которая нужна. Да, не всегда это подходит, но в большенстве случаев работает.

А как вы теперь справляетесь с тестированием? Вот был монолит, большая связанность, тесты и моки (если есть) покрывают различные сервисы/базы/итд, все в одном месте и максимально переиспользуется (в теории). В пайплайне юнит и интеграционные тесты позволяют отловить какие-либо недокументированные изменения. Изменили табличку, упал юнит-тест, изменили DTO - упал интеграционный.

Теперь вместо таблички с списком стран - сервис стран, который нужно мокать, описывать его контракты у себя и т.д. Как теперь прогнать тесты, когда зависимость стала от внешнего сервиса, а не внутренней реализации. Например, сервис стран поменял контракт, но моки у вас остались старые, пайплайн прошел, а вот у пользователя на проде ошибки. Как вы такое отлавливаете, если не секрет?)

У нас вся схема АПИ хранится в YAML файлах, и по ним генерируются клиенты. Есть чекеры которые запрещают тебе ломать обратную совместимость. Так что любые изменения у нас прямо и обратно совместимы.

Но вопрос с тестами для нас все равно актуальный. Иногда приходится переписывать сотни тестов что бы уйти от БД в пользу использования мока ответа сервиса. Иногда тесты просто удаляем, потому что они начинают проверять просто мок.

Здесь у нас 2 момента:
1) Мы просто начали писать больше интеграционных тестов
2) Делаем новые инструменты для более удобного написания и запуска этих интеграционных тестов. То есть, можно написать тест так, что бы при релизе одного сервиса прогонялись тесты всех связанных сервисов с реальными походами между ними.

Я однажды хотел попробовать заказать в доставке Яндекса
Но увидел как курьер Яндекса бежал на остановку и навернулся с этим рюкзаком...
Передумал...

По-человечески жалко курьера

Сколько разработчиков при этом было в команде проекта, если не секрет?

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

Так постепенно мы его и распиливаем.

Если отвечать на вопрос, то можно ответить так, в большинстве случаев хватает 2-3х разработчиков что бы за 1-2 месяца вынести значимую часть кода в сервис. Но иногда это бывают и дни, иногда месяца, все зависит от многих факторов.

Интересно там у вас, в Яндекс.Еда!

Про микросервисную архитектуру и переход на неё написаны сотни статей, однако почти все они больше теоретические и описывают ситуацию лишь верхнеуровнево.

Вот так претенциозно и с обесцениванием других статей всё начиналось. Признаться, я ожидал оригинальных историй и суровой практики. А контент - из довольно очевидных вещей, в особенности "итоговые советы" - набор очевидностей, которые справедливы в любой ситуации, не только в распиле монолита. Совет "Используйте как можно меньше костылей" - серьёзно? Хорошо делайте, плохо не делайте. Ну, такое.

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

Распил монолита == распил бюджета.

Сетования на дефицит PHP(!) разработчиков так прекрасно сочетаются с многоэтапными алгособесами, да!

А переписывание на C++, который совсем для иного класса задач предназначен, это прям вишенка какая-то...

Тоже подумал, что чем-то не тем занимаются...

Бюджет - это дело бизнеса. Хотят пилить - их право.

Другое дело, что редко когда распил монолита дает в итоге микросервисы.

Обычно он заканчивается монолитом с частично мертвым кодом в окружении сервисов. Как работает монолит уже никто не знает. Сервисы оказываются не атомарны и зачастую используют общиую базу.

В общем, закономерный конец распила монолита - распределенный монолит.

Возможно действительно многие проекты так и не доходят до стадии полного отказа от монолита. Что бы этого не произошло у нас, мы принимаем ряд мер.

1) Устраиваем активности типа "Новогодняя чистка", когда выделяется неделя-две для всех желающий разработчиков поудалять код в монолите. Естественно с призами. Вот в этом декабре такая прошла, в рамках которой мы удалили больше 300к строк кода из монолита.

2) Мы никогда не шарим базу монолита. Мы убеждены что шарить базу - это супер рискованное решение, которое приводит к трудно диагностируемым проблемам.

3) Как критерии для выноса, мы используем количество вносимых в какой-то участок кода или бизнес логики изменений, сложность выноса этой логики, нагрузка которая приходится на этот участок, количество инцидентов связанных с этим кодом.

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

Уйдя от монолита, вы всё равно придёте к тому же "монолиту". Микромонолиты, которые делают 10 дел. Конгломераты микросервисов, которые непойми как зачем и почему связаны между собой. Ничего не задокоментировано и непонятно как работает. Кто это делал и у кого это в голове уже давно уволились. Все боятся трогать этого франкенштейна. Безопаснее приклеить гавном ещё одну палку, чем что-то системно рефакторить.

Проблемы монолитов не потому что они монолиты. Проблемы из-за общего безкультурия разработки. И перейдя к микросервисной архитектуре эта чума благополучно перебирается и туда. Добавляя ещё и чисто микросервисных проблем.

Кмк не прозвучало самое интересное - вот вы перенесли сущность в МС из монолита. Но чтобы все "стыкующиеся" бизнес-процессы, которые еще не вынесены, не сломались - мы начинаем данные зеркалить в монолит. Также поступает и команда-сосед. И кмк есть серьезный риск что через 2-3 года ситуация может сложиться такая - есть куча МС, но все еще есть монолит со всеми ключевыми сущностями. Cost of change не изменился или вырос, ошибки за счет неконсистентности данных выросли, ТСО тоже вырос хотя бы по железу. Вопрос - как вы работаете с такого рода рисками "сцепленности" процессов в монолите?

Да, действительно у нас есть кейсы где так происходит(Я вроде в видео версии рассказывал, а тут не упомянул).
Например мы выносили сущность "Бренд ресторана", и эта сущность пронизывает огромное количество частей монолита.
Мы создали сервис, CRUD операции перевели на него, и данные оттуда "реплицируем" в старую табличку. При этом мы весь основной функционал в монолите переключили на получение данных из этого сервиса, оставив старую табличку только для самых не критичных вещей. Потому что стоимость переключения всего равнялась примерно 6 человекомесяцам работы, а профита было бы не очень много.

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

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

спасибо, а с заказом таких проблем случайно не было у вас? )

Из всей статьи больше всего удивило увидеть код на PHP. Яндекс всем своем существованием проявлял свою неприязнь и игнорирование самого популярного языка. Зато Perl почему-то везде используется.

Тут важно популярным среди кого. Среди ученых и DS — python. Олимпиадников и алгоритмитистов — си/плюсы. Среди интерпрайза — джава.

Популярность у эникеев и скрипт-кидди не делает язык сразу хорошим, собственно его и автор не считает хорошим. Адекватный инженер выбирает из тех тулов, что подходят для задачи. Вон для стартапа когда нет скилловых крутышей — пойдет и спагетти-монолит код «лишь бы работало», всё согласно парадигме “fake it until u make it” — нерасширяемый монолит в котором сложно делать изменения это просто не продукт в любой сфере кроме стартапов (где это бывает оправдано разными факторами).

Ой, только давайте без пещерного хейта. Понятно что комментатор выше имел в виду не DS, а бэкенд веба. К чему тут эникеи и скрипт-кидди - и вовсе непонятно. Первые скорее пишут на баше/ps, вторые - на питоне патамушта хайп. Популярность и "хорошесть" - это ортогональные понятия, вы сначала определитесь, с чем именно вы не согласны. Да, у современного пыха осталось несколько сложноустранимых недостатков, но в целом это нормальный язык, на котором пилят те же микросервисы все кому не лень - от какой-нибудь Ламоды до пресловутого Порнхаба. Главное спроси такого обличителя - чем пых хуже? - так он начнет бунить из статьи полуторадесятилетней давности, 70% которой уже неактуально, или вовсе скатится к вкусовщине, "так значок доллара ненавижу, что даже кюшать не могу!"

И, кстати, передергивать тоже не надо: у автора статьи нигде не написано отношение к РНР.

А как обстоят дела с деливери? Его же купил Яндекс, переносите все на одни рельсы или он самостоятельно развивается? Такой же монолит?

А можно tl;dr? Смотреть видео полчаса уже перебор.

Если коротко, то купили бренд, взяли пару вещей, которых не было в Яндексе. По типу приложения для сборщиков заказов. Перевели клиентов в еду и выкинули что осталось от деливери. Команда разбрелась кто куда. А сами сервисы были на Go и PHP. Как понял не захотели с Go работать просто

Как же вы удивитесь, когда все эти хитро выдуманные схемы, а так же возможные новые, можно сделать при помощи Apache Camel.

Судя по вашей диаграмме связности вы не умеете делать database view. Это абстракция как интерфейс. По этому поводу есть концепция database mesh: считается что данные имеют ценность и за них отвечает конкретная команда. Это удобнее чем "джоины разрезать с падением скорости".

Микросервисы помогают уменьшить связность кода но не очень. То что вы передаёте данные по сети никак не поможет в уменьшении связности. Вот разделение один домен - одна база данных поможет. Но микросервисы тут как 5я нога.

Микросервисы помогут скорости CI/CD но не очень. Можно ведь собирать отдельные проекты и поставлять их в виде DLL. Правда, придется гасить весь экземпляр монолита для замены, что при statefull или in memory cache плоховато.

Вам с данными надо разобраться, а потом уже микросервисами заниматься. Они тоже будут но в меньшем масштабе и без боли.

При этом микросервисы замедляют разработку вдвое потому что много дублирования кода, нужны оснастки https://azhidkov.pro/posts/23/07/project-e-results/

Ваши же слова "стоимость переключения [с таблички на микросервис] равнялась примерно 6 человекомесяцам работы"

А, ну да, ну да...

Я не против микросервисов но очень осторожно, для каждого микросервиса рассматривая альтернативу оставить монолит и исправить только БД.

Из другого комментария "Вот так претенциозно и с обесцениванием других статей всё начиналось. Признаться, я ожидал оригинальных историй и суровой практики."

Вот и получается антиреклама и микросервисов и Яндекса.

https://habr.com/ru/companies/vk/articles/720652/

data mesh

прочитал как вы повышали версию ПХП год

да, от такого монолита надо избавляться

у меня проект поменьше в 5 раз и на .Net но переезд на новые мажорные версии .Net 6->8 прошел совершенно безболезненным

Sign up to leave a comment.