Вообще говоря, я настоятельно рекомендую использовать вариант 2 из-за временной связи между этими двумя службами (если связь между этими службами не является сверхстабильной и не очень частой). Временная связь - это то, что вы описываете как this makes B and C dependant upon A (at all times)
, и это означает, что если A выключен или недоступен из B или C, B и C не могут выполнять свою функцию.
Я лично считаю, что оба варианта 1 и 3 имеют ситуации, когда они являются допустимыми вариантами.
Если связь между A и B & C настолько высока, или объем данных, необходимых для go в событие, достаточно велик, чтобы сделать его беспокойство, тогда вариант 3 является лучшим вариантом, потому что нагрузка на сеть намного ниже, и задержка операций будет уменьшаться с уменьшением размера сообщения. Другие проблемы, которые следует рассмотреть здесь:
- Стабильность контракта: если контракт сообщения, покидающего A, часто меняется, то добавление большого количества свойств в сообщение приведет к большим изменениям у потребителей. Однако в этом случае я считаю, что это не будет большой проблемой, потому что:
- Вы упомянули, что система A является CMS. Это означает, что вы работаете со стабильным доменом, и поэтому я не думаю, что вы будете часто сталкиваться с изменениями
- Поскольку B и C отправляют и отправляют электронную почту, а вы получаете данные от А, я полагаю, что вы будете испытывать аддитивные изменения, а не ломать их, которые можно добавлять всякий раз, когда вы обнаружите их без каких-либо переделок.
- Соединение: очень мало или нет сцепление здесь. Во-первых, поскольку связь осуществляется посредством сообщений, во время заполнения данных не существует никакой связи между службами, кроме коротких временных, и договором об этой операции (который не является связью, которую вы можете или должны попытаться избежать)
Вариант 1 - это не то, что я бы отверг. Существует такое же количество связей, но с точки зрения разработки это должно быть легко сделать (нет необходимости в специальных действиях), а стабильность домена должна означать, что они не будут меняться часто (как я уже упоминал).
Другой вариант, который я бы предложил, это небольшое изменение до 3, которое заключается не в том, чтобы запускать процесс во время запуска, а в том, чтобы вместо этого наблюдать событие «ProductAdded» и «ProductDetailsChanged» на B и C, когда есть изменение в каталоге продуктов в A. Это ускорит развертывание (и, следовательно, упростит исправление проблемы / ошибки, если вы ее обнаружите).
Редактировать 2020-03-03
У меня есть определенный c порядок приоритетов при определении подхода к интеграции:
- Какова стоимость согласованности? Можем ли мы принять несколько миллисекунд несоответствия между вещами, измененными в А и они отражаются в B & C?
- Вам нужны запросы на определенный момент времени (также называемые временными запросами)?
- Есть ли источник истины для данные? Служба, которая владеет ими и считается восходящей?
- Если есть владелец / единственный источник правды, это стабильно? Или мы ожидаем увидеть частые критические изменения?
Если цена несоответствия высока (в основном данные продукта в A должны быть как можно скорее согласованы с продуктом, кэшированным в B и C), тогда вы не сможете избежать необходимости принять недоступность и сделать синхронный запрос (например, запрос web / rest) от B & C к A для получения данных. Будь в курсе! Это по-прежнему не означает транзакционную согласованность, а сводит к минимуму windows за несогласованность. Если вы абсолютно, безусловно, должны быть последовательными, вам нужно изменить границы своих услуг. Однако я очень твердо верю, что это не должно быть проблемой. Исходя из опыта, на самом деле крайне редко, когда компания не может принять несколько секунд несогласованности, поэтому вам даже не нужно делать синхронные запросы.
Если вам нужны запросы на определенный момент времени (которые я не заметил в вашем вопросе и, следовательно, не упомянул выше, возможно, неправильно), стоимость поддержки этого в последующих сервисах очень высока (вы бы необходимо продублировать внутреннюю логику проекции события c во всех последующих службах), что делает решение ясным: вы должны оставить владение A и запросить A ad-ho c через веб-запрос (или аналогичный), а A должен использовать событие источник, чтобы получить все события, о которых вы знали в то время, чтобы спроецировать в состояние и вернуть его. Я предполагаю, что это может быть вариант 2 (если я правильно понял?), Но затраты таковы, что, хотя временная связь лучше, чем стоимость обслуживания дублированных событий и логических проекций c.
Если вы этого не сделаете нужен момент времени, и нет четкого, единого владельца данных (который в моем первоначальном ответе я предположил, что это основано на вашем вопросе), тогда вполне разумным было бы хранить представления продукта в каждом сервис отдельно. Когда вы обновляете данные для продуктов, вы обновляете A, B и C параллельно, делая параллельные веб-запросы к каждому, или у вас есть командный API, который отправляет несколько команд каждому из A, B и C. B & C используют свою локальную версию данных для выполнения своей работы, которая может быть или не быть устаревшей. Это не какой-либо из вышеперечисленных вариантов (хотя его можно сделать близким к варианту 3), поскольку данные в A, B и C могут различаться, и «весь» продукта может представлять собой совокупность всех три источника данных.
Полезно знать, что источник истины имеет стабильный контракт, потому что вы можете использовать его для использования домена / внутренних событий (или событий, которые вы сохраняете в своем источнике событий как шаблон хранения в A) для интеграции между А и службами B и C. Если договор стабилен, вы можете интегрироваться через доменные события. Тем не менее, у вас возникает дополнительная проблема в случае частых изменений или того, что договор сообщения достаточно велик, что делает транспортировку проблемой.
Если у вас есть явный владелец, с противоположным c, что как ожидается, будет стабильным, лучшие варианты будут вариант 1; заказ будет содержать всю необходимую информацию, а затем B и C будут выполнять свои функции, используя данные в событии.
Если контракт может изменяться или часто нарушаться, следуя вашему варианту 3, то есть Откат к веб-запросам для получения данных о продуктах на самом деле является лучшим вариантом, поскольку поддерживать несколько версий гораздо проще. Поэтому B сделает запрос на v3 продукта.