Pull to refresh
41
2
Табота Олег @nProfessor

Пользователь

Send message

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Если сразу проставлять типы, наверно проблем описанных в статье у вас не будет. Но если у вас легаси проект с сотнями подобных кусков кода, то плагин вам поможет

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

Подскажите, какой конкретно текст вызвал такое ощущение? Возможно стоит его подкорректировать.

Могу только предположить что вас смутила эта строчка

Это легаси-монолит, доставшийся Яндекс Еде после объединения со стартапом Foodfox

или эта

Монолит написан на PHP 7.2 разработчиками разного уровня и в разное время. Мы подумали, что так больше нельзя, и решили навести порядок.

Но это не про разработчиков, это про объективную реальность
Легаси - означает что код старый и уже нет овнеров кода. Любой код устаревает и становится легаси, и разработчики тут не причем.
Разработчиками разного уровня - это включает как разработчиков стартапа, так и разработчиков уже внутри яндекс еды, и это тоже просто факт без какого-то негативного оттенка.

чем конкретно вы до этого считали? 

PHPunit + Xdebug - подсчет покрытия кода тестами. В отчете есть данные по количеству строк кода, классов, методов и функций.

При том подсчете мы исключили все что смогли.

Ради интереса поставил плагин. Но возникает несколько вопросов, какой код вы анализировали?
В приведенном в статье примере, мы анализировали только файлы с бизнес логикой, исключая файлы тестов и Dto файлы, всякие клиенты к сервисам и другие не важные штуки.

Вот если ничего не исключать

Если исключить все Юнит тесты

Dto и другие вещи которые не нужно отслеживать, я уже исключать не буду.
А что исключили вы? Интересно что бы сравнить.

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

Исходя из полученного опыта могу сказать, что поэтапный переход был бы дольше, но каждый этап — намного проще. 

Возможно, мы бы после первого этапа сделали какие-то выводы и скорректоровали свои планы для следующих этапов.

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

В следующий раз, скорее всего, пойду по поэтапному плану 🙂

Если не экономить на кадрах, то такая задача решается быстрее.

Несомненно, если бы с самого начала было больше рук, решили все быстрее. 

Поддерживать тесты - дорого, симфони тоже кстати дорого.

Цена на поддержку тестов кажется оправданной для такого большого проекта.

По цифрам вообще фантастика какая-то, 500000 строчек чего, бизнес-логики?

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

Какие именно уязвимости php 7.2 вас не устроили?

Потенциальные. Конечно, вероятность того, что появится какая-то уязвимость, которую можно было бы эксплуатировать у нас, минимальна. Но все равно это потенциальные риски, которые нужно закрыть

Всегда не любил эту фразу «Хороший код не нуждается в комментариях»

Возможно это и так, но почему то большенство ее воспринимают так «Если я не пишу комментарии значит мой код хороший»

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

А ещё комментарии позволяют:
1) не разбираться в коде, даже если он красивый и легкий, а по одному предложению понять для чего этот метод нужен и просто его использовать
2) понять что должен делать метод, потому что метод может работать не правильно(вспомним школьников). А как по коду понять что бизнес логика не правильная?
Можно глянуть в Productivity Guide самое используемое )
image

Наличие сторонних плагинов, встроенный клиент работы с БД и вообще много крутых фитч.

Но одна фитча которой пользуюсь не часто, но каждый раз когда пользуюсь очень благодарен за нее, это "Local History" ни один раз меня выручала )
  1. Пробовал все. RandomForestRegressor сильно переобучался на столь маленьком количестве данных. Сначала использовал 500 деревьев, но потом, опытным путем определил что 80 давали лучший результат. Тем не менее они проигрывали ExtraTreeRegressor по данным кросс-валидации. К предсказаниям по зашумленным данным прибавлялась модель деревьев, для остальных среднее из 3х линейных моделей и полинома;
  2. Пробовал все линейные модели которые были в библиотеке scikit-learn, в разных сочетаниях и комбинациях; Тут особо нет смысла разделять если используем линейную модель. Если например TheilSen и RANSAC будут хороши для зашумленных данных, то для линейных они точно будут хорошими. Поэтому обращал внимание только на вторую группу(зашумленные данные);
  3. Для первой группы среднее от 4 моделй, для второй, тоже среднее, но с одним условием, если ExtraTreeRegressor предсказывал меньшее время чем среднее этих 4х моделей, то бралось среднее 5 моделей(где 5я это ExtraTreeRegressor), если больше, то так и оставалось среднее 4х моделей(я об этом выше писал).
  4. Не совсем понятен вопрос. Третьим параметром в LinearRegression можно передать вес. Вес считался по формуле 1/pow(Y,3.1);

По поводу кода, хорошо, немного позже выложу сюда код.
Все можно накрутить.
Можно взять гугловский ID пользователя, и посылать от его имени различные эвенты пост запросом с сервера. И гугл будет эти данные учитывать как реальная сессия этого человека.
Я так отслеживал в гугл аналитике информацию по заказам. В отложенном режиме посылал событие о смене статусов заказов, и потом в аналитике мог посмотреть статистику в срезе статусов.
Идея программы взята из какого то курса, какого то колледжа.
Смысл в том, что бы не смотреть на клавиатуру когда не помнишь где находится нужная клавиша.
Они в колледже рисовали клавиатуру на картонках и ставили рядом с монитором, а кнопки самой клавиатуры заклеивали.

Отличие от тренажеров в том, что можно практиковать на работе не сильно вредя продуктивности, то есть работать и обучаться одновременно, а не тратить N свободного времени на практику на тренажере.
Спасибо, интересная информация.
Но данных, для каких-либо серьезных выводов, по моему маловато.
1

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