Skip to content

Latest commit

 

History

History
490 lines (315 loc) · 50.8 KB

File metadata and controls

490 lines (315 loc) · 50.8 KB

Вопросы для собеседования

ООП + Микросервисы

Что такое ООП?

Объектно-ориентированное программирование (ООП) — методология программирования, основанная на представлении программы в виде совокупности объектов, каждый из которых является экземпляром определенного класса, а классы образуют иерархию наследования.

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

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

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

к оглавлению

Назовите основные принципы ООП.

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

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

к оглавлению

Что такое «инкапсуляция»?

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

Цель инкапсуляции — уйти от зависимости внешнего интерфейса класса (то, что могут использовать другие классы) от реализации. Чтобы малейшее изменение в классе не влекло за собой изменение внешнего поведения класса.

к оглавлению

Что такое «наследование»?

Наследование – это свойство системы, позволяющее описать новый класс на основе уже существующего с частично или полностью заимствующейся функциональностью.

Класс, от которого производится наследование, называется предком, базовым или родительским. Новый класс – потомком, наследником или производным классом.

к оглавлению

Что такое «полиморфизм»?

Полиморфизм – это свойство системы использовать объекты с одинаковым интерфейсом без информации о типе и внутренней структуре объекта. Т.е. использовать разные объекты одинаково, через общий интерфейс.

Пример: у нас есть метод draw(). Для круга он рисует окружность, для квадрата — квадрат. Но мы обращаемся к ним одинаково: figure.draw().

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

Полиморфизм бывает динамическим (переопределение методов в потомках) и статическим (перегрузка методов -одинаковое имя, разные параметры).

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

  • ad hoc, функция ведет себя по разному для разных типов аргументов (например, функция draw() — рисует по разному фигуры разных типов);
  • параметрический, функция ведет себя одинаково для аргументов разных типов (например, функция add() — одинаково кладет в контейнер элементы разных типов).

к оглавлению

Что такое «абстракция»?

Абстрагирование – это способ выделить набор общих характеристик объекта, исключая из рассмотрения частные и незначимые. Соответственно, абстракция – это набор всех таких характеристик.

Пример: когда мы говорим «машина», нам важно, что у неё есть двигатель и колёса, а цвет ковриков внутри — неважно.

к оглавлению

Что представляет собой «обмен сообщениями»?

Объекты взаимодействуют, посылая и получая сообщения. Сообщение — это запрос на выполнение действия + данные.

В ООП посылка сообщения (вызов метода) — это единственный путь передать управление объекту. Если объект должен «отвечать» на это сообщение, то у него должна иметься соответствующий данному сообщению метод. Так же объекты, используя свои методы, могут и сами посылать сообщения другим объектам.

к оглавлению

Расскажите про основные понятия ООП: «класс», «объект», «интерфейс».

Класс – шаблон описания сущности, определяющий состояние и поведение, зависящее от этого состояния, а также правила для взаимодействия с данной сущностью (контракт).

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

С точки зрения структуры программы, класс является сложным типом данных.

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

Интерфейс – это набор методов класса, доступных для использования. Интерфейсом класса будет являться набор всех его публичных методов в совокупности с набором публичных атрибутов. По сути, интерфейс специфицирует класс, чётко определяя все возможные действия над ним.

к оглавлению

В чем заключаются преимущества и недостатки объектно-ориентированного подхода в программировании?

✅ Ближе к человеческому восприятию мира.

✅ Код разбивается на логичные части.

✅ Удобнее поддерживать и расширять.

✅ Код можно переиспользовать.

✅ Легко добавлять новые объекты и изменять поведение программы.

❌ Иногда сложно понять, где что наследуется.

❌ Методы могут быть «размазаны» по разным классам.

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

❌ Дополнительные расходы памяти и производительности.

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

к оглавлению

Что подразумевают в плане принципов ООП выражения «является» и «имеет»?

«является» подразумевает наследование. Класс cat является потомком класса animal «имеет» агрегация или композиция. Класс car имеет класс engine

к оглавлению

В чем разница между композицией и агрегацией?

Ассоциация обозначает связь между объектами.

Агрегация — «часть» может существовать отдельно и принадлежать нескольким «целым». (Книга находится в библиотеке, её можно перенести в другую).

