Главная

Шаблон проектирования микросервисов: Dependency Driven Decomposition.

DDD – декомпозиция, управляемая зависимостями

578 

6+

При построении больших систем требуется интеграция с библиотеками и сторонними API-интерфейсами. Можно найти большое количество пользовательских SDK (с англ. software development kit: набор средств разработки), которые берут на себя основную часть работы по интеграции. Они также предоставляют множество функциональных возможностей, которые вам, вероятно, не нужны. Тем не менее, код (и его зависимости!) все еще дремлют на ваших серверах. Это приводит к длительным сборкам, медленному “холодному” запуску, сложным настройкам проекта и широкой подверженности уязвимостям безопасности.

На клиентской стороне эта проблема решается с помощью “встряхивания дерева” веб-пакета (с англ. webpack`s tree shaking). Суть данного метода состоит в связывании только того кода, который непосредственно используется вашим приложением. На стороне клиента такое решение оправдывается, но на серверной части оно не оптимизировано.
В бессерверном мире пакеты и инфраструктурные зависимости устанавливаются и кэшируются на уровне контейнеров, но при каждом выполнении создается новый процесс, в котором выполняется обработчик функции. Это означает, что для каждого выполнения функции все синхронно импортированные модули должны быть оценены и выполнены, и все соединения инициализации db (база данных | с англ. database) и обращения к db должны произойти до того, как запуститься бизнес-логика приложения.

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

Leaner сборки также означают более быструю непрерывную интеграцию/непрерывную поставку (CI/CD), что означает, что разработчики тратят меньше времени на сборку и больше на решение проблем. У вас есть десятки сборок, работающих параллельно — тогда получается, что каждый раз, когда вы избавляетесь от базовых показателей запуска контейнера, эффективность повышается.

Теперь речь идет не только о CI/CD, но и о времени разработки и времени тестирования. При одновременном импорте большого количества пакетов NPM время холодного запуска вашего приложения сводится на нет.
Хотите использовать nodemon в процессе разработки? Забудьте. Если вам нужно ждать 5–10 секунд для запуска приложения, вы не сможете запускать приложения локально в режиме просмотра.


Хотите использовать jest вместо mocha? Нет. Mocha выполняет тесты синхронно и использует кэш встроенного модуля узла, поэтому импорт нужно делать только один раз. С Jest каждый пакет запускает новый процесс, который сразу запускает все резолюции модулей и блокирует процессор.

Есть несколько решений этой проблемы, например ленивая оценка(с англ. lazy evaluation), но даже в таком случае во время выполнения все зависимости должны быть включены — в какой-то момент вы заплатите за это “железную цену”. Это очень актуальная проблема для JavaScript, особенно при бессерверном подходе. Итак, я хочу выделить и представить другой шаблон, который я узнал по счастливой случайности. Я решил назвать его «Dependency Driven Decomposition» или DDD.

Извлечение компонентов без состояния (с англ. stateless) с высокой степенью связности, низким сцеплением и “дорогостоящими” зависимостями в бессерверных функциях. Удвойте основной домен и сохраняйте его сфокусированным. Абстрагируйтесь от придатков.

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

Давайте рассмотрим пример:

Генерация PDF. Какое-то время мы использовали PhantomJS. Phantom требовал установки и запуска независимого бинарного файла на компьютере, а затем клиентской библиотеки для возможности доступа к нему с помощью NodeJs. Позже PhantomJS устарел, и предпочтительной библиотекой для создания PDF-файлов стал wkhtmltopdf, который имел также бинарный файл. В какой-то момент на нашем репозитории были все четыре пакета, которые в то время оказались единственными установленными пакетами, которые требовали перекомпиляции собственных двоичных файлов при установке — это добавляло весомые 45 секунд к нашей сборке (к каждой сборке на тест-контейнер!) для общего количества 2 эндпоинтов, которые очень редко используются. Это только один из многих компонентов, которые мы смогли вынести из ядра, чтобы ускорить время сборки и ускорить разработку.
Опять же — суть этого шаблона заключается в том, что зависимости должны полагаться на основные сервисы. Обменяйте сетевой скачок на «нишевые компоненты» в вашем облаке для увеличения скорости разработки. Однако мы все знаем о снижении доступности, когда речь идет о синхронно связанных микросервисах.
Спасибо!

Источник

6+