
Великий аргентинский писатель Хорхе Луис Борхес в одном из своих произведений попытался доказать, что вся мировая литература сводится к четырем базовым сюжетам: истории об осаде и защите обречённого города, истории о возвращении, истории о поиске и истории о жертвоприношении или самоубийстве бога. В комментарий к этому заявлению Виктор Пелевин в одном из своих романов написал: "А по-моему, сюжетов всего два. Первый – как человека убивают из-за денег. Второй – как человека приносят в жертву. А на самом деле оба сюжета можно даже объединить в один". Как бы то ни было, оставим спор о сюжетах литературоведам. В этом посте я хочу разобрать схожий тезис - все архитектуры разных видов программного обеспечения можно свести к двум базовым структурам - монолиту и шине.
Операционные системы
В операционных системах есть два типа ядер:
Монолитное ядро (монолит)
Микроядро (шина)
Весь код монолитного ядра выполняется в едином адресном пространстве, а его модули общаются друг с другом через обычные вызовы системных функций. Преимущество монолитного ядра состоит в скорости его работы. Проблема же состоит в том, что при изменении любого модуля, например какого-нибудь драйвера, приходится перекомпилировать всю систему. Кроме того, при фатальной ошибке в одном из модулей падает вся операционная система.
Микроядро предоставляет минимальный набор системных функций, а все модули, в том числе драйверы и файловая система, подключаются к нему и общаются друг с другом через сообщения по шине данных. Это даёт возможность заменять модули на лету - например, подгрузить драйвер без перекомпиляции и даже без перезапуска операционной системы. И ошибка в одном из модулей никак не затронет другие. Более того, можно выкинуть из операционки все ненужные модули, что сильно снизит её размер в байтах. Да и тестировать отдельные модули гораздо проще, чем огромный единый монолит. Недостаток же микроядерных ОС заключается в том, что за удобства приходится платить оверхедом по производительности и более низкой, чем у монолитных систем, скоростью работы.
Примеры ОС с монолитным ядром: Linux, MacOS, Windows. Знаменитый синий экран смерти в Windows возникает как раз из-за монолитности его ядра. Но даже в этих операционных системах используется похожая на микроядерную архитектура подгрузки внешних модулей, так что вернее было бы назвать их гибридными.
Примеры ОС с микроядром: учебный MINIX и операционная система реального времени QNX. Микроядерные системы часто используются в автомобилях, станках, самолетах, космических спутниках и кораблях и вообще везде, где важна стабильность, отказоустойчивость, маленький размер и возможность работать в реальном времени, то есть, иметь строго заданное время исполнения различных функций и фиксированное время отклика.
В 1992 году состоялся знаменитый спор создателя Linux Линуса Торвальдса и создателя MINIX Эндрю Таненбаума о преимуществах и недостатках монолитных ядер и микроядер.
Бекенд
При разработке бекенда тоже используется два подхода к построению его архитектуры:
Монолит
Микросервисы
Монолит представляет собой единое приложение, в котором все модули компилируются вместе и работают в рамках одного сервиса. Модули общаются друг с другом через обычные вызовы функций. Преимущество этого подхода состоит в скорости работы системы, ведь нет необходимости передавать данные по сети. Недостаток же состоит в том, что, когда кодовая база разрастается, и количество разработчиков увеличивается, поддерживать код монолитного бекенда становится всё сложнее и сложнее.
В микросервисном подходе модули приложения разделены по разным сервисам - то есть по сути разным приложениям, которые могут запускаться на разных серверных машинах. Общаются друг с другом микросервисы либо вызовами по сети, либо с помощью шины событий (event bus). Эта архитектура более медленная из-за взаимодействия модулей друг с другом по сети, более сложная в разработке, ведь необходимо деплоить и оркестировать множество модулей. Но в то же время микросервисы гораздо легче скейлить. Кроме того использование event bus позволяет использовать такие подходы как CQRS и event sourcing.
Фронтенд
При разработке фронтенда тоже используется два подхода:
Монолитное приложение
Микрофронтенды
Всё по аналогии с монолитом и микросервисами на бекенде. Но на фронтенде шинная архитектура используется и в других местах.
Во-первых, вся интерактивность в браузере построена на отправке и прослушивании событий. В любом месте кода можно как отправить любой ивент через window.dispatchEvent, так и подписаться на него через window.addEventListener.
Во-вторых, многие системы управления состоянием вроде Redux тоже представляют собой шину событий, которые редуцируют поток событий в текущее состояние подобно тому, как на бекенде при использовании event sourcing поток ивентов превращается в materialized view в базе данных.
Многопоточность
При разработке многопоточных систем тоже используется два подхода:
Ручное управление (философски ближе к монолитному подходу)
Акторы/корутины (шина)
При ручном управлении возможно выжать большую производительность, но разработка и отладка системы с семафорами, локами, волатильными переменными и прочими хитрыми инструментами превращается в ад.
При шинном подходе (акторы в Akka, корутины в Go) потоки обмениваются между собой информацией через сообщения по шине - производительность может быть не такой быстрой, но разработка и отладка в разы легче.
Факторио
На Хабре есть прекрасная серия статей про архитектуру разработки фабрики в игре Factorio:

В этих статьях автор рассказывает про то, как он строит фабрику в факторио: сначала с монолитной архитектурой, потом с микросервисной архитектурой без шины, а после с микросервисной архитектурой с шиной.
Заключение
Подводя итог, можно сказать, что монолитный подход к архитектуре почти всегда даёт преимущества в плане производительности, а модульный подход с шиной сообщений более ресурсозатратный, но более чистый, расширяемый и поддающийся отладке.
P. S.: в моём телеграм‑канале я не пишу про архитектуру ПО, но пишу про философию, математику и буддизм.
Комментарии (9)
tkutru
10.09.2025 15:50Да это просто извечный вопрос поиска "золотой середины". Сколько отдыхать, а сколько работать. Расти в знаниях вглубь или вширь. Насколько сильно изолированы должны быть транзакции в бд (надежность vs скорость). Компиляция vs интерпретация. Статическая vs динамическая типизация. Быстро-дешево-качественно - выбери два из трёх (CAP теорема Брюера туда же). Монолит vs микросервисы. И так далее.
И как правило это не выбор между одним либо другим, а выбор точки, которая насколько-то ближе к одному либо к другому.
SolidSnack
Так быстро от архитектуры ОС до фронтенда я еще не прыгал...
a-tk
Что лишь подтверждает общее в этих решениях.
SolidSnack
Как минимум код, а если серьёзно - на сколько я понял, микросервесная архитектура (ядра) в MINIX, отличается от Linux, способом взаимодействия программ с железом и между собой, но миниксу не надо поднимать сервера чтобы запустить процесс, у всех уже ассоциация - микросервис значит gRPC (чтобы всем говорить что у нас как в гугл), если уж говорить про веб разработку, например SSR делает SEO оптимизацию лучше, поэтому лучше не выносить все в браузер на JS
Ну и к слову, исторически, получается "монолит" победил ;)
a-tk
Монолит проще и надёжнее, и нет смысла делать мелкосервисы, если не доказана их необходимость.
PS: проектирование любой системы с микросервисов очень напоминает разработку мелкой консольной утилитки на Java с написания фабрик фабрик.