Композиция — «часть» жёстко привязана к «целому». (Страница принадлежит конкретной книге).

к оглавлению

Что такое статическое и динамическое связывание?

Связывание означает наличие связи между ссылкой и кодом. Например, переменная, на которую вы ссылаетесь, привязана к коду, в котором она определена. Аналогично, вызываемый метод привязан к месту в коде, где он определен.

Статическим или ранним связыванием (early binding) — компилятор заранее знает, какой метод будет вызван. (Напр. перегрузка методов).

Позднее связывание (late binding) или динамическое проводимое непосредственно во время выполнения программы, в зависимости от типа объекта (Напр. переопределение методов в наследниках). Механизм позднего связывания зависит от конкретного языка

Итак, фундаментальное различие между статическим и динамическим связыванием в Java состоит в том, что первое происходит рано, во время компиляции на основе типа ссылочной переменной, а второе – позднее, во время выполнения, с использованием конкретных объектов.

В Java почти все методы — динамические, кроме static, final и private.

Ключевые различия между ранним и поздним связыванием в языке Java:

  1. Статическое связывание используется в языке Java для разрешения перегруженных методов, в то время как динамическое связывание используется в языке Java для разрешения переопределенных методов.

  2. Аналогично, приватные, статические и терминальные методы разрешаются при помощи статического связывания, поскольку их нельзя переопределять, а все виртуальные методы разрешаются при помощи динамического связывания.

  3. В случае статического связывания используются не конкретные объекты, а информация о типе, то есть для обнаружения нужного метода используется тип ссылочной переменной. С другой стороны, при динамическом связывании для нахождения нужного метода в Java используется конкретный объект.

к оглавлению

Принцип SOLID?

Пять основных принципов дизайна классов:

  • Single Responsibility Principle (Принцип единственной ответственности).
  • Open Closed Principle (Принцип открытости/закрытости).
  • Liskov’s Substitution Principle (Принцип подстановки Барбары Лисков).
  • Interface Segregation Principle (Принцип разделения интерфейса).
  • Dependency Inversion Principle (Принцип инверсии зависимостей).

Принцип единственной ответственности (SRP)
Никогда не должно быть больше одной причины изменить класс.

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

Представьте себе модуль, который обрабатывает заказы. Если заказ верно сформирован, он сохраняет его в базу данных и высылает письмо для подтверждения заказа. Принцип единственной обязанности подразумевает, что три аспекта этой проблемы на самом деле — три разные обязанности. А значит, должны находиться в разных классах или модулях. Объединение нескольких сущностей, которые могут меняться в разное время и по разным причинам, считается плохим проектным решением. Гораздо лучше разделить модуль на три отдельных, каждый из которых будет выполнять одну единственную функцию.

Принцип открытости/закрытости (OCP)
Программные сущности (классы, модули, функции и т.п.) должны быть открыты для расширения, но закрыты для изменения.

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

Принцип подстановки Барбары Лисков (LSP)
Объекты в программе можно заменить их наследниками без изменения свойств программы.

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

Принцип разделения интерфейса (ISP)
Клиенты не должны быть вынуждены реализовывать методы, которые они не будут использовать.

Принцип разделения интерфейсов говорит о том, что слишком «толстые» интерфейсы необходимо разделять на более мелкие и специфические, чтобы клиенты мелких интерфейсов знали только о методах, необходимых в работе.

Рассмотрим пример. Разработчик Алекс создал интерфейс "отчет" и добавил два метода: generateExcel() и generatedPdf(). Теперь клиент А хочет использовать этот интерфейс, но он намерен использовать отчеты только в PDF-формате, а не в Excel. Он должен будет реализовать два метода, один из которых по большому счету не нужен и существует только благодаря Алексу — дизайнеру программного обеспечения. Клиент воспользуется либо другим интерфейсом, либо оставит поле для Excel пустым. Так в чем же решение? Оно состоит в разделении существующего интерфейса на два более мелких. Один — отчет в формате PDF, второй — отчет в формате Excel. Это даст пользователю возможность использовать только необходимый для него функционал.

Принцип инверсии зависимостей (DIP)
Зависимости внутри системы строятся на основе абстракций. Объектом зависимости должна быть абстракция, а не что-то конкретное. Модули верхнего уровня не зависят от модулей нижнего уровня. Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций. Программное обеспечение нужно разрабатывать так, чтобы различные модули были автономными и соединялись друг с другом с помощью абстракции.

