Табота Олег @nProfessor
Пользователь
Information
- Rating
- 1,141-st
- Location
- Москва, Москва и Московская обл., Россия
- Date of birth
- Registered
- Activity
Specialization
Backend Developer, Fullstack Developer
Lead
From 10,000 $
Symfony
PHP
High-loaded systems
OOP
Database
SQL
Возможно действительно многие проекты так и не доходят до стадии полного отказа от монолита. Что бы этого не произошло у нас, мы принимаем ряд мер.
1) Устраиваем активности типа "Новогодняя чистка", когда выделяется неделя-две для всех желающий разработчиков поудалять код в монолите. Естественно с призами. Вот в этом декабре такая прошла, в рамках которой мы удалили больше 300к строк кода из монолита.
2) Мы никогда не шарим базу монолита. Мы убеждены что шарить базу - это супер рискованное решение, которое приводит к трудно диагностируемым проблемам.
3) Как критерии для выноса, мы используем количество вносимых в какой-то участок кода или бизнес логики изменений, сложность выноса этой логики, нагрузка которая приходится на этот участок, количество инцидентов связанных с этим кодом.
Скорее всего монолит у нас останется в каком-то виде на долго, но там точно не будет критичной функциональности. Скорее всего это будет черная коробочка которая по сути ни на что не влияет. Просто потому что избавление от нее по соотношению цена-качество не в пользу выпила.
А так у нас уже больше 180 атомарных микро сервисов
По этому поводу очень хорошо рассказал CTO Яндекс.Еды https://youtu.be/F6NN8pW2Wac?si=UdUsWAlRycUHPabw
Да, действительно у нас есть кейсы где так происходит(Я вроде в видео версии рассказывал, а тут не упомянул).
Например мы выносили сущность "Бренд ресторана", и эта сущность пронизывает огромное количество частей монолита.
Мы создали сервис, CRUD операции перевели на него, и данные оттуда "реплицируем" в старую табличку. При этом мы весь основной функционал в монолите переключили на получение данных из этого сервиса, оставив старую табличку только для самых не критичных вещей. Потому что стоимость переключения всего равнялась примерно 6 человекомесяцам работы, а профита было бы не очень много.
Все новые сервисы брали данные из сервиса брендов, и если нужно было расширить функциональность, мы принципиально не расширяли старую табличку. Она помечена как деприкейтед. Если в монолите кому то требуется новая функциональность сервиса брендов, он переходит на сервис как на первоисточник.
У нас таких кейсов не много, и если они создают проблемы мы в первую очередь стараемся от такого уйти. Это состояние считается не законченной задачей.
У нас вся схема АПИ хранится в YAML файлах, и по ним генерируются клиенты. Есть чекеры которые запрещают тебе ломать обратную совместимость. Так что любые изменения у нас прямо и обратно совместимы.
Но вопрос с тестами для нас все равно актуальный. Иногда приходится переписывать сотни тестов что бы уйти от БД в пользу использования мока ответа сервиса. Иногда тесты просто удаляем, потому что они начинают проверять просто мок.
Здесь у нас 2 момента:
1) Мы просто начали писать больше интеграционных тестов
2) Делаем новые инструменты для более удобного написания и запуска этих интеграционных тестов. То есть, можно написать тест так, что бы при релизе одного сервиса прогонялись тесты всех связанных сервисов с реальными походами между ними.
Это не какой-то законченный проект, это больше направление движения. У нас все команды стараются делать новую функциональность в новых сервисах, и для этого им приходится вытаскивать часть функциональности из монолита, потому что мы специально создали такие условия, что бы в монолит большая сложная функциональность больше не добавлялась.
Так постепенно мы его и распиливаем.
Если отвечать на вопрос, то можно ответить так, в большинстве случаев хватает 2-3х разработчиков что бы за 1-2 месяца вынести значимую часть кода в сервис. Но иногда это бывают и дни, иногда месяца, все зависит от многих факторов.
Мы стараемся в планирование новых фич закладывать сроки на реализации их в новом сервисе. Если бизнес ни в какую, нужно срочно и все, думаем над компромиссами, например в рамках задачи сделать функцию в монолите, но часть функциональность все таки написать в сервисе, что бы в следующий раз менять уже там.
И очень помогает подход, который я описал в статье в разделе "Вынос эндпоинта получения оффера". То есть мы просто поднимаем сервис прокси, и там добавляй функциональность которая нужна. Да, не всегда это подходит, но в большенстве случаев работает.
Спасибо за хорошие вопросы!
Ответ на первый. Мы выносим сущностями. Это значит, что, скорее всего, уедет или вся табличка, или ее часть, или даже несколько. Чтобы посчитать нагрузку, мы начали собирать метрики запросов. В Симфони есть листнеры, и мы подписались на события запроса в базу данных. Там ловим SQL-запрос, парсим его и шлем в метрики в особом формате. После чего в метриках мы можем увидеть, сколько было запросов, к какой табличке, через какие эндпоинты, скрипты или консьюмеры. Если, например, при инсерте будет добавлено 100 строк, то мы увидим только одно обращение, но это дает нам примерное понимание профиля нагрузки. Для более тонкого понимания можно посмотреть метрики MYSQL или просто посчитать количество добавленных данных.
То есть мы смотрим на RPS ручки, которую выносим, и/или на RPS табличек, которые выносим. Смотрим на сами таблички: для чего они, что делают, какой у них профиль нагрузки. Может быть, это табличка с логами, где только INSERT, или табличка со статической информацией, где только SELECT.
По этим данным чаще всего становится понятно, что нужно делать, но момент докручивания никто не отменял. Действительно, при запуске какой-то фичи нам может понадобиться, например, увеличить флейвор базы сервиса. Да, такое бывало, но в основном мы попадаем.
Ответ на второй. На него сложнее ответить, потому что универсального ответа нет. Каждый случай индивидуальный. Мы пытаемся мыслить адекватно, прогнозируя, к чему приведет то или иное изменение. Где-то продумываем фолбеки (деградацию), где-то переосмысливаем сущность и формат ее хранения и переписываем на другое поведение, где-то получается заюзать кеш, как, например, с сервисом стран.
Потому что плагин создан для проекта написанного на PHP7 где не было таких возможностей.
Если сразу проставлять типы, наверно проблем описанных в статье у вас не будет. Но если у вас легаси проект с сотнями подобных кусков кода, то плагин вам поможет
Ни в коем случае никого не критикую. Если проект жив столько лет, значит на разных этапах разработки все делали какие-то правильные вещи, что позволило выжить среди конкуренции. Это касается как разработчиков так и менеджмента.
Подскажите, какой конкретно текст вызвал такое ощущение? Возможно стоит его подкорректировать.
Могу только предположить что вас смутила эта строчка
или эта
Но это не про разработчиков, это про объективную реальность
Легаси - означает что код старый и уже нет овнеров кода. Любой код устаревает и становится легаси, и разработчики тут не причем.
Разработчиками разного уровня - это включает как разработчиков стартапа, так и разработчиков уже внутри яндекс еды, и это тоже просто факт без какого-то негативного оттенка.
PHPunit + Xdebug - подсчет покрытия кода тестами. В отчете есть данные по количеству строк кода, классов, методов и функций.
При том подсчете мы исключили все что смогли.
Ради интереса поставил плагин. Но возникает несколько вопросов, какой код вы анализировали?
В приведенном в статье примере, мы анализировали только файлы с бизнес логикой, исключая файлы тестов и Dto файлы, всякие клиенты к сервисам и другие не важные штуки.
Вот если ничего не исключать
Если исключить все Юнит тесты
Dto и другие вещи которые не нужно отслеживать, я уже исключать не буду.
А что исключили вы? Интересно что бы сравнить.
Как я писал в статье, подсчет покрытия тестами мы провели уже постфактум. Признаю, было ошибкой не сделать этого перед началом работы. Из-за этого мы потратили около двух недель на отлов остальных ошибок в тестинге. А это, в свою очередь, означало еще 2 недели фриза на релизы и 2 недели дополнительной работы команде тестировщиков.
Исходя из полученного опыта могу сказать, что поэтапный переход был бы дольше, но каждый этап — намного проще.
Возможно, мы бы после первого этапа сделали какие-то выводы и скорректоровали свои планы для следующих этапов.
Основную проблему создали не изменения в фреймворке или PHP, а изменения в сторонних библиотеках, которые не поддерживались или полностью меняли интерфейс. Не исключено, что у некоторых из них интерфейс менялся несколько раз, поэтому пришлось бы делать одну и ту же работу по кругу.
В следующий раз, скорее всего, пойду по поэтапному плану 🙂
Несомненно, если бы с самого начала было больше рук, решили все быстрее.
Цена на поддержку тестов кажется оправданной для такого большого проекта.
Так посчитала автоматика при подсчете покрытия тестами. Это без учета наших бандлов, только монолит.
Потенциальные. Конечно, вероятность того, что появится какая-то уязвимость, которую можно было бы эксплуатировать у нас, минимальна. Но все равно это потенциальные риски, которые нужно закрыть
Возможно это и так, но почему то большенство ее воспринимают так «Если я не пишу комментарии значит мой код хороший»
Каждый школьник считает себя гуру и поэтому не пишет комментарии, а потом за ними фиг разберёшься.
Так что гуру пишите пожалуйста комменты, что бы школьники повторяли за вами )
А ещё комментарии позволяют:
1) не разбираться в коде, даже если он красивый и легкий, а по одному предложению понять для чего этот метод нужен и просто его использовать
2) понять что должен делать метод, потому что метод может работать не правильно(вспомним школьников). А как по коду понять что бизнес логика не правильная?
Наличие сторонних плагинов, встроенный клиент работы с БД и вообще много крутых фитч.
Но одна фитча которой пользуюсь не часто, но каждый раз когда пользуюсь очень благодарен за нее, это "Local History" ни один раз меня выручала )
По поводу кода, хорошо, немного позже выложу сюда код.
Можно взять гугловский ID пользователя, и посылать от его имени различные эвенты пост запросом с сервера. И гугл будет эти данные учитывать как реальная сессия этого человека.
Я так отслеживал в гугл аналитике информацию по заказам. В отложенном режиме посылал событие о смене статусов заказов, и потом в аналитике мог посмотреть статистику в срезе статусов.
Смысл в том, что бы не смотреть на клавиатуру когда не помнишь где находится нужная клавиша.
Они в колледже рисовали клавиатуру на картонках и ставили рядом с монитором, а кнопки самой клавиатуры заклеивали.
Отличие от тренажеров в том, что можно практиковать на работе не сильно вредя продуктивности, то есть работать и обучаться одновременно, а не тратить N свободного времени на практику на тренажере.
Но данных, для каких-либо серьезных выводов, по моему маловато.