Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

«Тактика распила PHP-монолита» — Лакосников Пав...

Badoo Tech
February 15, 2020

«Тактика распила PHP-монолита» — Лакосников Павел, Авито

«Последние три года мы в Авито активно разделяем PHP-монолит на микросервисы. В процессе нашли много устаревших продуктовых и технологических решений — неактуальные хранилища, слишком «толстые» ответы, неиспользуемые методы API.

В докладе расскажу, как мы избавлялись от легаси:‌ выносили словари и другую статику, выделяли интерфейсы, упрощали иерархию наследования и совершенствовали покрытие тестами. А ещё — как улучшаем то, что пока осталось в монолите».

Badoo Tech

February 15, 2020
Tweet

More Decks by Badoo Tech

Other Decks in Programming

Transcript

  1. !4 Как выглядел монолит 3 года назад: 2.6к файлов и

    200к строк PHP 1.5к html файлов 1к+ файлов js, lua, python, perl ServiceRegistry + Global как основные способ работы с базой Разветвлённая многоуровневая система наследования
  2. !5 Как выглядел монолит 3 года назад: 2.6к файлов и

    200к строк PHP 1.5к html файлов 1к+ файлов js, lua, python, perl ServiceRegistry + Global как основные способ работы с базой Разветвлённая многоуровневая система наследования
  3. !14 Не позволял быть гибкими Не позволял командам быстро внедрять

    изменения, не вызывая «эффект лавины» Не позволял экспериментировать
  4. !15 Не позволял быть гибкими Не позволял командам быстро внедрять

    изменения, не вызывая «эффект лавины» Не позволял экспериментировать Гигантскими тяжелыми моделями
  5. !24 Вендоризация 1. Собираем код в отдельный пакет 2. Прогоняем

    статический анализатор 3. Пишем тесты 4. Подключаем к монолиту как внешнюю библиотеку
  6. !25 Зачем? 1. Контроль за изменениями 2. Изоляция всех внешних

    зависимостей 3. Одинаковое поведение у всех потребителей
  7. !33 Зачем? Это корневые зависимости, нужные не только в монолите,

    но и в большинстве сервисов Фиксация констант, интерфейсов
  8. !34 Зачем? Это корневые зависимости, нужные не только в монолите,

    но и в большинстве сервисов Фиксация констант, интерфейсов Контроль за их изменением
  9. !35 Зачем? Это корневые зависимости, нужные не только в монолите,

    но и в большинстве сервисов Фиксация констант, интерфейсов Контроль за их изменением Доступность для любых сервисов
  10. !38 Как именно? Вендоризовали интерфейсы всех словарных сущностей, все константы

    Отделили базу данных, хранящих словарные сущности Сделали микросервис, способный отдавать словарные данные в куче форматов
  11. !39 Как именно? Вендоризовали интерфейсы всех словарных сущностей, все константы

    Отделили базу данных, хранящих словарные сущности Сделали микросервис, способный отдавать словарные данные в куче форматов Доработали сборку монолита, добавив этап сборки словарей
  12. !40

  13. !45 На вход в метод отрисовки объявления $expandedItem = [

    'id' => $itemId, 'category' => [ 'id' => $itemCategory->id, 'name' => $itemCategory->name ] ];
  14. !55 Что именно? Многие сущности представлялись в коде как большие

    массивы с данными Эти массивы передаются из метода в метод, по цепочке
  15. !56 Что именно? Многие сущности представлялись в коде как большие

    массивы с данными Эти массивы передаются из метода в метод, по цепочке В процессе дополняются, расширяются и декорируют
  16. !59 Зачем? Больше типизации => меньше ошибок Понимание, какие поля

    и где используются Удаление неиспользуемых или устаревших полей
  17. !73 Проблемы Огромная холостая нагрузка на сеть Низкая надежность Сложность

    тестирования Невозможность создать микросервис, отвечающий только за часть свойств этой модели
  18. !76 Как именно? Выделили десятки интерфейсов из большой модели Разбили

    одну большую модель на множество маленьких Сделали отдельные фабрики для каждой из них
  19. !79 Что именно? Вызовы хранимок на получение данных из самых

    разных места монолита Сохранение моделей в отличном от создания месте
  20. !80 Что именно? Вызовы хранимок на получение данных из самых

    разных места монолита Сохранение моделей в отличном от создания месте Разные алиасы у полей, и способы получения данных
  21. !85 Проблемы Большая глубина наследования на классах, занимающихся работой с

    моделью Большое количество входных похожих точек, вызывающих работу с моделью
  22. !86 Проблемы Большая глубина наследования на классах занимающихся работой с

    моделью Большое количество входных похожих точек, вызывающих работу с моделью Неконсистентность вызовов
  23. !89 Как именно? Переход на dataMapper модель Подстройка публичного интерфейса

    под нужды конкретных потребителей Инкапсулюяция всей логики базы связанной с сущностью в одном месте
  24. !92 Что именно? Большой хвост из старых версий мобильных приложений

    Большое десктоп-апи, которые не чистили раньше
  25. !94 Проблемы Старые методы ожидали очень большие модели данных, избыточные

    для их работы Часть запросов использовались исключительно ботами
  26. !95 Проблемы Старые методы ожидали очень большие модели данных, избыточные

    для их работы Часть запросов использовались исключительно ботами Часть запросов были «мертвыми»
  27. !96 Проблемы Старые методы ожидали очень большие модели данных, избыточные

    для их работы Часть запросов использовались исключительно ботами Часть запросов были «мертвыми» Осложняли рефакторинг
  28. !98

  29. !101 Как именно? Сделали метрики по использованию API Сверились c

    ними Отказались от поддержки версий приложений с минорным трафиком
  30. !106 Проблемы Перетирали ключи в разных потребителях Автоматически конвертит классы

    через php_serialize (круто, когда класс переименовали а кэш нет)
  31. !107 Проблемы Перетирали ключи в разных потребителях Автоматически конвертит классы

    через php_serialize (круто, когда класс переименовали а кэш нет) Не перистентен
  32. !108 Проблемы Перетирали ключи в разных потребителях Автоматически конвертит классы

    через php_serialize (круто, когда класс переименовали а кэш нет) Не перистентен Общие политики вытеснения для всех
  33. !110 Как именно? Плавно заменили несколько мемкешей на большую пачку

    персистентных Redis Выделили отдельные обертки под отдельные Redis
  34. !111 Как именно? Плавно заменили несколько мемкешей на большую пачку

    персистентных Redis Выделили отдельные обертки под отдельные Redis Разделили потребителей каждый по своему Redis’у
  35. !120 implode (string $glue , array $pieces ) Раньше порядок

    аргументов не имел значения Было implode (string $glue, array $pieces): string implode (array $pieces, string $glue): string Стало implode (string $glue, array $pieces): string
  36. !122 Добавили литеры Php-stan Php-cs Route-checker Сrontab-checker Проверка схемы ответов

    API Линтер на examples ответов API Валидация контраков
  37. !123 Добавили литеры Php-stan Php-cs Route-checker Сrontab-checker Проверка схемы ответов

    API Линтер на examples ответов API Валидация контраков