Классическое применение этого принципа — Spring framework. В рамках Spring framework все модули выполнены в виде отдельных компонентов, которые могут работать вместе. Они настолько автономны, что могут быть быть с такой же легкостью задействованы в других программных модулях помимо Spring framework. Это достигнуто за счет зависимости закрытых и открытых принципов. Все модули предоставляют доступ только к абстракции, которая может использоваться в другом модуле.

к оглавлению

Что такое Монолит, Микросервис?

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

При начале работы над монолитным проектом Достоинства:

✅ Быстрая разработка

✅ Возможность внесения радикальных изменений (например изменить архитетуру, класс-дизайн, схему бд)

✅ Безболезненое тестирование

✅ Легкое развертывание

✅ Простое hardware масштабирование

С увеличением размера проекта и команды разработки появляются Минусы:

❌ Медленное внесение изменений

Команды А и Б работают не пересекаясь. Выкатывается новая версия проекта с багами в коде команды Б. Откатывается на предыдущуюю версию весь код и команды Б и команды А.

❌ Уязвимая надежность - если падает часть кода, то не работает все приложение.

❌ Трудности в hardware масштабировании.

Одна часть требует оперативу, другая ядра. Приходится апгрейдить "вертикально" - покупать больше оперативных планок и процессоры с большим кол-вом ядер для всех сервисов. А не по потребностям

❌ Дороговизна обновления технологического стека. Например переход на новую версию Java. Чтобы проверить эффективность, нужно переписывать весь проект

Микросервисная архитектура — система, которая содержит больше одного обособленнго сервиса. Размер значения не имеет. Обособленный сервис — является независимой единицей развертывания, имеет своё хранилище, свою БД (?), отвечает за свою часть предметной области

Достоинства:

✅ Возможность масштабирования разработки

✅ Дешевизна эксперементов с новым стеком

✅ Инкрементальное обновление технолошического стека

✅ Повышенная надежность и отказоустойчивость

Минусы: ❌ Сложность проектирования архитектуры

❌ Долгое внесение радикальных изменений

❌ Нетривиальное тестирование

❌ Повышенные требования к Continuous Integration/Continuous Delivery (деплою)

Сложности проектирования Микросервисов

  • Сложно разделить предметную область на части

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

Соответствие принципам Low coupling, high cohesion способствует быстрому внесению изменений и легкому тетсированию.

Сильная связанность high cohesion - части системы, которые изменяются вместе, должны находиться ближе друг к другу

Слабая связанность low coupling - части системы, которые изменяются параллельно, должны иметь как можно меньше зависимостей друг на друга b внутри сервиса и между сервисами

Image alt

  • Задержки при межсервисном взаимодействии влияют на производительность + сеть ненадежна
  • Межсервисное взаимодействие влияет на доступность
  • Сложно добиться согласованности данных

к оглавлению

Что такое Continuous Integration, Continuous Delivery/Deployment?

Непрерывная интеграция (CI) — процесс автоматического принятия изменений. Первичный процесс обновления ПО, в рамках которого все изменения на уровне кода вносятся в единый центральный репозиторий. Такое внесение принято называть слиянием. После каждого слияния (которое проходит по несколько раз в день) в изменяемой системе происходит автоматическая сборка (часто приложение упаковывается в Docker) и тестирование (проверка конкретных модулей кода, UI, производительности, надёжности API). Таким образом разработчики страхуются от слишком поздних обнаружений проблем в обновлениях.

  • Возможность локальной сборки проекта
  • На каждый коммит в кдаленный репо запускаем сборки проекта в системе (Jenkins, TravisCI)
  • Сломанная сборка запрещает слияние

Непрерывная доставка (CD) — CI + CD. Автоматизированый процесс доставки изменений до продакшена. Теперь новая версия не только создаётся и тестируется при каждом изменении кода, регистрируемом в репозитории, но и может быть оперативно запущена по одному нажатию кнопки развёртывания. Однако запуск развёртывания всё ещё происходит вручную — ту самую кнопку всё же надо кому-то нажать. Этот метод позволяет выпускать изменения небольшими партиями, которые легко изменить или устранить в случае необходимости.

  • Поддерживаем артефакты стабильными
  • Развертываем по кнопке

