Микросервисы
June 12, 2023

Не начинайте с монолита

… когда ваша цель — микросервисная архитектура

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

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

Приступая к созданию новой системы, вы должны думать о том, чтобы разделить ее на части. Я категорически не согласен с идеей, что это можно отложить, как выразился Сэм Ньюман, опять же тот, с кем я согласен в 95% случаев:

Я по-прежнему убежден, что гораздо проще разделить существующую "готовую" систему, чем делать новую систему на современный лад. Вам есть с чем работать. У вас есть код, который вы можете изучить, вы можете поговорить с людьми, которые используют и поддерживают систему. Вы также знаете, как выглядит «хорошо» — так как у вас есть работающая система, которую нужно изменить, в этом случае вам легче понять, когда вы, возможно, что-то не так поняли или были слишком опрометчивы в процессе принятия решений.
Сэм Ньюман

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

Если вы действительно можете построить хорошо структурированный монолит, вам, вероятно, вообще не нужны микросервисы. Что нормально! Я определенно согласен с Мартином: вам не следует усложнять систему дополнительным её распределением, если у вас нет для этого очень веской причины.

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

Ожидание и Реальность

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

Но если вы начнете с монолита, части будут чрезвычайно тесно связаны друг с другом. Это и есть определение монолита. Части будут зависеть от особенностей платформы, которую они все используют. Они будут взаимодействовать на основе общих абстракций, потому что все они используют одни и те же библиотеки. Они будут обмениваться данными, используя средства, доступные только тогда, когда они размещены в одном и том же процессе. И это только технические аспекты! Что еще хуже, части будут (почти) свободно совместно использовать объекты предметной области, полагаться на одну и ту же общую модель, полагаться на одну и ту же общую модель сохранения, предполагать, что транзакции базы данных легко доступны, так что нет необходимости в компенсации… Даже сам факт того, что можно легко реорганизовать и перемещать части – для удобства представления в вашей IDE в рамках проекта – это то, что чрезвычайно затрудняет повторное разделение. Чрезвычайно сложно разделить существующий монолит на отдельные части.

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

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

Итак, есть ли какой-либо реальный опыт, подтверждающий это? Да, есть несколько систем, с которыми мы недавно работали, которые показали, что эта концепция работает – при условии, что вы допускаете тот факт, что то, о чем я говорю, скорее всего, больше, чем ваш типичный микросервис. Наиболее заметным из них является Otto.de, о котором я говорил вместе с их техническим руководителем (и о котором вы можете прочитать в этой замечательной статье одного из их ведущих архитекторов). Но есть и немало других, и я по–прежнему убежден, что начать создавать систему с использованием этого подхода - хорошая идея, если вы очень-очень хорошо знаете предметную область, для которой строите.

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

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

Источник: https://martinfowler.com/articles/dont-start-monolith.html