Осложнения со слабой связью в архитектуре микросервисов

Я новичок во всем мире микросервисов. Я провел некоторое исследование архитектуры и принципов, лежащих в основе хорошей среды микросервисов.

Предполагается, что одна из основных характеристик микросервиса - это слабосвязанная природа каждой услуги. Микрослужба A никогда не должна вызывать Micro Service B напрямую, в противном случае вы фактически создаете монолитную систему, которая теряет масштабируемость, предлагаемую шаблоном архитектуры.

Вопрос / пример

Если я разрабатываю микрослужбу, которая возвращает GUID (например), разумно предположить, что другие микросервисы в среде могут вызывать службу GUID напрямую, когда она требуется.

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

Я не могу понять, как будет использоваться очередь для простого чтения (как в моем примере с GUID) и почему вы просто не вызовете службу GUID напрямую из другого микросервиса.

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

Было бы очень полезно внести некоторую ясность в этот вопрос.


person Gers    schedule 18.06.2019    source источник
comment
Вы все неправильно думаете об этом. Очереди используются для передачи событий. События описывают то, что уже произошло. Получить мне GUID - это команда, которая является инструкцией на случай, если что-то произойдет в будущем. В архитектуре микросервисов сообщения о событиях могут использоваться для синхронизации состояния между отдельными службами. Вместо GUID в вашем примере. представьте себе пользователя. Когда пользователь создается, событие UserCreated публикуется службой Users. Это позволяет любой другой службе также использовать эти данные. Таким образом, для получения пользователя больше не нужно обращаться к сервису «Пользователи».   -  person tom redfern    schedule 18.06.2019
comment
Кроме того, он не нарушает никаких правил, позволяющих микросервисам вызывать друг друга напрямую через http (s). Любая конструкция системы, которая требует, чтобы вы никогда этого не делали, ошибочна. Архитектура микросервисов стремится уменьшить взаимосвязь, а не устранить ее. Прямые вызовы иногда являются лучшим или даже единственным способом передачи состояния между службами. Просто в большинстве случаев затраты на усиление сцепления не окупаются.   -  person tom redfern    schedule 18.06.2019
comment
Спасибо за ответ @tomredfern, это немного проясняет ситуацию. Думаю, требуется еще несколько исследований по аспекту сообщений о событиях.   -  person Gers    schedule 18.06.2019


Ответы (1)


Не следует соблюдать все правила как таковые.

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

Я не согласен с этим ограничением, согласно которому микрослужба A никогда не должна вызывать микросервис B как общее правило, поскольку это не относится ко всем случаям. Я работал с несколькими системами, использующими микросервисы, и мы этого не делали.

Связь между микросервисами:

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

  1. События (с использованием очереди)

  2. Команды - прямой вызов через API к другому микросервису (который является своего рода инструкцией для микросервиса), который требует внесения изменений (Create, Update, Delete).

  3. Запросы - прямой вызов через API к другому микросервису (например, ваш пример получения GUID). Опять же, некоторые люди скажут, что это тоже команда. Использование запроса в качестве термина часто комбинируется, когда вы также используете CQRS.

  4. Общие базы данных (большинство онлайн-ресурсов советуют вам не делать этого по нескольким причинам) В целом это не рекомендуемый подход.

В целом

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

Я дам вам пример, почему:

Пример:

Допустим, у вас есть «микросервис A» и «микросервис B». Ваш «микросервис B» потребляет события, которые «микросервис A» публикует через Kafka. «Микросервис B» при использовании событий сохраняет некоторые релевантные «Внешние» данные в своей собственной базе данных (дублируя их). Это распространенный подход - не вызывать «микросервис А» каждый раз, когда вам нужны некоторые из его данных. Это обычное явление, например, если «микрослужба A» - это служба, имеющая параметры конфигурации системы или аналогичные.

Допустим, у вас есть сценарий катастрофы, когда ваша база данных и все данные из вашей «микросервиса B» уничтожены или повреждены. Чтобы решить эту проблему, вы можете просто восстановить резервную копию и применить последние события, скажем, за последний час, когда ваша «микрослужба B» не работала, и решить проблему (если ваша обработка событий реализована как Idempotent). В этом случае все хорошо.

С другой стороны, если у вас есть система, работающая какое-то время в производственной среде. Через некоторое время вы разрабатываете «микросервис C» и решаете развернуть его в производственной среде. Оказывается, вам нужны какие-то данные, которые производит «микросервис А». Вам нужны эти данные на вашем «микросервисе C» как внешние данные, аналогичные тем, которые были у вас с «микросервисом B». Как получить эти данные? Вы потребляете все события из «микросервиса А»? В идеальном мире вы бы навсегда сохранили все события в Кафке. В этом случае вы просто должны подписаться на события и применить их все, чтобы сохранить все необходимые данные в «микросервисе C». На самом деле вам нужно установить некоторое Retention Период для вашего Kafka, скажем, 5 дней. Если ваша система работает дольше 5 дней, вы не можете воссоздать свои данные из событий.

В этом случае вам нужно вызвать службу напрямую с помощью Command / Query и заполнить базу данных «микросервис C».

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

Резюме:

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

person xargs    schedule 18.06.2019