к оглавлению

Что выбрать Монолит или Микросервис?

Микро если:

  • Предметная область хорошо делится на части
  • Много направлений, которые нужно развивать параллельно
  • "Особенности" монолита не устраивают бизнес

Монолит если:

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

https://microservices.io/ https://martinfowler.com/ "microservices patterns" chris richardson "clean architecture" robert martin

к оглавлению

Взаимодействие между микросервисами

Межсервисное взаимодействие = сетевое взаимодействие, т.е. система управляется сообщениями

  • Производительность = задержки и пропускная способность
  • Доступность и отказоустойчивость
  • Архитектура

Транспорт

  • стандарт JSON внутри HTTP (REST, RPC, GraphQL). Простой, множество инструментов, человекочитаемость. Из-за текстового формата большие объемы и нужно оптимизировать

  • бинарные протоколы: gRPC, Thrift, Avro и т.д. Выше производительность, оптимизированно представление данных, можно определить схему сообщения из коробки, но меньше инструментов и не читаемы человеком

Что выбрать?

  • Начинать с HTTP
  • Бинарные не бесплатные
  • Большинство проблем не из-за протокола!
  • Для публичных API всегда HTTP либо несколько реализаций одна из которых HTTP

API

Application Programming Interface - интерфейс, определяющий способ и схему взаимодействия с сервисом

  • Remote Procedure Call (RPC)

Только POST метод. Все параметры в теле запроса. Любой статус !=200, считается ошибкой Выбирают: Простая реализация, Внутренние API, HTTP только как транспорт

  • Representational State Transfer (REST)

Архитектурный стиль, в основе которого лежат ресурсы и их идентификация, изменение их состояния через представление. REST != HTTP Выбирают: Своего рода стандарт, Внутренние API, Публичные API, HTTP как протокол

  • GraphQL

Язык запросов для API. Например можно задать конкретный набор полей, которые хотим получить в ответе на запрос Выбирают: Типо-безопасность, API для Web и мобильных клиентов, тут свой инструментарий

Проектирвоание

  • Клиент-сервер
  • Stateless - сервис не должен хранить состояние в памяти, это важно для масштабирования
  • Кеширование

Типы сообщений

  • Команды

Императивное управление (звучит как "сделать что-то"), вызывают сильную связанность, зато понятны - названия обычно отражают логику Image alt

  • События

Декларативное управление (звучит как "что-то произошло"), снижают связанность, менее понятны - не знаем что скрыто в notifyOrderCreated Image alt

Виды взаимодействия

  • Синхронные - отправляем запрос и блокируемся, ожидая результата. Просто и понятно, быстрые операции и низкие задержки (ок), низкая пропускная способность (не ок), вызывает низкую доступность (не ок)
  • Ассинхронные - не блокируемся ожидая ответ Сложнее в реализации, выше задержки (не ок), выше пропускная способность (ок), повышает доступность (ок)

Short polling - вызываем операцию и получаем ссылку на ресурс с результатом операции. Переодически опрашиваем этот ресурс на предмет текущего статуса операции Image alt

Пользователь должен ждать как можно меньше, и нужно выполнять как можно меньше запросов на опрос

Стратегии опроса:

  • Фиксированное время (раз в секунду) - просто, но время запроса может чуть отличаться, что приведет к лишним запросам
  • Прогрессия (геометрическая/алгебраическая) - сокращает кол-во запросов, но возможен вариант когда придется долго ждать
  • На основе статистического распределения - например, знаем, что запрос выполняется 50% за 1.5с, 90% за 3с и 99% за 5с, мы можем распределить запросы во времени

Callbacks - вызываем операцию и получаем идентификатор операции. Сервис, выполняющий операцию, отправляет уведомление вызвавшему сервису о результате выплонения операции Image alt

Способы взаимодействия

  • Прямой обмен А->Б - просто, легкая эксплуатация, но сильная связанность сервисов. Хорошо для Команд
  • Обмен через брокеры сообщений А->Брокер->Б - сложнее, позволяет снизить связанность сервисов. Хорошо для Событий На основе callback: RabbitMQ Image alt

На основе polling: Kafka Image alt

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

Сильная согласованность - всегда актуальные данные, но высокие задержки при получении

