Статьи

Состав сервисов: модульность для SOA и событийно-ориентированных приложений, часть I

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

В этой серии статей я расскажу о том, как были построены модульные архитектуры для двух различных приложений на основе Java: высоконадежной платформы обработки налогов SOA, которая взаимодействует с унаследованными системами; и система с низкой задержкой, основанная на событиях, для торговли валютой FX. Была достигнута модульность OSGi, Service Component Architecture (SCA) и Fabric3 в качестве стека времени выполнения.

Этот пост начнется с краткого обзора технологий, используемых при создании этих модульных систем, и перейдет к подробному обсуждению того, как они использовались для создания платформы налоговой обработки SOA для европейского правительства. В следующем посте мы расскажем о том, как были применены те же методы модульности, чтобы успешно доставлять торговую архитектуру FX с низкой задержкой в ​​крупный банк.

От OSGi к составу сервиса

Нет ни одной технологии, которая бы предлагала полное модульное решение. Это потому, что модульность предоставляет ряд функций и существует на нескольких уровнях в приложении. С точки зрения возможностей, модульность:

  • Уменьшает сложность , сегментируя код на отдельные единицы
  • Предоставляет механизм для изменения , позволяя компонентам приложений быть версионными
  • Способствует повторному использованию путем определения контрактов между подсистемами

Модульность также присутствует на разных уровнях приложения:

slide1 Модульность приложения

Хотя большая часть приведенной выше диаграммы будет знакома разработчикам Java, стоит определить, что мы подразумеваем под композицией сервисов и архитектурной модульностью. Сервис-ориентация (организация логики приложения в контрактные модули) и внедрение зависимостей (популяризируемые, среди прочего, такими платформами, как Spring и Guice) являются основой современной архитектурной модульности. В двух словах, обе помогают разделить подсистемы, что делает приложение более модульным.

Чего не хватает, так это архитектурной инкапсуляции и композиции. Например, приложениям часто необходимо предоставлять грубые сервисы, которые сами состоят из множества сервисов поиска. Традиционные интеграционные платформы, ESB и Java EE не имеют средств, позволяющих сделать это простым и эффективным способом. Возможно, вы видели это с распространением сервисов, предоставляемых через контексты приложений Enterprise Service Bus (ESB) или Spring, которые содержат сотни или даже тысячи компонентов.

Как и в случае с объектно-ориентированной ориентацией, необходим способ группировки наборов сервисов для лучшего управления и механизм инкапсуляции деталей реализации конкретных сервисов:

slide2
Модульность обслуживания

Fabric3 предоставляет такой механизм компоновки, который хорошо работает как для SOA, так и для проектов, управляемых событиями. Теперь я перейду к тому, как это было достигнуто в системе обработки налогов и платформе FX Trading.

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

SOA Модульность

Архитектура налоговой системы выглядит так:

slide3
Архитектура налоговой системы

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

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

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

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

На что эта модульность перевела на практике? Среда разработки была настроена как многомодульная сборка Maven. Модули базового API содержат интерфейсы Java для различных сервисов. Отдельные модули для обработки ядра, правил и интеграции зависят от соответствующих модулей API:

Модули налоговой системы

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

Slide4
OSGi Импорт и экспорт

Налоговая система использует состав услуг для обеспечения модульности на уровне обслуживания. Базовая обработка, правила и подсистемы интеграции состоят из множества детализированных сервисов. В частности, подсистема интеграции предоставляет единый интерфейс для приема запросов от основного модуля обработки. Этот запрос затем передается через серию сервисов, которые вызывают устаревшие системы с использованием веб-сервисов (WS- *):

Slide6
Модуль интеграции налоговой системы

Состав службы обрабатывается в Fabric3 с помощью SCAcomposites . Подобно контексту приложения Spring, составной набор определяет набор компонентов и их связку. В этом примере мы используем XML для определения композита (следующая версия Fabric3 также будет поддерживать DSL на основе Java ):

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<composite name="IntegrationComposite" …>
        <service name="TaxSystem" promote="TaxSystem"/>
        <component name="TaxSystem>
                <implementation.java class="…"/>
                <reference name="idprocessor" target="IdProcessor"/>
        <component/>
 
        <component name="IdProcessor">
                <implementation.java class="…"/>
                <reference name="locationProcessor" target="LocationProcessor"/>
 
                <reference name="legacySystem">
                        <binding.ws uri="…."/>
                </reference>
        </component>
 
        <component name="LocationProcessor >
                <implementation.java class="…"/>
                <reference name="dataProcessor" target="DataProcessor"/>
                <reference name="legacySystem">
                        <binding.ws uri="…."/>
                </reference>
        </component>
                … other components …
</composite>

Компонент модуля интеграции

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

Продвижение услуг

Когда это сделано, клиентские сервисы в модуле основной обработки могут ссылаться на композит интеграции TaxSystem как на единый сервис:

1
2
3
4
<component name="MessageProcessor">
        <implementation.java class=".."/>
        <reference name="taxSystem" target="IntegrationComposite"/>
<component> 

При наличии композитов налоговая система успешно предоставила согласованный модульный дизайн от уровня кода до своей сервисной архитектуры:

Модульность сервисной архитектуры

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

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