Что за сервисы и как поделены — ничего про это нету.
Тут вопрос знания нашей специфики и предметной области. Вряд ли Вам что-то даст описание наших сервисов. Но если есть конкретные вопросы — спрашивайте, постараюсь ответить.
При восходящей разработке (аджайлы — это bottom-up), функции добавляются инкрементально. После десятков итераций получается каша из взаимозависимостей, по-хорошему требующая работы предметных аналитиков по реструктуризации. Хотя, конечно, всегда есть опция «оставить как есть и жить с этим».
Рефакторинг и работу над техническим долгом никто не отменял
Смотря какой вопрос… Расскажите, что имелось в виду, плз
Сколько слоев из (микро)сервисов получется на данный момент?
Пока уровень вложенности меньше 10
Какова стоимость развертывания и управления зависимостями по сравнению с обычными сервисами?
А что считать обычными сервисами? Любому сервису нужен сетевой доступ, роутинг, мониторинг, доступы к БД… У нас сейчас многие из этих задач на себя берет k8s и PaaS, поэтому на мой взгляд сейчас у нас выходит дешевле и безопаснее — многие риски закрывает сам PaaS и прикладной инструментарий ему сопутствующий
Cоблюдается ли правило один мс — одна таблица в бд (модель)?
Никогда не слышал о таком правиле. У нас есть другое правило — у каждого сервиса своя БД в которую можно достучаться только через API. И в этой БД может быть столько таблиц, сколько необходимо для реализации функционала сервиса.
Как общаются мс между собой?
Вызовы по API и Event Bus
Есть ли разница в общении между мс, написанными на одном языке и мс, написанными на разных?
По сути нет — мы выпускаем клиентов под наши основные языки. Взаимодействия через общие принципы работы шины или REST API
Дублируются ли мс для распределения нагрузки?
Если я правильно понял вопрос — да, мы запускаем несколько инстансев сервиса
>Сложно менять код одновременно везде
Тут как раз ключевое не в том, что код сложно менять как таковой, а речь идет о каких-то больших рефакторингах которые затрагивают много сервисов.
Мониторить <> завести в zabbix/графану/ etc
Тут вопрос более комплексный: какие метрики собирать, на что обращать внимание, что выводить на графики и как эти графики трактовать. Как различать — вот тут оно само починится, а тут уже админам звонить. Или вот тут вроде само чинится, но что-то идет не так.
Event Bus — это по определению notify, в противном случае вы создаете сильную связанность между сервисами и теряете возможность их независимой разработки и поддержки. Поэтому речь тут идет именно о NSQ и RabbitMQ, а не, скажем, о Gearman.
А ситуацию с контролем нужно рассматривать несколько иначе: входная точка — это корректное создание аккаунта. Если создание прошло, значит есть отправная точка и предварительная проверка корректности данных. Далее у нас есть UserID к которому делается привязка остальных частей — заведение в биллинге, подготовка аватары и тп. И тут вступает в игру такой паттерн как «eventual consistency» — т.е. мы даем системе какое-то время, чтобы собраться к конечному состоянию в правильном виде и получить итоговый статус «регистрация полностью завершена». Если же этого не происходит, то сервис контроля инициирует процедуру отката. И вот наличие этой процедуры отката — один из вопросов при проектировании распределенной системы. Эта ситуация характерна не только для микросервисов — это вопрос именно к любой распределенной многокомпонентной системе.
Реализуете ли вы каждый раз новую Hystrix-команду для обращения к микросервису в конкретном месте кода, или circuit breaker «вшит» где-то на инфраструктурном уровне?
Не уверен, что правильно понял вопрос, но… каждый вызов внешнего сервиса делается посредством обертки хистрикса
Как вы управляете конфигурацией circuit breaker'ов: список инстансов микросервиса, допустимые таймауты и процент ошибок, время бана микросервиса и т.п.
У нас для всех сервисов единая точка конфигурирования на базе KV-хранилища Consul-а. В нем хранится вообще все, что касается конфигурации сервисов в целом и каждого в частности. Каждый сервис на момент инициализации знает только свой ID, версию и то, как достучатся до Consul-а, чтобы забрать из него конфигурацию
Как вы «подружили» Hystrix с кодом на Go?
Использовали вот эту библиотеку: https://github.com/afex/hystrix-go
1. Как собираете образы? На каждый микросервис свой образ или же вся кодовая база в одном образе и при старте контейнера передаете аргументом название микросервиса? Или как-то еще?
1 микросервис — 1 репозиторий — 1 контейнер. Каждый репозиторий самодостаточен, у каждого своя кодовая база.
2. Как выполняете, например, миграции? При деплое стартует микросервис, который выполняет необходимые действия и затем умирает?
Нет, миграции — это часть процесса деплоя, сервис поставляется с файлами миграции, которые запускаются системой деплоя в момент раскатки в среду (прод/стэйдж/лоад/...)
3. Как структурирован проект? При таком количестве микросервисов, подозреваю, что все это хранятся не в одном репозитории. Тогда как решаете необходимость переиспользования кода в разных микросервисах (общие модели и т.д.)? Подмодулями? Как?
Есть шаблон микросервиса — из него генерится новый микросервис на старте разработке, далее у него полностью своя кодовая база, которая развивается самостоятельно. Если какой-то функционал из шаблона должен получить критическое обновление — выпускается общий патч.
Для нас основной аргумент для миграции был в том, что на тот момент Nomad не умел работать с внешними volume и имел серьезные проблемы с запуском/остановкой сервисов в случае переименования job-а
— Как распространяются изменения в шаблоне? Допустим, исправили критическую ошибку в логировании, каким образом изменения появятся в зупущенных сервисах и появятся ли они вообще?
Если прям критическое, то выпускается патч и рассылается всем командам, если не критичное, то каждая команда принимает решение об апдейте самостоятельно
— Как появился этот шаблон: вырос самостоятельно, введён директивно мейнтейнером, etc?
Самостоятельно, по мере накопления опыта выделились общие части каждого микросервиса, которые и стали сборкой для шаблона
habr.com/ru/company/avito/blog/418235
Тут вопрос знания нашей специфики и предметной области. Вряд ли Вам что-то даст описание наших сервисов. Но если есть конкретные вопросы — спрашивайте, постараюсь ответить.
Рефакторинг и работу над техническим долгом никто не отменял
Смотря какой вопрос… Расскажите, что имелось в виду, плз
Пока уровень вложенности меньше 10
А что считать обычными сервисами? Любому сервису нужен сетевой доступ, роутинг, мониторинг, доступы к БД… У нас сейчас многие из этих задач на себя берет k8s и PaaS, поэтому на мой взгляд сейчас у нас выходит дешевле и безопаснее — многие риски закрывает сам PaaS и прикладной инструментарий ему сопутствующий
Никогда не слышал о таком правиле. У нас есть другое правило — у каждого сервиса своя БД в которую можно достучаться только через API. И в этой БД может быть столько таблиц, сколько необходимо для реализации функционала сервиса.
Вызовы по API и Event Bus
По сути нет — мы выпускаем клиентов под наши основные языки. Взаимодействия через общие принципы работы шины или REST API
Если я правильно понял вопрос — да, мы запускаем несколько инстансев сервиса
Тут как раз ключевое не в том, что код сложно менять как таковой, а речь идет о каких-то больших рефакторингах которые затрагивают много сервисов.
Тут вопрос более комплексный: какие метрики собирать, на что обращать внимание, что выводить на графики и как эти графики трактовать. Как различать — вот тут оно само починится, а тут уже админам звонить. Или вот тут вроде само чинится, но что-то идет не так.
А ситуацию с контролем нужно рассматривать несколько иначе: входная точка — это корректное создание аккаунта. Если создание прошло, значит есть отправная точка и предварительная проверка корректности данных. Далее у нас есть UserID к которому делается привязка остальных частей — заведение в биллинге, подготовка аватары и тп. И тут вступает в игру такой паттерн как «eventual consistency» — т.е. мы даем системе какое-то время, чтобы собраться к конечному состоянию в правильном виде и получить итоговый статус «регистрация полностью завершена». Если же этого не происходит, то сервис контроля инициирует процедуру отката. И вот наличие этой процедуры отката — один из вопросов при проектировании распределенной системы. Эта ситуация характерна не только для микросервисов — это вопрос именно к любой распределенной многокомпонентной системе.
По нагрузке точно не скажу кто нагружен сильнее, но могу сказать, что в ситуации обмена сообщения между датацентрами мы используем NSQ.
У нас для всех сервисов единая точка конфигурирования на базе KV-хранилища Consul-а. В нем хранится вообще все, что касается конфигурации сервисов в целом и каждого в частности. Каждый сервис на момент инициализации знает только свой ID, версию и то, как достучатся до Consul-а, чтобы забрать из него конфигурацию
Использовали вот эту библиотеку: https://github.com/afex/hystrix-go
1 микросервис — 1 репозиторий — 1 контейнер. Каждый репозиторий самодостаточен, у каждого своя кодовая база.
Нет, миграции — это часть процесса деплоя, сервис поставляется с файлами миграции, которые запускаются системой деплоя в момент раскатки в среду (прод/стэйдж/лоад/...)
Есть шаблон микросервиса — из него генерится новый микросервис на старте разработке, далее у него полностью своя кодовая база, которая развивается самостоятельно. Если какой-то функционал из шаблона должен получить критическое обновление — выпускается общий патч.
Если прям критическое, то выпускается патч и рассылается всем командам, если не критичное, то каждая команда принимает решение об апдейте самостоятельно
Самостоятельно, по мере накопления опыта выделились общие части каждого микросервиса, которые и стали сборкой для шаблона