В таких случаях используются Распределенные транзакции. Но это сложно, дорого и есть не везде. Можно эмулировать распределенную транзакцию с помощью вложенных локальных транзакций Image alt

При этом возврат ошибки не гарантирует, что запись не была вставленна в БД. А откат первой транзакции не приводит к откату второй.

Saga паттерн: Для решения нужно разбивать одну большую распределенную транзакцию на последовательность локальных транзакций и предоставить возможность отката всех локальных транзакций. Image alt

Особенности: нужно уметь восстанавливаться после сбоев любого участка и повторять сагу с определенного шага + отличать финальные ошибки от нефинальных Хореография Image alt

  • Нет единой точки отказа
  • Легко менять кусочек процесса
  • Сложно понять процесс целиком и отслеживать ошибки

Оркестрация Image alt

  • Есть единая точка отказа
  • Сложнее вносить изменения в места
  • Легко понять процесс и отслеживать ошибки

Image alt

Конечная согласованность - могут быть неактуальные данные, зато низкие задержки

Image alt

Взаимоисключения

Иногда требуется выполнять какой-то процесс эксклюзивно. Например используя распределенный консенсус - алгоритмы, которые сложно и медленно работают. etcd, Consul, Zookeeper. Зато отказоустойчивы

Альтернатива - red lock, когда БД используется в качестве хранилища блокировок. Блокировка не захватывается, а арендуется на время. Чтобы в случае блокировки и отказа системы блокировка не осталась навсегда Добавляем версию блокировки для контроля ее корректности Image alt

к оглавлению

OpenAPI

OpenAPI - спецификация для описания REST API.

https://habr.com/ru/post/541592/

Swagger - это фреймворк для спецификации RESTful API, цель которого - поддерживать документацию в актуальном виде. Его прелесть заключается в том, что он дает возможность не только интерактивно просматривать спецификацию, но и отправлять запросы – так называемый Swagger UI.

  • Code first - сначала пишем код, потом генерируем спецификацию
  • Schema first - сперва спецификация, затем генерируем по ней код
  • Публикуем спецификацию (отделный артефак или Swagger)
  • Строго следовать этой спецификации

Документирование БД Database Schema as a Code - текущая схема должна быть представлена последовательностью патчей, хранимых как код

  • Возможность восстановить БД на любом окружении
  • Аудит, контроль, валидация
  • Flyway, Liquibase

к оглавлению

Тестирование микросервисов

  • Компонентные тесты проверяют работу сервисов и их взаимодействие
  • Модульные тесты для тестирования отдельных функций

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

Тесты должны быть независимыми и уметь работать параллельно.

Для тестирования API лучше делать реальные HTTP вызовы, валидировать ответ согласно схеме (JSON). RESTAssured как пример инструмента.

При тестирование взаимодействия с БД на каждый запуск тестов локально поднимается БД. Embedded или TestContainers. Тесты не должны очищать БД или буффер брокера сообщений перед/после своего запуска/завершения

При тестировании взаимодействия микросервисов на каждый запуск тестов локально HTTP-сервер, создаем моки операций сервисов, выполняем, моки валидируем. WireMock, MockServer

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

Для автоматизации развиваем Continuous Integration/Continuous Delivery - помогает быстрее развивать сервисы и доставлять их на production. Но дорого.

к оглавлению

Распределенная трассировка

При межсервисном взаимодействии сложно отследить весь путь запроса по системе

  • К каждому внешнему запрсос прикрепляем "идентификатор операции"
  • Пробрасываем его по всей системе
  • Добавляем его в логовые сообщения для отслеживания. Elastic APM, OpenTracing

Для HTTP: Прикрепляем HTTP-заголовок с этим идентификатором - Используем его при обработке запроса - Поллинг делаем с тем же индентификаторо - Обраный вызов с ним же - В брокер сообщений также отправляем этот индентификатор

Для Саги: Исходный запрос теряется при обработке асинхронных процессов - В задачу на продолжение саги кладем исходный идентификатор операции (в БД) - При возобновлении саги используем этот идентификатор

Визуализация трасс помогает построить схему взаимодействия между сервисами. Можно это делать атоматически и динамически. Zipkin, Jaeger

к оглавлению

Источники

Вопросы для собеседования