Как структурировать репозитории кода: мульти, моно или органические?

1656534015 kak strukturirovat repozitorii koda multi mono ili organicheskie

автор Четан Шарма

BldvbE37nusd26cWWR6cj4LWA5HMBTFqXp7S
Фото Йорена на Unsplash

Новейшая дискуссия в городе заключается в том, стоит ли хранить свои услуги в одном хранилище или в нескольких небольших хранилищах.

Идея нескольких небольших хранилищ состоит в том, что код для каждого микросервиса вашего приложения хранится в отдельном репозитории. С помощью моно-репо вы храните весь код в одном репозитории и разворачиваете код как микросервис.

Итак, что следует использовать? Слишком жесткое отношение к любому подходу – без учета цели и использования каждого подхода – может привести к негативным результатам в долгосрочной перспективе. Если вы знаете, когда использовать каждый, это может повысить вашу производительность и улучшить ваш проект.

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

Общая рекомендация – иметь независимое хранилище для каждой программы/сервиса. Но почему? Потому что, имея один репозиторий для каждого микросервиса, мы получаем:

  • Свобода писать код по-разному и независимо от всех остальных сервисов.
  • Скорость во внесении изменений в код при исправлении ошибок, обновлении, тестировании и развертывании. Поскольку изменения нужно тестировать только в одном репозитории, развертывание кода происходит быстрее и надежнее.
  • Разделение кода как независимые блоки, что предотвращает утечку ошибок и узкие места производительности между службами.
  • Четкое право собственности каждого репозитория и службы, что особенно полезно для больших команд.

Но почему возникла потребность в монорепо?

Очевидно, что подход с несколькими РЕПО имеет свои преимущества. Но это также имеет свои проблемы, особенно в проектах с большим количеством микросервисов, использующих одинаковые рамки, язык, стеки и т.д.

Некоторые из этих проблем:

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

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

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

  • Обслуживание и обновление легко и быстро.
  • Нахождение кода для отладки или изменения гораздо более структурировано.
  • Легче привлекать новых товарищей по команде.

Как мы решаем, какой тип хранилища использовать

Нижеследующие рассуждения помогли нам решить, когда использовать моно-репо или много-репо.

1. Подумайте о коде, который послужит основой сервиса.

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

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

Например, Collect – наш основной инструмент сбора данных – имеет несколько микросервисов, построенных на идентичной основе. Эти сервисы построены на Node.js, Express и Parse Server. Они имеют много библиотек, таких как Winston, Mongoose и другие посторонние интеграции. Ранее, когда каждый из этих сервисов имел свой репозиторий, обновление или исправление ошибки в любом из этих общих модулей означало обновление и тестирование каждого репозитория отдельно. Это было медленно и громоздко.

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

Потенциальный риск моно-репо состоит в том, что разработчик может повторно использовать код, первоначально написанный для несвязанного модуля. Если два модуля общих кодов, то изменение этого общего кода может привести к ошибкам. Если эти ошибки не проверяются, они могут повлиять на конвейеры CI/CD (непрерывная интеграция и доставка) несвязанных микросервисов. Чтобы избежать таких проблем, важно иметь мощный пакет тестирования.

2. Проверьте, есть ли у вас модули, сильно отличающиеся от других.

Вы разрабатываете модуль, требующий совершенно иной технологии, языка, структуры или устойчивости? Тогда лучше выделить его в отдельный репозиторий.

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

Поэтому когда мы думали о реструктуризации кода для Collect, сохранение этих служб в отдельном репо казалось самоочевидным. Эти службы очень отличались от основного репозитария Collect (описанного выше). Хотя основное хранилище было предназначено для запросов пользователей, это хранилище касалось фоновых задач и исполнения. Кроме того, управление изменениями в этих службах должно быть другим и изолированным от основного хранилища.

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

3. Учитывайте неопределенность и, следовательно, частоту изменений, по которым может испытать услуга.

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

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

Первоначально блог был опубликован на blog.socialcops.com. Выше описано, как мы обрабатываем наши решения по хранилищу. Я надеюсь, что это поможет вам рассмотреть первых принципов, если вы подходите к этой проблеме. Подпишитесь на нашу рассылку, чтобы получить больше обновлений от команды SocialCops Engineering and Data Science.

Добавить комментарий

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