SOFA (масштабируемая открытая финансовая архитектура)
Это распределенное промежуточное программное обеспечение финансового уровня, независимо разработанное Ant Financial. Оно включает в себя различные компоненты, необходимые для создания облачной архитектуры финансового уровня. Это лучшая практика, адаптированная к финансовым сценариям.
SOFABoot — это среда разработки на основе Spring Boot, исходный код которой открыт группой Ant Financial Middleware. Начиная с версии 2.4.0 SOFABoot поддерживает возможности модульной разработки на основе изоляции контекста Spring. Модуль SOFABoot включает не только код Java, но и конфигурацию Spring. files. , каждый модуль SOFABoot представляет собой отдельный контекст Spring.
Адрес SOFABoot на Github:
https://github.com/alipay/sofa-boot
Ловушки традиционной модульности
Прежде чем представить модульность SOFABoot, давайте еще раз рассмотрим недостатки традиционной модульности.Модульность бизнес-системы Ant Financial ---- Модульное решение для изоляции.
В простой системе Spring/SpringBoot мы часто видим, что модули системы располагаются следующим образом: как показано в левой части рисунка ниже, система просто делится на веб-уровень и сервисный уровень. слой ДАЛ.
Когда эта система предоставляет больше услуг, система может развиваться так, как показано справа на рисунке выше. В правой части приведенного выше рисунка система несет две службы, одна из которых — Кассир (кассир), а другая — Плата (оплата).Эти две службы могут иметь некоторые зависимости, и Кассиру необходимо вызвать Pay, чтобы предоставить возможность совершать платежи. .
Но в этом модульном решении контекст Spring все тот же, а классы не изолированы, что означает, что любой bean-компонент в модуле Pay Service может зависеть от модуля Cashier Service. В крайнем случае могут возникнуть следующие ситуации:
Cashier Service ошибочно назвал внутренний bean-компонент в Pay Service, что привело к тесной связи между двумя модулями.
Проблема с этой традиционной модульностью заключается в том, что модульность не является полной. Хотя во время разработки путем разделения модулей и помещения классов с определенными обязанностями в конкретные модули достигается связность «физического расположения» классов. Однако во время выполнения, поскольку нет средств изоляции, разработчик модуля не может четко знать, что такое внешний интерфейс, предоставляемый другим модулем, какие bean-компоненты я могу внедрить напрямую, а какие bean-компоненты — это ваш внутренний Bean-компонент. , я не могу его использовать. В долгосрочной перспективе связь между модулями будет становиться все более и более серьезной, и первоначальное разделение модулей бесполезно. Когда система становится все больше и больше, и, наконец, нужно выполнить разделение сервисов, ей нужно потратить много энергии, чтобы разобраться в отношениях между модулями.
Введение в модульность SOFABoot
Чтобы решить проблему неполной модульности в традиционной схеме модульности, SOFABoot поддерживает возможность модульности на основе изоляции контекста Spring, начиная с версии 2.4.0.Каждый модуль SOFABoot использует независимый контекст Spring, каждый модуль автономен, а модули Общаются через службу JVM, чтобы избежать тесной связи между модулями:
Как видно из приведенной выше схемы архитектуры системы, модульность SOFABoot включает в себя три основных понятия, а именно модуль SOFABoot, службу JVM и контекст корневого приложения:
Модуль SOFABoot: модуль SOFABoot представляет собой общий пакет Jar, включающий код Java, файл конфигурации Spring, идентификатор модуля SOFABoot и другую информацию. Каждый модуль SOFABoot представляет собой независимый контекст Spring.
Служба JVM: после изоляции контекста bean-компоненты между модулями не могут быть внедрены напрямую.Служба JVM используется для реализации межмодульной связи, а также для публикации и ссылки на службы модуля.
Контекст корневого приложения: Контекст Spring, сгенерированный приложением SOFABoot, вызывающим метод SpringApplication.run(args), является родителем всех модулей SOFABoot.
В следующей части этой статьи будут представлены поиск и обновление модуля SOFABoot, служба JVM и управление компонентами, а также основные концепции корневого контекста приложения, а затем кратко представлены Require-Module, Spring-Parent и параллельный запуск модуля SOFABoot, а также наконец Дает практические советы по модульной разработке.
Найдите и обновите модуль SOFABoot.
Схема последовательности поиска и обновления модуля SOFABoot выглядит следующим образом:
В SOFABoot мы определяем SofaModuleContextRefreshedListener, который прослушивает событие ContextRefreshedEvent, отправленное корневым контекстом приложения, и выбирает реакцию на это событие по следующим двум соображениям:
ContextRefreshedEvent — это стандартное событие Spring, которое носит более общий характер.
Для обновления модуля SOFABoot необходимо дождаться обновления контекста корневого приложения, поскольку модуль SOFABoot может зависеть от определений bean-компонентов в контексте корневого приложения.
После того, как SofaModuleContextRefreshedListener прослушает событие ContextRefreshedEvent, он создаст объект PipelineContext, и в PipelineContext будут добавлены три этапа: ModelCreatingStage, SpringContextInstallStage и ModuleLogOutputStage. Функции трех этапов следующие:
ModelCreatingStage: найти все действительные модули SOFABoot в текущем ClassPath;
SpringContextInstallStage: SOFABoot для каждого модуля, чтобы найти новый контекст Spring, модуль загрузки файла конфигурации SOFABoot Spring;
MODULOGOUTPUTSTAGE: выводит все модули Sofaboot, которые были обновлены и обновлены, чтобы пользователи могли быстро найти проблемы.
Вызов метода процесса PipelineContext приведет к последовательному выполнению этих трех этапов и обновлению всех модулей SOFABoot, содержащихся в текущем ClassPath.
Служба JVM и управление компонентами
После изоляции контекста bean-компоненты между модулями не могут быть внедрены напрямую.JVM Service используется для реализации межмодульной связи, а также для публикации и ссылки на сервисы модулей.
Чтобы обеспечить межмодульное обнаружение сервисов, мы определяем интерфейс управления компонентами ComponentManager внутри SOFABoot:
public interface ComponentManager {
/**
* register component in this manager
*
* @param componentInfo component that should be registered
*/
void register(ComponentInfo componentInfo);
/**
* get concrete component by component name
*
* @param name component name
* @return concrete component
*/
ComponentInfo getComponentInfo(ComponentName name);
}
ComponentInfo — это интерфейс, используемый для представления информации о компонентах.В настоящее время он содержит две конкретные реализации, ServiceComponent и ReferenceComponent, которые представляют службы и ссылки соответственно. ComponentName — это уникальный идентификатор ComponentInfo, используемый для различения различных реализаций ComponentInfo.
Класс реализации ComponentManager содержит Map с ComponentName в качестве ключа и ComponentInfo в качестве значения для хранения всех зарегистрированных ComponentInfo:
public class ComponentManagerImpl implements ComponentManager {
/** container for all components */
protected ConcurrentMap<ComponentName, ComponentInfo> registry;
// other definition
}
При публикации службы JVM мы будем вызывать метод register для регистрации службы JVM в ComponentManager.Когда происходит вызов службы, мы будем вызывать метод getComponentInfo для поиска и вызова служб, опубликованных другими модулями в ComponentManager.
Root Application Context
SOFABoot является расширением Spring Boot. Приложение SOFABoot запускается с помощью метода SpringApplication.run(args).После вызова этого метода приложение сгенерирует контекст Spring, который мы называем корневым контекстом приложения. Контекст корневого приложения — это особый элемент модульной структуры SOFABoot. Он является родительским для каждого контекста модуля SOFABoot. bean-компоненты определены, и эти bean-компоненты будут действовать только в корневом контексте приложения по умолчанию. Готов к использованию.
В дополнение к определению некоторых bean-компонентов Starter может также определить некоторые BeanPostProcessor и BeanFactoryPostProcessor.Для этих двух типов специальных определений bean-компонентов подконтексту недостаточно найти определения bean-компонентов.Определения этих двух типов bean-компонентов должны быть скопированы в текущий контекст, чтобы он вступил в силу, поэтому при обновлении контекста, соответствующего модулю SOFABoot, мы скопируем все BeanPostProcessors и BeanFactoryPostProcessors, определенные в корневом контексте приложения, в контекст модуля SOFABoot, чтобы некоторые процессоры, определенные Starter может быть непосредственно использован в контексте модуля SOFABoot, например, runtime-ServiceAnnotationBeanPostProcessor будет определен в Sofa-boot-starter. Этот класс в основном используется для реализации службы публикации аннотаций. После автоматического копирования, пока runtime-sofa-boot-starter добавлена зависимость, она поддерживает службу публикации на основе аннотаций в модуле SOFABoot.
Require-Module, Spring-Parent и параллельные модули запуска
При обновлении модуля SOFABoot в модуле A может быть опубликована служба JVM, которую необходимо вызвать в методе init компонента в модуле B. Если предположить, что модуль B запускается до модуля A, то компонент модуля B будет запущен. be Инициализация завершится ошибкой, потому что служба JVM модуля A не выпущена, что приведет к сбою запуска контекста Spring. На этом этапе мы можем указать Require-Module в диван-модуле.properties, чтобы заставить модуль A запускаться раньше модуля B.
В приложении SOFABoot каждый модуль SOFABoot является независимым контекстом Spring, и эти контексты Spring изолированы друг от друга. Хотя такой модульный подход может дать много преимуществ, он все же будет неудобен в некоторых сценариях.В настоящее время вы можете использовать Spring-Parent, чтобы открыть контекст Spring двух модулей SOFABoot. Например, модуль DAL можно использовать в качестве родительского модуля службы, чтобы модуль службы мог напрямую использовать определение источника данных, определенное модулем DAL, без публикации источника данных в качестве службы JVM.
SOFABoot рассчитает дерево зависимостей модулей в соответствии с Require-Module и Spring-Parent. Например, следующее дерево зависимостей указывает, что модуль B и модуль C зависят от модуля A, модуль E зависит от модуля D, а модуль F зависит от модуля E. :
Дерево зависимостей гарантирует, что модуль A должен запускаться перед модулем B и модулем C, модуль D начинается перед модулем E, а модуль E начинается перед модулем F, но дерево зависимостей не определяет модуль B и модуль C, модули B, C и модули Последовательность запуска между D, E и F, эти модули могут запускаться последовательно или параллельно. SOFABoot по умолчанию запускает модули параллельно, что может значительно увеличить скорость запуска приложения.
Практические советы
Каждый модуль SOFABoot использует независимый контекст Spring, и модули взаимодействуют друг с другом через службу JVM.При публикации сервисов мы рекомендуем публиковать сервисы в сервисном измерении, подобно использованию RPC, предоставляя пакет Facade, включая определения интерфейса, затем модуль реализует интерфейс и публикует сервис.
Некоторые реализации не подходят для определения в модуле SOFABoot, например определение контроллера. Определение контроллера является реализацией уровня представления, а модуль SOFABoot относится к бизнес-уровню. Мы не рекомендуем и не поддерживаем определение контроллера компоненты в модуле SOFABoot. Определение компонента контроллера рекомендуется размещать в корневом контексте приложения. Если компоненту контроллера необходимо вызвать службу, опубликованную модулем SOFABoot, он может напрямую использовать аннотацию для ссылки на службу. Конкретные примеры см.Практика | Модульная разработка на базе SOFABootпример в .
Некоторые модули не подходят для определения в качестве модуля Sofaboot, например, модуль UTIL или модуль FACADE, первый в основном определяет некоторые классы инструментов, последний в основном определяет некоторые сервисные интерфейсы и не включает публикацию и ссылку на сервис. Не рекомендуется определять эти модули как модуль Sofaboot.
Суммировать
В этой статье в основном представлен принцип реализации модуляризации SOFABoot и основное внимание уделяется трем важным концепциям модульности SOFABoot: поиску и обновлению модуля SOFABoot, управлению службами и компонентами JVM, а также основным концепциям корневого контекста приложения. помочь пользователям быстро понять принцип реализации модуляризации SOFABoot. После анализа принципов в конце статьи мы также даем практические советы, которые помогут пользователям быстро приступить к работе с модуляризацией SOFABoot.
В статье упоминается:
Открытый исходный код | Интеграция возможностей изоляции класса SOFABoot в Spring Boot
Открытый исходный код | Анализ принципа изоляции класса SOFABoot
Модульность бизнес-системы Ant Financial ---- Модульное решение для изоляции
Нажмите и удерживайте кнопку «Подписаться», чтобы получить распределенную архитектуру сухих товаров.
Добро пожаловать на сборку SOFAStack вместе https://github.com/alipay